Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_role_assignment "The role assignment already exists." #17421

Open
1 task done
justin-chizer opened this issue Jun 28, 2022 · 13 comments
Open
1 task done

azurerm_role_assignment "The role assignment already exists." #17421

justin-chizer opened this issue Jun 28, 2022 · 13 comments

Comments

@justin-chizer
Copy link

justin-chizer commented Jun 28, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform Version

1.2.3

AzureRM Provider Version

3.11

Affected Resource(s)/Data Source(s)

azurerm_role_assignment

Terraform Configuration Files

resource "azurerm_role_assignment" "aks" {
  scope              = data.azurerm_virtual_network.vnet.id
  role_definition_id = "/subscriptions/${var.subscription_id}/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7" # Network Contributor
  principal_id       = data.azurerm_user_assigned_identity.mi.principal_id
}

Debug Output/Panic Output

Terraform will perform the following actions:
  # module.kubernetesplat.azurerm_role_assignment.aks will be created
+ resource "azurerm_role_assignment" "aks" ***
+id                               = (known after apply)
+name                             = (known after apply)
+principal_id                     = ""
+principal_type                   = (known after apply)
+role_definition_id               = "/subscriptions/***/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
+role_definition_name             = (known after apply)
+scope                            = "/subscriptions/***/resourceGroups/***/providers/Microsoft.Network/virtualNetworks/***"
+skip_service_principal_aad_check = (known after apply)
    ***



Error: authorization.RoleAssignmentsClient#Create: Failure responding to request: StatusCode=409 -- Original Error: autorest/azure: Service returned an error. Status=409 Code="RoleAssignmentExists" Message="The role assignment already exists."

Expected Behaviour

Terraform should know that the Network Contributor role is already assigned to the AKS cluster that was created but it does not even know its there. It exists in the state file.

Actual Behaviour

terraform plan output says a new resource will be created.
terraform apply says resource already exists and throws a 409

Steps to Reproduce

Have a Network Contributor role assignment to a VNet and run terraform apply twice. Once to create the role and the next to throw the error.

Important Factoids

No response

References

There are similar issues but they all show Terraform trying to modify the resource not create a new one.
This is also a role to a VNet.

@github-actions github-actions bot removed the bug label Jun 28, 2022
@sinbai
Copy link
Contributor

sinbai commented Jun 29, 2022

@justin-chizer thanks for opening this issue here. Unfortunately, I could not reproduce this issue by running terraform apply twice with the following terraform configuration. Could you reproduce with it?


terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.11.0"
    }
  }
}

provider "azurerm" {
  features {
  }
}

data "azurerm_client_config" "test" {
}

resource "azurerm_resource_group" "example" {
  name     = "rg-example"
  location = "eastus"
}

resource "azurerm_virtual_network" "example" {
  name                = "network-example"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  address_space       = ["10.1.0.0/16"]
}

resource "azurerm_role_assignment" "test" {
  scope                = azurerm_virtual_network.example.id
 role_definition_id =  "/subscriptions/***/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
  principal_id         = data.azurerm_client_config.test.object_id
}

@pmav99
Copy link

pmav99 commented Jul 2, 2022

@sinbai Your example works, but I can reproduce using the following example, i.e. trying to assign the Contributor role to Microsoft Azure Batch (which seems to be necessary for "User Subscription Mode") :

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.11.0"
    }
  }
}

provider "azurerm" {
  features {
  }
}

data "azurerm_subscription" "this" {
}

data "azurerm_client_config" "test" {
}

resource "azurerm_role_assignment" "example" {
  scope                = data.azurerm_subscription.this.id
  role_definition_name = "Contributor"
  # https://portal.azure.com/#view/Microsoft_AAD_IAM/ManagedAppMenuBlade/~/Overview/objectId/788b2cad-5d5b-4046-8167-9cef6f46ac02/appId/ddbf3205-c6bd-46ae-8127-60eb93363864
  principal_id         = "788b2cad-5d5b-4046-8167-9cef6f46ac02"
}

The error is:

