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.48k stars 4.56k forks source link

Unable to modify an RBAC Owner-role with constraints: "CannotDeleteLastRbacAdminAssignment" error shown #26122

Open knuterik-ballestad opened 1 month ago

knuterik-ballestad commented 1 month ago

Is there an existing issue for this?

Community Note

Terraform Version

= 1.8.4

AzureRM Provider Version

~> 3.104.2

Affected Resource(s)/Data Source(s)

azurerm

Terraform Configuration Files

# Called in loop, once per subscription/LZ configuration:
resource "azurerm_role_assignment" "owner_role" {
  for_each             = var.sub_owners                                 # Typically *one* person
  scope                = "/subscriptions/${var.sub_id}"
  role_definition_name = "Owner"
  principal_id         = each.value
  # Inserted ARM template JSON for constraining the "Owner" role
  condition_version = "2.0"
  condition         = <<-EndOfInsertedJSON
    (
      (!(ActionMatches{'Microsoft.Authorization/roleAssignments/write'}))
      OR
      (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId]
        ForAnyOfAnyValues:GuidEquals {${join(", ", values(local.owner_available_role_delegations)[*].role_id)}})
    )
    AND
    (
      (!(ActionMatches{'Microsoft.Authorization/roleAssignments/delete'}))
      OR
      (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId]
        ForAnyOfAnyValues:GuidEquals {${join(", ", values(local.owner_available_role_delegations)[*].role_id)}})
    )
  EndOfInsertedJSON
}

Debug Output/Panic Output

│ Error: authorization.RoleAssignmentsClient#Delete: Failure responding to request: StatusCode=412 -- Original Error: autorest/azure: Service returned an error. Status=412 Code="CannotDeleteLastRbacAdminAssignment" Message="Cannot delete the last RBAC admin assignment"

Expected Behaviour

We expect terraform to either be able to modify the role assignment or fail gracefully.

Actual Behaviour

Terraform removes Owner from all ALZ-subscriptions, and THEN fails in a state that doesn't even let us re-run TF to apply the role assignmens again.

Steps to Reproduce

image This image shows in the Portal what we are trying to do (adding or removing "Constrain roles"), meaning what roles the Owner are allowed to assign to others.

Important Factoids

No response

References

No response

knuterik-ballestad commented 1 month ago

Before upgrading to latest azurerm+terrform runtime, terraform failed "gracefully", allowing us to re-run the github action with the terraform apply - and then the role assignments was re-created with the correct, updated constraints.

magodo commented 1 month ago

@knuterik-ballestad Presumably, the loop in your case covers all the original owners, including the principal that is running terraform. Also, assuming your workspace has kept track of all these principals' states, when your change introduce a "replace", terraform will remove the role assignments prior creating the new ones. That's why you saw the error.

If above assumption holds, it looks like a "shoot yourself in the foot" case. My suggestion is to at least keep the principal that runs terraform not included in the sub_owners.

knuterik-ballestad commented 1 month ago

@knuterik-ballestad Presumably, the loop in your case covers all the original owners, including the principal that is running terraform. Also, assuming your workspace has kept track of all these principals' states, when your change introduce a "replace", terraform will remove the role assignments prior creating the new ones. That's why you saw the error.

If above assumption holds, it looks like a "shoot yourself in the foot" case. My suggestion is to at least keep the principal that runs terraform not included in the sub_owners.

Well, the principal that runs terraform, and certain admin users are set as Owners in the management structure, and not directly on the subscription - though the subscription inherits these Owners of course.

Our script only assigns one Owner directly to the subscription - the requester of a subscription to be created. That is why terraform has trouble when updating the Owner's constraint - because instead of just adding a constraint the whole role assignment is:

  1. Removed (this is where terraform fails)
  2. Re-applied with the additional constraint

So, if terraform could check also inherited Owners, and not only directly assigned, this would be solved.