4. Azure AD/Entra ID 实战:条件访问策略、托管身份与服务主体、Azure RBAC 与 ABAC

好,咱们进入 Azure 这一章。说实话,在多云身份治理里,Azure 的体系是最复杂的,但也是设计得最灵活的。它把身份分成了“人”和“非人”两条线,权限又分成了角色(RBAC)和属性(ABAC)两层。今天我就带你把这几个核心组件串起来,讲明白它们在实际项目中怎么配合。

4.1 条件访问策略:不只是“允许/拒绝”

条件访问策略,说白了就是“在什么条件下,允许谁用什么方式访问什么资源”。它不是简单的开关,而是一个策略引擎。

我刚开始接触时,觉得它跟防火墙规则差不多。后来在项目中踩了坑才明白——条件访问的评估顺序和策略组合,才是真正的难点。

4.1.1 核心组件

一条完整的条件访问策略,由三部分组成:

  • 分配(Assignments):谁(用户/组)、什么(云应用)、什么条件(位置/设备状态/风险)
  • 访问控制(Access Controls):允许、阻止、或要求多因素认证/合规设备
  • 启用策略(Enable policy):开/关/仅报告模式

关键点:条件访问策略是“与”逻辑。所有分配条件必须同时满足,才会触发访问控制。如果某个条件不匹配,策略就不生效,而不是拒绝访问。

4.1.2 实战:配置一个“高危位置登录要求 MFA”的策略

我记得有一次,客户发现管理员账号经常从海外 IP 登录。我们立刻配了一条策略:

# 策略名称:Block-HighRisk-Locations
# 分配:
#   用户和组:所有管理员(角色组)
#   云应用:所有云应用
#   条件:
#     - 位置:选择“不信任的国家/地区”
#     - 客户端应用:浏览器 + 移动应用
# 访问控制:
#   授予:需要多因素认证
#   会话:使用应用强制限制
# 启用策略:开

配完之后,管理员从海外登录时,会先被要求 MFA。如果连续失败,策略会自动阻止。

我的习惯:上线前先用“仅报告”模式跑一周,看看会影响多少用户。别一上来就开“阻止”,容易把自己锁在外面。

4.1.3 避坑指南

  • 策略优先级:条件访问没有优先级,所有匹配的策略都会生效。如果一条要求 MFA,另一条要求合规设备,用户必须同时满足。
  • 排除紧急访问账号:我曾经见过一个客户,配了条件访问后把所有管理员都锁了,因为策略要求 MFA,但 MFA 服务本身也被策略覆盖了。所以一定要留 1-2 个紧急访问账号(Break Glass Account),排除在策略之外。
  • 设备平台限制:如果策略要求“合规设备”,但用户用的是 Linux 或老旧手机,可能永远无法满足条件。记得加一个“其他客户端”的降级策略。

4.2 托管身份与服务主体:非人身份的两种形态

在 Azure 里,非人身份有两种:托管身份(Managed Identity)和服务主体(Service Principal)。很多人分不清,我简单说一下。

特性 托管身份 服务主体
创建方式 自动,绑定 Azure 资源 手动,通过应用注册
生命周期 随资源自动管理 需要手动管理密钥/证书
使用场景 Azure 内部资源互访 外部应用、CI/CD、跨租户
密钥轮换 Azure 自动处理 需要手动或脚本轮换
典型例子 VM 访问 Key Vault GitHub Actions 部署到 Azure

4.2.1 托管身份实战

假设你有一个 Web App,需要读取 Key Vault 里的数据库密码。用托管身份是最优雅的方式:

# 1. 为 Web App 启用系统分配托管身份
az webapp identity assign --name myWebApp --resource-group myRG

# 2. 在 Key Vault 中授予托管身份读取权限
az keyvault set-policy --name myKeyVault \
  --object-id <托管身份的对象ID> \
  --secret-permissions get list

# 3. 在代码中通过 Azure SDK 获取令牌
# C# 示例
var credential = new DefaultAzureCredential();
var secretClient = new SecretClient(vaultUri, credential);
KeyVaultSecret secret = await secretClient.GetSecretAsync("db-password");

这样做的好处是:没有密钥文件,没有硬编码密码,Azure 自动帮你轮换身份。

注意:系统分配托管身份的生命周期和资源绑定。如果你删除了 Web App,这个身份也就没了。如果多个资源需要共享同一个身份,用用户分配托管身份。

4.2.2 服务主体实战

服务主体通常用于外部系统。比如你的 CI/CD 工具要部署到 Azure,就需要一个服务主体。