azurerm_role_assignment.example: Creating...
╷
│ Error: authorization.RoleAssignmentsClient#Create: Failure responding to request: StatusCode=409 -- Original Error: autorest/azure: Service returned an error. Status=409 Code="RoleAssignmentExists" Message="The role assignment already exists."
│ 
│   with azurerm_role_assignment.example,
│   on main.tf line 23, in resource "azurerm_role_assignment" "example":
│   23: resource "azurerm_role_assignment" "example" {
│ 

@adansmashni
Copy link

adansmashni commented Jul 29, 2022

Same Error.

resource "azurerm_role_assignment" "all-ids-reader" {
depends_on = [var.myobjids]
for_each = toset(var.myobjids)
scope = "${data.azurerm_storage_account.sa.id}"
role_definition_name = "Storage Blob Data Reader"
principal_id = each.key
}

@haleemason
Copy link

haleemason commented Aug 18, 2022

I am having this same error today when trying to run the pipeline in the terraform apply step:

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"
azurerm_role_assignment.rg_assign: Creating...
azurerm_role_assignment.storage_identity_contributor_lca: Creating...
azurerm_role_assignment.storage_identity_contributor_gip: Creating...
azurerm_role_assignment.storage_account_identity_contributor_gip: Creating...

│ Error: authorization.RoleAssignmentsClient#Create: 
 Failure responding to request: StatusCode=409 -- Original Error: autorest/azure:
 Service returned an error. Status=409 Code="RoleAssignmentExists"
 Message="The role assignment already exists."
│ 
│   with azurerm_role_assignment.storage_account_identity_contributor_gip,
│   on terraform.tf line 429, in resource "azurerm_role_assignment" "storage_account_identity_contributor_gip":
│  429: resource "azurerm_role_assignment" "storage_account_identity_contributor_gip" {
│ 

It fails on all these azurerm_role_assignment steps (there are 4 roles to assign as role_definition_name = "Storage Queue Data Contributor" or role_definition_name = "Contributor")

From terraform.tf:

# Add service principal roles
resource "azurerm_role_assignment" "storage_account_identity_contributor_gip" {
  scope                = azurerm_storage_account.az_sa.id
  role_definition_name = "Storage Account Contributor"
  principal_id         = data.azuread_service_principal.az_sp_gip.object_id
}

Is there any recommended solution to fix this?

Edit: I also tried manually going into Azure Portal and removing the Service Principal role assignments from the resource group and then re-running the pipeline, but this did not work.

@benc-uk
Copy link
Contributor

benc-uk commented Sep 29, 2022

Same problem assigning the Managed Identity Operator role to an AKS cluster
This is required for pod identity to work

resource "azurerm_role_assignment" "mi_operator" {
  scope                = azurerm_user_assigned_identity.iommi_user_api.id
  role_definition_name = "Managed Identity Operator"
  principal_id         = azurerm_kubernetes_cluster.aks.identity[0].principal_id
}

Results in

Error: authorization.RoleAssignmentsClient#Create: Failure responding to request: StatusCode=409 -- Original Error: autorest/azure: Service returned an error. Status=409 Code="RoleAssignmentExists" Message="The role assignment already exists."

@Azkel
Copy link

Azkel commented Oct 17, 2022

I had some time to investigate what's happening with that error:

Before executing the API call to create resources, azurerm checks if the role assignment already exists. But it does so only based on name property, not doing any checks based on role_definition_name/role_definition_id. If this name is not provided, it is generated on-the-go and used to deploy main application.

Which makes a possible workaround of generating this name yourself and providing it to resource definition, thanks to which you solve the problem. name is not optional in this scenario.

Proper solution should be checking if role assignment with the same roleDefinitionId already exists (role name is resolved to role ID at the very beginning of execution) during the existence check, probably only in case name is not provided and role_definition_name or role_definition_id is provided.

I will try to provide that kind of solution in upcoming weeks (depending on my free time unfortunatelly), so people waiting for the fix - hopefully soon it should be resolved.

@Azkel
Copy link

Azkel commented Oct 29, 2022

Unfortunately I am not able to reproduce the behaviour anymore - probably in the meantime some other changes fixed the issue.

My test Terraform declaration:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.29.1"
    }
  }
}
provider "azurerm" {
  features {
  }
}
 
data "azurerm_subscription" "primary" {
}

data "azurerm_client_config" "example" {
}
 
