对 Azure RBAC 限制进行故障排除

本文介绍在 Azure 基于角色的访问控制 (Azure RBAC) 中超出限制时的一些常见解决方案。

先决条件

注意

本文中使用的查询仅返回你有权读取的角色分配或自定义角色。 例如,如果你仅有权读取资源组范围内的角色分配,则不会返回订阅范围的角色分配。

症状 - 无法再创建角色分配

尝试分配角色时,收到以下错误消息:

No more role assignments can be created (code: RoleAssignmentLimitExceeded)

原因

Azure 支持每个订阅最多 5000 个角色分配。 此限制包括订阅、资源组和资源范围内的角色分配,但不包括管理组范围内的角色分配。 符合条件的角色分配和将来计划的角色分配不计入此限制。 你应尝试减少订阅中的角色分配数。

注意

每个订阅 5000 个角色分配的限制是固定的,不能增加。

若要获取角色分配数,可以查看 Azure 门户中“访问控制(IAM)”页上的图表。 还可以使用以下 Azure PowerShell 命令:

$scope = "/subscriptions/<subscriptionId>"
$ras = Get-AzRoleAssignment -Scope $scope | Where-Object {$_.scope.StartsWith($scope)}
$ras.Count

解决方案 1 - 将基于主体的角色分配替换为基于组的角色分配

若要减少订阅中的角色分配数,请将主体(用户、服务主体和托管标识)添加到组,并改为将角色分配给组。 按照以下步骤,确定可将分配给主体的多个角色分配替换为分配给组的单个角色分配的位置。

  1. 登录到 Azure 门户并打开 Azure Resource Graph 资源管理器。

  2. 选择“范围”并设置查询的范围

    通常将范围设为 目录 以查询整个租户,但你也可以将范围缩小到特定订阅。

    显示范围选择的 Azure Resource Graph 资源管理器的屏幕截图。

  3. 选择 设置授权范围,并将授权范围设置为 当前级别、上级和下级,以查询指定作用域内的所有资源。

    显示“设置授权范围”窗格的 Azure Resource Graph 资源管理器的屏幕截图。

  4. 运行以下查询,获取具有相同角色、处于同一范围但针对不同主体的角色分配。

    此查询会检查活动角色分配,不会考虑 Microsoft Entra Privileged Identity Management 中符合条件的角色分配。 若要列出符合条件的角色分配,可使用 Microsoft Entra 管理中心、PowerShell 或 REST API。 有关详细信息,请参阅 Get-AzRoleEligibilityScheduleInstance角色资格计划实例 - 范围列表

    如果使用角色分配条件使用条件委托角色分配管理,则应使用“条件”查询。 否则,使用“默认”查询。

    authorizationresources
    | where type =~ "microsoft.authorization/roleassignments"
    | where id startswith "/subscriptions"
    | extend RoleId = tolower(tostring(properties.roleDefinitionId))
    | join kind = leftouter (
      authorizationresources
      | where type =~ "microsoft.authorization/roledefinitions"
      | extend RoleDefinitionName = tostring(properties.roleName)
      | extend RoleId = tolower(id)
      | project RoleDefinitionName, RoleId
    ) on $left.RoleId == $right.RoleId
    | extend principalId = tostring(properties.principalId)
    | extend principal_to_ra = pack(principalId, id)
    | summarize count_ = count(), AllPrincipals = make_set(principal_to_ra) by RoleDefinitionId = RoleId, Scope = tolower(properties.scope), RoleDefinitionName
    | where count_ > 1
    | order by count_ desc
    

    下面显示了结果示例。 count_ 列表示在同一范围内被分配相同角色的主体数量。 计数值按降序排序。

    Azure Resource Graph 资源管理器的屏幕截图,其中显示了具有相同角色、处于同一范围但针对不同主体的角色分配。

  5. 找到要将多个角色分配替换为针对某个组的单一角色分配的行。

  6. 在该行中,选择“查看详细信息”以打开“详细信息”窗格

    “详细信息”窗格的截图,其中显示了具有相同角色且处于同一作用域、但属于不同主体的角色分配。

    说明
    RoleDefinitionId 当前分配角色的 ID
    Scope 角色分配的作用域,可以是订阅、资源组或资源。
    RoleDefinitionName 当前分配的角色的名称
    count_ 在同一作用域内被分配到同一角色的主体数量。
    AllPrincipals 被分配了相同角色且处于同一作用域的主体 ID 列表。
  7. 使用 RoleDefinitionId、RoleDefinitionName 和 Scope 来获取角色和范围

  8. 使用 AllPrincipals 获取具有相同角色分配的主体 ID 的列表

  9. 创建 Microsoft Entra 组。 有关详细信息,请参阅管理 Microsoft Entra 组和组成员身份

  10. 将 AllPrincipals 中的主体添加到组

    有关如何批量添加主体的信息,请参阅在 Microsoft Entra ID 中批量添加组成员

  11. 将角色分配给在同一范围内创建的组。 有关详细信息,请参阅使用 Azure 门户分配 Azure 角色

    现在,您可以查找并删除基于主体的角色分配。

  12. 根据主体 ID 获取主体名称。

  13. 在与角色分配相同的范围内打开“访问控制 (IAM)”页面。

  14. 选择“角色分配”选项卡。

  15. 若要筛选角色分配,请选择“角色”筛选器,然后选择角色名称

  16. 查找基于主体的角色分配。

    你还应该能看到基于组的角色分配。

    “访问控制(IAM)”页面的屏幕截图,其中显示了分配给不同主体的角色分配,这些分配具有相同的角色并且位于同一作用域内。

  17. 选择并删除基于主体的角色分配。 有关详细信息,请参阅删除 Azure 角色分配

