3. Azure RBAC核心机制
Azure RBAC(基于角色的访问控制)是 Azure 资源访问控制的统一授权引擎。它的核心思想可以用一句话概括:“谁(安全主体)在什么范围(Scope)上拥有什么权限(角色定义)”。这三者组合起来,就形成一条角色分配(Role Assignment)。理解 RBAC,本质上就是理解这三个要素以及它们之间的组合规则。
很多初学者会把 RBAC 与 Entra ID 目录角色混淆。需要明确:Entra ID 角色(如全局管理员)管理的是目录对象(用户、组、应用注册);而 Azure RBAC 管理的是Azure 资源(虚拟机、存储账户、Key Vault、订阅本身)。两者是不同平面上的授权体系,不要混用。
角色定义:权限的“模板”
角色定义(Role Definition)是一份权限清单,它规定了“允许做什么”和“不允许做什么”。一份角色定义包含以下关键字段:
- Name / Id:角色名称与唯一标识(内置角色有固定 GUID)。
- IsCustom:是否为自定义角色。
- Actions:允许的控制平面操作,例如
Microsoft.Compute/virtualMachines/start/action。 - NotActions:从 Actions 中减去的操作,用于收窄权限,但不是拒绝。
- DataActions / NotDataActions:数据平面操作,例如读取 Blob 内容
Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read。 - AssignableScopes:该角色可以被分配的范围,自定义角色必须显式声明。
范围层级:权限的“作用域”
Azure 的资源组织是树形结构,RBAC 的授权范围也沿这棵树继承:
- 管理组(Management Group):树的根,用于跨订阅统一治理。
- 订阅(Subscription):计费与配额边界。
- 资源组(Resource Group):生命周期管理单元。
- 资源(Resource):最细粒度,如单台 VM、单个存储账户。
继承规则是向下传递:在管理组授予的权限,会自动作用于其下所有订阅、资源组和资源。反过来,在资源上授予的权限不会向上影响。因此,范围越大,影响面越广,越应谨慎。
角色分配:把三者绑定起来
角色分配是 RBAC 的“执行动作”。一条角色分配由三个要素构成:安全主体 + 角色定义 + 范围。例如:
安全主体:user@contoso.com
角色定义:Reader(读者)
范围:/subscriptions/aaaa-bbbb-cccc-dddd
结果:该用户可读取此订阅下所有资源,但不能修改
角色分配是叠加的。如果同一主体在订阅范围有 Reader,在某个资源组范围有 Contributor,那么在该资源组内,Contributor 的权限生效(因为 Contributor 包含 Reader 的所有操作)。RBAC 是“允许模型”,没有显式拒绝时,权限取并集。
内置角色与自定义角色
Azure 提供了大量内置角色,常用的有:
| 角色 | 典型权限 | 适用场景 |
|---|---|---|
| Owner(所有者) | 全部资源权限 + 可分配角色 | 资源最高管理者 |
| Contributor(参与者) | 可创建和管理资源,不能分配角色 | 日常运维人员 |
| Reader(读者) | 只读查看 | 审计、监控、只读用户 |
| User Access Administrator | 仅管理角色分配 | 权限管理员 |
| Virtual Machine Contributor | 管理 VM,不能改网络与存储 | VM 运维 |
| Storage Blob Data Reader | 读取 Blob 数据(数据平面) | 数据读取应用 |
当内置角色无法满足最小权限原则时,就需要自定义角色。自定义角色的创建需要三个关键输入:
- Actions / DataActions:明确允许哪些操作。
- NotActions / NotDataActions:可选,用于收窄。
- AssignableScopes:声明该角色可在哪些范围被分配。
下面是一个自定义角色的 JSON 示例,目标:允许启动和重启虚拟机,但不能删除,且只能在指定订阅内分配。
{
"Name": "VM Start Restart Operator",
"Description": "可启动和重启虚拟机,不可删除或修改配置",
"Actions": [
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/read"
],
"NotActions": [],
"AssignableScopes": [
"/subscriptions/aaaa-bbbb-cccc-dddd"
]
}
创建后,该角色会出现在该订阅的角色列表中,可以像内置角色一样被分配。注意:AssignableScopes 决定了角色的“可分配边界”,如果只写了某个订阅,就不能在管理组或其他订阅上分配它。
如何判断权限是否生效
当用户反馈“无法操作”时,排查顺序建议如下:
- 确认用户登录的身份是否正确(是否有多个账户)。
- 在目标范围(资源 → 资源组 → 订阅 → 管理组)逐层查看“访问控制 (IAM)”中的角色分配。
- 检查是否存在拒绝分配(Deny Assignment),它会覆盖允许。
- 确认操作属于控制平面还是数据平面。例如读取 Blob 内容需要 DataActions,而 Reader 只给控制平面读取。
- 使用
Check Access或az role assignment list验证有效权限。
az role assignment list \
--assignee user@contoso.com \
--scope /subscriptions/aaaa-bbbb-cccc-dddd \
--include-inherited \
--output table
该命令会列出直接分配和继承的角色。如果结果为空,说明该主体在此范围没有任何 RBAC 授权。
范围选择的核心原则
范围选择直接决定安全边界。一个实用的判断方法是:“这个权限需要覆盖多少资源?” 如果只需要管理一个资源组内的资源,就不要在订阅范围授予。如果多个订阅需要统一策略,才考虑管理组。范围越小,爆炸半径越小,审计也越清晰。
同时要注意:角色分配数量本身也有配额限制(每个订阅默认约 4000 条,可申请提升)。大规模环境中,应优先使用安全组而非单个用户进行分配,这样人员变动时只需调整组成员,不必逐条修改角色分配。
总结来说,Azure RBAC 的四个关键词是:角色定义(能做什么)、角色分配(谁在什么范围拥有它)、范围层级(权限作用到哪里)、内置与自定义(用现成的还是自己裁剪)。把这四者串起来,就能在 Azure 中构建出既安全又可维护的访问控制体系。