Skip to content

Get-AzRoleDefinition incorrectly flattens multiple permission entries, losing per-permission conditions #29058

@atomassi

Description

@atomassi

Description

Get-AzRoleDefinition returns empty/null Condition and ConditionVersion for roles that have ABAC conditions defined on non-first permission entries.

For example, the built-in role "Azure Container Storage Contributor" (ID: 95dd08a6-00bd-4661-84bf-f6726f83a4d0) has two permission entries:

  • permissions[0]: Storage/Kubernetes actions with no condition
  • permissions[1]: Role assignment actions with ABAC condition

The old code incorrectly returned Condition = null because it only looked at permissions[0].Condition.

Root cause: The cmdlet was flattening the permissions array into single Actions, NotActions, DataActions, NotDataActions properties and only taking Condition from the first permission entry (permissions[0].Condition).

Expected: The full permission structure should be preserved so each permission's condition is accessible.

Issue script & Debug output

PS> $DebugPreference='Continue'
PS> Get-AzRoleDefinition -Id "95dd08a6-00bd-4661-84bf-f6726f83a4d0" | ConvertTo-Json -Depth 10
{
  "Name": "Azure Container Storage Contributor",
  "Id": "95dd08a6-00bd-4661-84bf-f6726f83a4d0",
  "IsCustom": false,
  "Description": "Lets you install Azure Container Storage and manage its storage resources",
  "Actions": [
    "Microsoft.KubernetesConfiguration/extensions/write",
    "Microsoft.KubernetesConfiguration/extensions/read",
    "Microsoft.KubernetesConfiguration/extensions/delete",
    "Microsoft.KubernetesConfiguration/extensions/operations/read",
    "Microsoft.Authorization/*/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.Resources/subscriptions/read",
    "Microsoft.Management/managementGroups/read",
    "Microsoft.Resources/deployments/*",
    "Microsoft.Support/*",
    "Microsoft.Authorization/roleAssignments/write",
    "Microsoft.Authorization/roleAssignments/delete"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/"
  ],
  "Condition": null,           # <-- BUG: Should contain the ABAC condition!
  "ConditionVersion": null     # <-- BUG: Should be "2.0"
}

What the Azure API actually returns:

{
    "properties": {
        "roleName": "Azure Container Storage Contributor",
        "type": "BuiltInRole",
        "description": "Lets you install Azure Container Storage and manage its storage resources",
        "assignableScopes": [
            "/"
        ],
        "permissions": [
            {
                "actions": [
                    "Microsoft.KubernetesConfiguration/extensions/write",
                    "Microsoft.KubernetesConfiguration/extensions/read",
                    "Microsoft.KubernetesConfiguration/extensions/delete",
                    "Microsoft.KubernetesConfiguration/extensions/operations/read",
                    "Microsoft.Authorization/*/read",
                    "Microsoft.Resources/subscriptions/resourceGroups/read",
                    "Microsoft.Resources/subscriptions/read",
                    "Microsoft.Management/managementGroups/read",
                    "Microsoft.Resources/deployments/*",
                    "Microsoft.Support/*"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            },
            {
                "actions": [
                    "Microsoft.Authorization/roleAssignments/write",
                    "Microsoft.Authorization/roleAssignments/delete"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": [],
                "conditionVersion": "2.0",
                "condition": "((!(ActionMatches{'Microsoft.Authorization/roleAssignments/write'})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals{08d4c71acc634ce4a9c85dd251b4d619})) AND ((!(ActionMatches{'Microsoft.Authorization/roleAssignments/delete'})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals{08d4c71acc634ce4a9c85dd251b4d619}))"
            }
        ]
    },
    "id": "/providers/Microsoft.Authorization/roleDefinitions/95dd08a6-00bd-4661-84bf-f6726f83a4d0",
    "type": "Microsoft.Authorization/roleDefinitions",
    "name": "95dd08a6-00bd-4661-84bf-f6726f83a4d0"
}


Notice the API returns **two permission entries** - the condition is on `permissions[1]`, not `permissions[0]`. The cmdlet flattens all actions together and only reads `permissions[0].Condition`, which is null.

Environment data

PS> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.4.13
PSEdition                      Core
GitCommitId                    7.4.13
OS                             Microsoft Windows 10.0.22631
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Module versions

PS> Get-Module Az.Resources

ModuleType Version    PreRelease Name
---------- -------    ---------- ----
Script     7.5.0                 Az.Resources

Error output

PS> Resolve-AzError
# No error - the cmdlet succeeds but returns incorrect/incomplete data

Metadata

Metadata

Assignees

No one assigned

    Labels

    Resource AuthorizationAzRole* in Az.ResourcesSimilar-IssuebugThis issue requires a change to an existing behavior in the product in order to be resolved.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions