maxvanp/az-rbac-watch

GitHub: maxvanp/az-rbac-watch

Azure RBAC 治理工具,通过 YAML 声明期望状态实现权限漂移检测与护栏策略审计。

Stars: 0 | Forks: 0

# Azure Permissions Watch Azure RBAC as Code — 漂移检测与护栏。 ## 功能介绍 一个工具中的两个互补命令: - **`scan`** — **RBAC as Code**(正向):在 YAML 中声明您期望的 RBAC 状态,检测与该状态的漂移 - **`audit`** — **Policy as Code**(负向):定义禁止模式(护栏),检测违规行为 - **`scan --orphans-only`** — 检测引用已删除主体的分配(孤立身份) 这两个命令共享同一个 RBAC 扫描器 —— 其核心价值在于,无论是 OPA 还是 Azure Policy 都无法原生扫描 RBAC 分配。 ## 安装说明 ``` # 推荐 — CLI 工具的隔离安装 pipx install az-rbac-watch # 或者使用 pip pip install az-rbac-watch ``` 需要 Python ≥ 3.12 和 [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) 用于身份验证。 ## Shell 补全 为 bash、zsh 或 fish 启用 tab 补全: ``` az-rbac-watch --install-completion ``` 安装后请重启您的 shell。 ## 快速入门 ### 1. 身份验证 ``` az login ``` ### 2. 发现现有分配 ``` # 单个订阅 az-rbac-watch discover -t -s -o my_policy.yaml # 所有可访问范围 az-rbac-watch discover -t -o my_policy.yaml ``` ### 3. 扫描漂移 (RBAC as Code) `scan` 命令将实际 RBAC 分配与您的基线规则进行比较。任何未被基线规则覆盖的分配都将被报告为 **DRIFT**。 ``` # 控制台输出 az-rbac-watch scan -p my_policy.yaml # HTML 报告 az-rbac-watch scan -p my_policy.yaml -o report.html # JSON (CI/CD) az-rbac-watch scan -p my_policy.yaml --format json ``` ### 4. 审计护栏 (Policy as Code) `audit` 命令检查治理规则(禁止模式)。任何匹配治理规则的分配都将被报告为 **violation**(违规)。 ``` # 控制台输出 az-rbac-watch audit -p my_policy.yaml # HTML 报告 az-rbac-watch audit -p my_policy.yaml -o report.html # JSON (CI/CD) az-rbac-watch audit -p my_policy.yaml --format json ``` 包含常见治理规则的入门工具包可在 [`examples/deny_rules_starter.yaml`](examples/deny_rules_starter.yaml) 中找到。 ### 5. 验证策略语法(离线) ``` az-rbac-watch validate -p my_policy.yaml ``` ### 6. 捕获 RBAC 快照 ``` # 从策略文件 az-rbac-watch snapshot -p my_policy.yaml -o snapshot_2026-03-09.json # 从显式范围 az-rbac-watch snapshot -t -s -o snapshot.json ``` ### 7. 比较快照(变更追踪) ``` # 控制台输出 az-rbac-watch diff snapshot_old.json snapshot_new.json # JSON (CI/CD) az-rbac-watch diff snapshot_old.json snapshot_new.json --format json -o changes.json ``` ## 双轴合一 | 维度 | 命令 | 规则类型 | 发现结果 | 回答的问题 | |------|---------|-----------|---------|-------------------| | RBAC as Code | `scan` | `baseline` | `DRIFT` | “是否有我未声明的内容?” | | Policy as Code | `audit` | `governance` | `GOVERNANCE_VIOLATION` | “是否有被禁止的内容?” | | Change tracking | `snapshot` + `diff` | 不适用 | Added / Removed / Modified | “自上次以来发生了什么变化?” | 您可以在同一个策略文件中同时使用两者。每个命令只关注其对应的规则类型,并忽略另一种。 ## 范围模式 策略模型支持两种范围模式: - **`scope: explicit`**(默认)—— 仅扫描 YAML 中列出的订阅和管理组 - **`scope: all`** —— 在扫描时自动发现所有可访问的范围,并支持可选排除项 ``` scope: all exclude_subscriptions: - "22222222-2222-2222-2222-222222222222" exclude_management_groups: - "mg-sandbox" ``` CLI 排除项(`--exclude-subscription`、`--exclude-management-group`)在 YAML 排除项之上叠加应用。 ## CLI 参考 ### `az-rbac-watch scan` 检测 RBAC 漂移 —— 将实际状态与基线规则进行比较。 | 选项 | 描述 | |---|---| | `-p, --policy PATH` | 策略模型 YAML(必需) | | `-t, --tenant-id ID` | Tenant ID(临时模式) | | `-s, --subscription ID` | 要扫描的订阅,可重复(临时模式) | | `-m, --management-group ID` | 要扫描的管理组,可重复(临时模式) | | `-o, --output PATH` | HTML 报告输出路径 | | `-f, --format FORMAT` | `console`(默认)或 `json` | | `--orphans-only` | 仅扫描孤立分配(需要 `--tenant-id`) | | `--dry-run` | 显示扫描计划而不进行 API 调用 | | `--exclude-subscription ID` | 排除订阅(可重复) | | `--exclude-management-group ID` | 排除管理组(可重复) | | `-v, --verbose` | 调试日志 | | `--debug` | 出错时显示完整回溯 | ### `az-rbac-watch audit` 检查治理护栏 —— 根据实际状态评估治理规则。 | 选项 | 描述 | |---|---| | `-p, --policy PATH` | 策略模型 YAML(必需) | | `-t, --tenant-id ID` | Tenant ID(临时模式) | | `-s, --subscription ID` | 要扫描的订阅,可重复(临时模式) | | `-m, --management-group ID` | 要扫描的管理组,可重复(临时模式) | | `-o, --output PATH` | HTML 报告输出路径 | | `-f, --format FORMAT` | `console`(默认)或 `json` | | `--dry-run` | 显示扫描计划而不进行 API 调用 | | `--exclude-subscription ID` | 排除订阅(可重复) | | `--exclude-management-group ID` | 排除管理组(可重复) | | `-v, --verbose` | 调试日志 | | `--debug` | 出错时显示完整回溯 | ### `az-rbac-watch discover` | 选项 | 描述 | |---|---| | `-t, --tenant-id ID` | Tenant ID | | `-s, --subscription ID` | 要扫描的订阅(可重复) | | `-m, --management-group ID` | 要扫描的管理组(可重复) | | `-o, --output PATH` | 输出 YAML(默认:`discovered_policy.yaml`) | ### `az-rbac-watch validate` | 选项 | 描述 | |---|---| | `-p, --policy PATH` | 要验证的策略模型 YAML(必需) | ### `az-rbac-watch snapshot` 捕获完整的 RBAC 快照(分配 + 角色定义)为 JSON。 | 选项 | 描述 | |---|---| | `-p, --policy PATH` | 策略模型 YAML(使用其范围) | | `-t, --tenant-id ID` | Tenant ID | | `-s, --subscription ID` | 要扫描的订阅(可重复) | | `-m, --management-group ID` | 要扫描的管理组(可重复) | | `--exclude-subscription ID` | 排除订阅(可重复) | | `--exclude-management-group ID` | 排除管理组(可重复) | | `-o, --output PATH` | 输出 JSON 文件(必需) | | `-v, --verbose` | 调试日志 | | `--debug` | 出错时显示完整回溯 | ### `az-rbac-watch diff` 比较两个快照并显示 RBAC 变更(已添加、已移除、已修改的分配)。 | 选项 | 描述 | |---|---| | `OLD_SNAPSHOT` | 较旧快照 JSON 文件的路径(必需) | | `NEW_SNAPSHOT` | 较新快照 JSON 文件的路径(必需) | | `-f, --format FORMAT` | `console`(默认)或 `json` | | `-o, --output PATH` | 输出文件路径 | ## 退出代码 | 代码 | 含义 | |------|---------| | `0` | 合规 —— 未检测到发现结果 | | `1` | 不合规 —— 检测到发现结果 | | `2` | 错误 —— 身份验证失败、API 错误、YAML 无效 | `diff` 命令如果无变更则返回 `0`,如果检测到变更则返回 `1`。 CI/CD 使用示例: ``` # 检查漂移 az-rbac-watch scan -p policy.yaml --format json -o drift.json scan_exit=$? # 检查护栏 az-rbac-watch audit -p policy.yaml --format json -o audit.json audit_exit=$? if [ "$scan_exit" -eq 1 ] || [ "$audit_exit" -eq 1 ]; then echo "Non-compliant — review reports" elif [ "$scan_exit" -eq 2 ] || [ "$audit_exit" -eq 2 ]; then echo "Scan error — check credentials and permissions" fi ``` ## 故障排除 **身份验证错误** - 运行 `az login` 刷新您的凭据 - 验证 `DefaultAzureCredential` 可以进行身份验证(检查 `AZURE_*` 环境变量或托管标识) **访问被拒绝** - 扫描主体需要每个范围内的订阅/MG 拥有 `Microsoft.Authorization/roleAssignments/read` 权限 - 使用以下命令检查:`az role assignment list --scope /subscriptions/ --assignee ` **名称未解析(显示 UUID)** - App Registration(或用户)需要 Microsoft Graph 的 `Directory.Read.All` 权限 - 使用 `--verbose` 运行以在日志中查看 Graph API 错误 **限流** - Azure ARM API 对并行请求有速率限制 - 降低并行度:默认为 4 个 worker(可在代码中通过 `max_workers` 配置) - 等待几分钟后重试 **完整回溯** - 使用 `--debug` 在出现任何错误时查看完整的 Python 回溯 ## 规则匹配运算符 所有比较均不区分大小写。条件使用 AND 逻辑组合。 | 运算符 | 类型 | 描述 | |---|---|---| | `scope` | `str` | 精确范围匹配 | | `scope_prefix` | `str` | 范围以此值开头 | | `role` | `str` | 精确角色名称 | | `role_in` | `list` | 角色在列表中 | | `role_not_in` | `list` | 角色不在列表中 | | `role_type` | `str` | `BuiltInRole` 或 `CustomRole` | | `principal_type` | `str` | `User`、`Group` 或 `ServicePrincipal` | | `principal_type_in` | `list` | 主体类型在列表中 | | `principal_id` | `str` | 精确主体 ID | | `principal_name_prefix` | `str` | 显示名称以此开头 | | `principal_name_not_prefix` | `str` | 显示名称不以此开头 | | `principal_name_contains` | `str` | 显示名称包含此内容 | | `principal_name_not_contains` | `str` | 显示名称不包含此内容 | 基于名称的运算符需要 Graph API 访问权限。如果不可用,它们将评估为 `false`(无假阳性)。 ## 所需 Azure 权限 - 扫描范围内的 `Microsoft.Authorization/roleAssignments/read` - `Directory.Read.All`(Graph API,用于显示名称解析) ## 许可证 MIT
标签:Azure, Azure CLI, CI/CD 集成, CSPM, DevSecOps, Force Graph, IAM, Java RMI, Orphaned Identities, Python, RBAC, TinkerPop, YAML 配置, 上游代理, 二进制发布, 云治理, 僵尸账户检测, 合规性审计, 基即代码, 安全态势管理, 开源工具, 护栏, 无后门, 权限管理, 模型越狱, 漂移检测, 策略即代码, 聊天机器人安全, 角色分配, 订阅管理, 身份与访问管理, 逆向工具