解决方案 2 - 删除冗余角色分配

若要减少订阅中的角色分配数,请删除冗余角色分配。 按照以下步骤,确定较低范围内的冗余角色分配可能被删除的位置,因为较高范围内的角色分配已授予访问权限。

  1. 登录到 Azure 门户并打开 Azure Resource Graph 资源管理器。

  2. 选择“范围”并设置查询的范围

    通常会将范围设置为 目录,以查询整个租户,但你也可以将范围缩小到特定订阅。

    显示范围选择的 Azure Resource Graph 资源管理器的屏幕截图。

  3. 选择设置授权范围,并将授权范围设置为当前范围、上级和下级,以查询指定范围内的所有资源。

    显示“设置授权范围”窗格的 Azure Resource Graph 资源管理器的屏幕截图。

  4. 运行以下查询,获取具有相同角色和相同主体但处于不同范围的角色分配。

    此查询会检查处于活动状态的角色分配,且不会考虑 Microsoft Entra Privileged Identity Management 中符合条件的角色分配。 若要列出符合条件的角色分配,可使用 Microsoft Entra 管理中心、PowerShell 或 REST API。 有关详细信息,请参阅 Get-AzRoleEligibilityScheduleInstance角色资格计划实例 - 范围列表

    如果使用角色分配条件使用条件委托角色分配管理,则应使用“条件”查询。 否则,使用“默认”查询。

    authorizationresources
    | where type =~ "microsoft.authorization/roleassignments"
    | where id startswith "/subscriptions"
    | extend RoleDefinitionId = tolower(tostring(properties.roleDefinitionId))
    | extend PrincipalId = tolower(properties.principalId)
    | extend RoleDefinitionId_PrincipalId = strcat(RoleDefinitionId, "_", PrincipalId)
    | join kind = leftouter (
      authorizationresources
      | where type =~ "microsoft.authorization/roledefinitions"
      | extend RoleDefinitionName = tostring(properties.roleName)
      | extend rdId = tolower(id)
      | project RoleDefinitionName, rdId
    ) on $left.RoleDefinitionId == $right.rdId
    | summarize count_ = count(), Scopes = make_set(tolower(properties.scope)) by RoleDefinitionId_PrincipalId,RoleDefinitionName
    | project RoleDefinitionId = split(RoleDefinitionId_PrincipalId, "_", 0)[0], RoleDefinitionName, PrincipalId = split(RoleDefinitionId_PrincipalId, "_", 1)[0], count_, Scopes
    | where count_ > 1
    | order by count_ desc
    

    下面显示了结果示例。 count_ 列表示在角色和主体相同的情况下,角色分配所涉及的不同作用域的数量。 按数量降序排列。

    Azure Resource Graph 资源管理器的截图,显示了针对相同角色和相同主体、但位于不同作用域的角色分配。

    说明
    角色定义 ID 当前分配的角色的 ID
    RoleDefinitionName 当前分配的角色的名称
    PrincipalId 被分配该角色的主体的 ID。
    count_ 相同角色和相同主体的角色分配所对应的不同作用域数量。
    作用域 相同角色和相同主体下的角色分配范围。
  5. 确定要删除冗余角色分配的行。

  6. 在一行中,选择“查看详细信息”以打开“详细信息”窗格

    显示相同角色和相同主体在不同作用域下的角色分配的“详细信息”窗格屏幕截图。

  7. 使用 RoleDefinitionIdRoleDefinitionNamePrincipalId 获取角色定义和主体 ID。

  8. 使用“Scopes”获取相同角色和相同主体的范围列表

  9. 确定角色分配所需的范围。 可删除其他角色分配。

    确定可删除哪些角色分配时,应遵循最小特权的最佳做法。 较高范围内的角色分配可能会向主体授予超出所需的访问权限。 在这种情况下,应删除范围更高的角色分配。 例如,当较低资源组范围的“虚拟机参与者”角色分配授予所需的访问权限时,用户可能不需要订阅范围内的“虚拟机参与者”角色分配。

  10. 从主体 ID 获取主体名称。

  11. 在要删除的角色分配所属的作用域中,打开访问控制 (IAM)页面。

  12. 选择“角色分配”选项卡。

  13. 若要筛选角色分配,请选择“角色”筛选器,然后选择角色名称

  14. 查找主体。

  15. 选择并删除角色分配。 有关详细信息,请参阅删除 Azure 角色分配