# 创建服务主体并分配 Contributor 角色
az ad sp create-for-rbac --name "github-actions-deployer" \
  --role Contributor \
  --scopes /subscriptions/<sub-id>/resourceGroups/myRG

# 输出类似:
# {
#   "appId": "xxx",
#   "displayName": "github-actions-deployer",
#   "password": "yyy",
#   "tenant": "zzz"
# }

然后把这个 appId 和 password 配置到 GitHub Secrets 里。注意,密码是一次性的,丢了就得重新创建。

我的建议:服务主体的密钥要定期轮换。我一般用 Azure Automation 或 GitHub Actions 写一个定时任务,每 90 天自动生成新密钥并更新到 Key Vault。

4.3 Azure RBAC 与 ABAC:从角色到属性的进化

RBAC 大家都很熟了——给用户分配角色,角色包含权限。但 RBAC 有个硬伤:它只能基于“你是谁”或“你在哪个组”来控制权限,不能基于“资源本身是什么”来做精细控制。

举个例子:你想让某个用户只能读取“标记为 Production”的存储账户。用 RBAC 做不到,因为 RBAC 的权限是静态的。这时候就需要 ABAC。

4.3.1 RBAC 实战:最小权限原则

我见过太多人直接给“Contributor”角色,这是不对的。正确的做法是:

  1. 先分析用户需要做什么(读日志?重启 VM?部署代码?)
  2. 找到对应的内置角色(Reader、Virtual Machine Contributor、Website Contributor)
  3. 如果内置角色权限太大,创建自定义角色
# 创建自定义角色:只允许重启 VM,不能做其他操作
az role definition create --role-definition '{
  "Name": "VM Restart Operator",
  "Description": "Can restart virtual machines",
  "Actions": [
    "Microsoft.Compute/virtualMachines/restart/action"
  ],
  "NotActions": [],
  "AssignableScopes": ["/subscriptions/<sub-id>"]
}'

4.3.2 ABAC 实战:基于属性的条件

ABAC 是 RBAC 的增强版。它在角色分配的基础上,增加了条件表达式。条件可以基于资源属性、请求属性或环境属性。

我记得有个项目,客户要求“开发人员只能读取自己部门的存储容器”。我们用 ABAC 实现了:

# 条件表达式(使用 Azure 条件语言)
(
  (
    !(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/read'})
  )
  OR
  (
    @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:name]
    StringEquals 'dev-*'
  )
)

这个条件的意思是:如果操作不是读取,允许;如果是读取,只允许读取名称以“dev-”开头的容器。

核心区别:RBAC 是“谁可以做什么”,ABAC 是“谁可以在什么条件下做什么”。ABAC 让权限从静态变成了动态。

4.3.3 什么时候用 ABAC?

  • 资源数量巨大,无法手动分组(比如上千个存储容器)
  • 权限需要根据资源标签、名称、地域动态变化
  • 需要实现“数据层面”的细粒度控制(比如只读某些列)

但 ABAC 也有代价:条件表达式写起来复杂,调试困难。我建议先从 RBAC 开始,等确实遇到“RBAC 搞不定”的场景时,再引入 ABAC。

4.4 本章知识体系

下面这张图,把 Azure 身份治理的核心逻辑串起来了:

Azure 身份治理核心逻辑 Azure 身份治理核心逻辑 人类身份(用户/组) 非人身份 外部身份(B2B/B2C) 条件访问策略引擎 位置 | 设备 | 风险 | 应用 | 用户属性 → 允许/阻止/MFA/合规 Azure RBAC 角色分配(谁 + 角色 + 范围) 静态权限,基于身份 Azure ABAC RBAC + 条件表达式 动态权限,基于资源属性 Azure 资源(VM / Storage / SQL / Key Vault ...) 说明:身份经过条件策略引擎过滤后,通过 RBAC/ABAC 模型授予对 Azure 资源的访问权限

嗯,这张图把整个流程串起来了。你想想看,从身份到策略,再到权限模型,最后到资源,每一层都有对应的 Azure 服务。理解了这张图,你就掌握了 Azure 身份治理的骨架。

4.5 本章小结

这一章我们实战了三个核心组件:

  • 条件访问策略:控制“谁在什么条件下能访问”,记得留紧急账号和用仅报告模式
  • 托管身份与服务主体:非人身份的两条路,内部用托管身份,外部用服务主体
  • RBAC 与 ABAC:从静态角色到动态属性,ABAC 是 RBAC 的补充,不是替代