hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.6k stars 4.64k forks source link

azurerm_role_assignment "The role assignment already exists." #17421

Open justin-chizer opened 2 years ago

justin-chizer commented 2 years ago

Is there an existing issue for this?

Community Note

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.

sinbai commented 2 years ago

@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 commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 1 year ago

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 commented 12 months ago

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 commented 3 months ago

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.