解决方案 3 - 将多个内置角色分配替换为自定义角色分配

若要减少订阅中的角色分配数,请将多个内置角色分配替换为单个自定义角色分配。 按照以下步骤,确定多个内置角色分配可能被替换的位置。

  1. 登录到 Azure 门户并打开 Azure Resource Graph 资源管理器。

  2. 选择“范围”并设置查询的范围

    通常会将作用域设为目录,以对整个租户进行查询,但也可以将作用域缩小到特定订阅。

    显示范围选择的 Azure Resource Graph 资源管理器的屏幕截图。

  3. 运行以下查询,获取具有相同主体和相同范围,但具有不同的内置角色的角色分配。

    此查询检查活动角色分配,且不考虑 Microsoft Entra Privileged Identity Management 中符合条件的角色分配。 若要列出符合条件的角色分配,可使用 Microsoft Entra 管理中心、PowerShell 或 REST API。 有关详细信息,请参阅 Get-AzRoleEligibilityScheduleInstance角色资格计划实例 - 范围列表

    如果使用角色分配条件使用条件委托角色分配管理,则应使用“条件”查询。 否则,使用“默认”查询。

    authorizationresources
    | where type =~ "microsoft.authorization/roleassignments"
    | where id startswith "/subscriptions"
    | extend PrincipalId = tostring(properties.principalId) 
    | extend Scope = tolower(properties.scope)
    | extend RoleDefinitionId = tolower(tostring(properties.roleDefinitionId))
    | join kind = leftouter (
      authorizationresources
      | where type =~ "microsoft.authorization/roledefinitions"
      | extend RoleName = tostring(properties.roleName)
      | extend RoleId = tolower(id)
      | extend RoleType = tostring(properties.type) 
      | where RoleType == "BuiltInRole"
      | extend RoleId_RoleName = pack(RoleId, RoleName)
    ) on $left.RoleDefinitionId == $right.RoleId
    | summarize count_ = count(), AllRD = make_set(RoleId_RoleName) by PrincipalId, Scope
    | where count_ > 1
    | order by count_ desc
    

    下面显示了结果示例。 count_ 列表示具有相同主体和相同作用域的不同内置角色分配的数量。 计数值按降序排序。

    Azure Resource Graph 资源管理器的屏幕截图,其中显示了具有相同主体和相同范围的角色分配。

    说明
    PrincipalId 被分配内置角色的主体 ID。
    Scope 内置角色分配的范围。
    count_ 相同主体和相同作用域的内置角色分配数量。
    AllRD 内置角色的 ID 和名称。
  4. 在一行中,选择“查看详细信息”以打开“详细信息”窗格

    “详细信息”窗格的屏幕截图,其中显示了具有相同主体和相同范围的角色分配。

  5. 使用AllRD查看可组合成自定义角色的内置角色。

  6. 列出内置角色的操作和数据操作。 有关详细信息,请参阅 列出 Azure 角色定义Azure 内置角色

  7. 创建一个包含所有操作和数据操作的自定义角色作为内置角色。 若要更轻松地创建自定义角色,可从克隆其中一个内置角色开始。 有关详细信息,请参阅使用 Azure 门户创建或更新 Azure 自定义角色

  8. 从主体 ID 获取主体名称。

  9. 在与角色分配相同的范围内打开“访问控制(IAM)”页面

  10. 将新的自定义角色分配给主体。 有关详细信息,请参阅使用 Azure 门户分配 Azure 角色

    现在,可删除内置角色分配。

  11. 在同一范围内的“访问控制(IAM)”页上,选择“角色分配”选项卡

  12. 查找主体和内置角色分配。

  13. 删除主体的内置角色分配。 有关详细信息,请参阅删除 Azure 角色分配