resource "azurerm_role_assignment" "example" {
  scope                = data.azurerm_subscription.primary.id
  role_definition_name = "Reader"
  principal_id         = "e3f01abb-e6c8-44d9-9307-7171031781c4
}

409 error is still thrown if you create Role Assignment outside of Terraform and then run terraform apply. If that's the case, you need to get proper id of the assignment via azure role assignment command. In my example above it would be /subscriptions/2c6cce2d-c9df-4f41-9133-fc2da450bb30/providers/Microsoft.Authorization/roleAssignments/bb65ac5b-ba76-41c3-b7a4-b64371bb13fe (GUID at the end of this id was not visible in Azure Portal) and add it via standard command

terraform import azurerm_role_assignment.example /subscriptions/2c6cce2d-c9df-4f41-9133-fc2da450bb30/providers/Microsoft.Authorization/roleAssignments/bb65ac5b-ba76-41c3-b7a4-b64371bb13fe

In case I created role assignment via Terraform itself, it was properly added to tfstate and processed in further runs via terraform apply/plan/destroy as expected. @justin-chizer, could you verify if it works for you as well now? I used the current main codebase, which probably corresponds to 3.29.1 version of azurerm provider.

@SSanjeevi
Copy link

SSanjeevi commented Jul 6, 2023

We are facing the same issue, any updates or fixes for this?
This happens whenever we update some fields in apigroup or other fields and it tries to create new role binding and failing. NOTE: i haven't changed name or id.

@ramvem
Copy link

ramvem commented Nov 14, 2023

Seeing these with managing ACL entries to storage account, container registry with hashicorp/azurerm 3.75.0

In terraform we have azurerm_role_assignment as named resources, but it seems they don't map to named resources on azure side to be able to do a terraform import.

@justinmchase
Copy link

I am having this issue where the assignment is created but then the state file failed to upload due to some unrelated error.

Trying to deploy a second time emits this error but it lacks the azure resource id of the role binding that already exists so there is no way for me to import it into the state file.

The only option is to delete the existing role binding and try again but without knowing what the resource id is of the role binding it is absolutely excruciating to debug.

@justinmchase
Copy link

I want to follow up on this because this is an incredibly painful issue that is still plauging us and we would really like to see this issue getting some attention.

Specifically the simplest thing that could be done would be to simply modify the error message to contain the resource id.

In this case the error message may look something like this:

╷
│ Error: authorization.RoleAssignmentsClient#Create: Failure responding to request: StatusCode=409 -- Original Error: autorest/azure: Service returned an error. Status=409 Code=""RoleAssignmentExists"" Message=""The role assignment already exists.""
│ 
│   with module.synapse_analytics.azurerm_role_assignment.blob_contributor_managed_identity,
│   on .terraform/modules/synapse_analytics/add_ons/synapse_analytics/main.tf line 62, in resource ""azurerm_role_assignment"" ""blob_contributor_managed_identity"":
│   62: resource ""azurerm_role_assignment"" ""blob_contributor_managed_identity"" ***
│ 
╵

But for all other resources when the resource already exists it looks like this:

╷
│ Error: A resource with the ID ""/subscriptions/0816a7b7-daf6-4f6a-8d35-0297a9da1f73/resourceGroups/sample-app-shared-sharedpr71"" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for ""azurerm_resource_group"" for more information.
│
│   with module.shared.module.resource_group.azurerm_resource_group.this,
│   on .terraform/modules/shared/shared/resource_group/main.tf line 1, in resource ""azurerm_resource_group"" ""this"":
│    1: resource ""azurerm_resource_group"" ""this"" {
│
╵

You'll notice in the latter error message it contains both the Resource ID as well as the terraform module path. Using these two data points I can do any of the following:

  • import the already existing resource
  • easily use the azurecli to delete the existing resource
  • have enough information to debug whats going on

But lacking the resource id it makes this nearly impossible to do any of the above. So please at the very least alter the error to contain the resource id of the already existing resource.

@mybesttools
Copy link

Terraform has detailed logs that you can enable by setting the TF_LOG environment variable to any value. Enabling this setting causes detailed logs to appear on stderr. see https://developer.hashicorp.com/terraform/internals/debugging

@justinmchase
Copy link

Does it print out the resource id in this case and can it be updated to print out the resource id by default in this case? Of course setting the TF_LOG variable has a lot of other side effects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests