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

Namespace-level role assignments are created on resource group level #408

Open
joachimnielandt opened this issue Mar 22, 2024 · 2 comments

Comments

@joachimnielandt
Copy link

Hello all,

I am currently experiencing a peculiar problem, where the namespace role assignments (

resource maMicrosoftEntraA0008ReaderGroupClusterReaderRole_roleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = if (isUsingAzureRBACasKubernetesRBAC && !(empty(a0008NamespaceReaderMicrosoftEntraGroupObjectId)) && (!(a0008NamespaceReaderMicrosoftEntraGroupObjectId == clusterAdminMicrosoftEntraGroupObjectId))) {
) are not created on the namespace level, but instead on the resource group level. This has the result that the first time, my deployment works fine. The second time I deploy though, I get a deployment error saying the role assignment resource already exists (or cannot be updated).

Below is my adaptation of this repository, in a minimal working example, which results in the described behaviour. Is this something that other users of aks-baseline experience? Can I troubleshoot this somehow?

targetScope = 'resourceGroup'

var clusterReaderGroupObjectId = 'aaaaa-bbbbb-cccccc-ddddddd-eeeee'

resource clusterReaderRole 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' existing = {
  name: '7f6c6a51-bcf8-42ba-9220-52d62157d7db'
  scope: subscription()
}

resource aks 'Microsoft.ContainerService/managedClusters@2023-04-01' existing = {
  name: 'my-cluster'
}

#disable-next-line BCP081 // this namespaces child type doesn't have a defined bicep type yet.
resource nsDev 'Microsoft.ContainerService/managedClusters/namespaces@2023-04-01' existing = {
  parent: aks
  name: 'dev'
}

resource maAadEnvReaderGroupClusterReaderRole_roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: nsDev
  name: guid('aad-dev-reader-group', aks.id, clusterReaderGroupObjectId)
  properties: {
    roleDefinitionId: clusterReaderRole.id
    description: 'Members of this group are readers of the dev namespace in this cluster.'
    principalId: clusterReaderGroupObjectId
    principalType: 'Group'
  }
}
@ckittel
Copy link
Member

ckittel commented Mar 22, 2024

The issue could very likely come from guid('aad-dev-reader-group', aks.id, clusterReaderGroupObjectId). The reason I say that is Azure RBAC doesn't allow one RBAC assignment to be changed to another principalId (or roleDefinitionId, IIRC). As long as that guid has a 1-to-1 mapping with a unique set of principal and role information, you can overwrite (with no change) or create new.

I unfortunately do not have the bandwidth right now to help triage this further, but the tip I will leave for you is:

name: Guid -> must be UNIQUE and UNCHANGING for role + principal.

Meaning:

  1. role + principal must not exist under two different GUIDs at the same scope
  2. ONE GUID cannot "change" principal information nor role information between deployments. (You have to do a new role assignment (ie. a new name) if you are changing permissions)

I'm hoping one of those situations are what you are facing. If not, we can keep this issue open, but expect quite a delay before our team could engage further.

@joachimnielandt
Copy link
Author

I have since gotten feedback from Azure's support. My issue was a lack in the bicep compiler, apparently, which doesn't provide enough information about the issue at hand. I was generating the role assignment in a for-loop, where the scope was built using the for-variable. This is currently not supported, which leads to the scope defaulting to the resource group (in this case). The issue is that this is not communicated to the user as an error, masking the problem. The solution was then to eliminate the for loop, making the scope known at compile time. Below is my response from support:

    Issue:
        When deploying a bicep file with a Role Assignment with a dynamic scope, the Role Assignment defaults to the bicep file targetScope. No error or warning is shown. 
    Cause:
        Extracting the logic into a variable shows the error
            Error BCP120: This expression is being used in an assignment to the "scope" property of the "Microsoft.Authorization/roleAssignments" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("scope" -> "nsDev"). Properties of nsDev which can be calculated at the start include "apiVersion", "id", "name", "type".
    Resolution:
        Workaround: use conditional deployment instead of a dynamic scope
        Fix is coming in Bicep 1.0 (source: https://github.com/Azure/bicep/issues/10475)

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

No branches or pull requests

2 participants