解决方案 4 - 使角色分配符合条件

若要减少订阅中的角色分配数,并且你拥有 Microsoft Entra ID P2,请在 Microsoft Entra Privileged Identity Management 中使角色分配符合条件,而不是使之永久分配。

解决方案 5 - 添加其他订阅

添加额外的订阅。

症状 - 无法在管理组范围内创建更多角色分配

无法在管理组范围内分配角色。

原因

Azure 对于每个管理组最多支持 500 个角色分配。 此限制不同于每个订阅中的角色分配数量限制。

注意

每个管理组的角色分配数限制 500 是固定的,无法提高。

解决方案

尝试减少管理组中的角色分配数。 有关可能的选项,请参阅症状 - 无法创建更多角色分配。 若要使查询在管理组级别检索资源,需要对查询进行以下更改:

替换

| where id startswith "/subscriptions"

With

| where id startswith "/providers/Microsoft.Management/managementGroups"

症状 - 无法创建更多角色定义

尝试创建新的自定义角色时,收到以下消息:

Role definition limit exceeded. No more role definitions can be created (code: RoleDefinitionLimitExceeded)

原因

Azure 在一个目录中最多支持 5000 个自定义角色。 (对于由世纪互联运营的 Microsoft Azure,限制为 2000 个自定义角色。)

解决方案

按照以下步骤,查找和删除未使用的 Azure 自定义角色。

  1. 登录到 Azure 门户并打开 Azure Resource Graph 资源管理器。

  2. 选择范围,并将查询范围设置为目录

    显示范围选择的 Azure Resource Graph 资源管理器的屏幕截图。

  3. 运行以下查询,获取没有任何角色分配的所有自定义角色:

    此查询检查的是活动角色分配,且不考虑 Microsoft Entra Privileged Identity Management 中符合条件的自定义角色分配。 若要列出符合条件的自定义角色分配,可使用 Microsoft Entra 管理中心、PowerShell 或 REST API。 有关详细信息,请参阅 Get-AzRoleEligibilityScheduleInstance角色资格计划实例 - 范围列表

    authorizationresources
    | where type =~ "microsoft.authorization/roledefinitions"
    | where tolower(properties.type) == "customrole"
    | extend rdId = tolower(id)
    | extend Scope = tolower(properties.assignableScopes)
    | join kind = leftouter (
    authorizationresources
      | where type =~ "microsoft.authorization/roleassignments"
      | extend RoleId = tolower(tostring(properties.roleDefinitionId))
      | summarize RoleAssignmentCount = count() by RoleId
    ) on $left.rdId == $right.RoleId
    | where isempty(RoleAssignmentCount)
    | project RoleDefinitionId = rdId, RoleDefinitionName = tostring(properties.roleName), Scope
    

    下面显示了结果示例:

    Azure Resource Graph 资源管理器的屏幕截图,其中显示了没有角色分配的自定义角色。

    说明
    RoleDefinitionId 未使用的自定义角色的 ID。
    RoleDefinitionName 未使用的自定义角色的名称。
    Scope 未使用的自定义角色的可分配范围
  4. 打开范围(通常为订阅),然后打开“访问控制(IAM)”页

  5. 选择“角色”选项卡以查看包含所有内置角色和自定义角色的列表。

  6. 在“类型”筛选器中,选择“CustomRole”,以便仅查看你的自定义角色。

  7. 选择要删除的自定义角色对应的省略号 (...),然后选择“删除”

    可选择删除的自定义角色列表的屏幕截图。

后续步骤