aws-samples/sample-kms-access-audit

GitHub: aws-samples/sample-kms-access-audit

该工具用于全面解析并报告跨 IAM 策略、密钥策略及授权的 AWS KMS 密钥访问权限,帮助团队高效完成合规审计与用户证明。

Stars: 2 | Forks: 0

# kms-audit 解析并报告**谁**可以使用您的 AWS KMS keys —— 横跨 IAM policies、key policies 和 grants,并通过 IAM Identity Center 解析来识别 SSO 角色背后的真实人员。 ## 问题所在 AWS KMS 让创建加密密钥变得简单,但要回答“谁能使用这个密钥?”却很困难: - **访问权限来自三个独立的来源。** 基于 Identity 的 IAM policies、key policies(在每个 AWS KMS key 上都是强制性和默认拒绝的)以及 KMS grants 各自独立授予访问权限。没有单一的 API 可以将这三者一起评估。 - **Key policies 是强制性和默认拒绝的。** 与大多数 AWS 服务不同,AWS KMS keys 需要显式的 key policy。即使 IAM policy 授予了 `kms:Encrypt`,key policy 也必须允许它(直接或通过 root 委托)。这种双层评估是 AWS KMS 独有的。 - **KMS grants 添加了第三条访问路径。** 诸如 EBS、RDS 和 S3 之类的 AWS 服务会通过编程方式创建 grants 以使用您的 keys。这些 grants 完全独立于 IAM 和 key policies 存在。 - **IAM Identity Center 增加了一层间接性。** SSO 提供的角色(如 `AWSReservedSSO_DatabaseAdmin_abcdef123456`)并不能告诉您哪些人员具有访问权限。您需要在不同账户中通过 permission sets、账户分配以及 IAM Identity Center 的用户/组进行解析。 - **Condition keys 不可见地限制了访问。** `kms:ViaService` 将 key 的使用限制在特定的 AWS 服务。`kms:CallerAccount` 限制跨账户访问。如果不解析 policy JSON,这些约束是不可见的。 `kms-audit` 通过一条命令解决了所有这些问题。 ## 用例 `kms-audit` 专为以下场景设计: - **用户证明** — 定期审查确认只有经过授权的 principal 才能使用给定的 AWS KMS key,并通过 IAM Identity Center 解析出真实人员姓名。 - **审计** — 为内部和外部审计(SOC 2、PCI-DSS、HIPAA、ISO 27001)收集证据。CSV 和 PDF 输出专为提交给审计员而设计。 - **治理** — 对跨账户的 key 访问进行持续监督,包括通过 IAM policies、key policies 或 grants 检测意外的访问路径。 ## 快速开始 ``` git clone cd kms-audit pip install . kms-audit --key ``` ## 它的工作原理 ``` kms-audit --key alias/my-production-key --output table ``` 该工具运行一个多步骤的 pipeline: 1. **验证输入** — key ID/ARN/alias 格式、输出格式、profile 名称 2. **解析 key 元数据** — 调用 `kms:DescribeKey` 和 `kms:ListResourceTags` 3. **评估 IAM policies** — 通过 `GetAccountAuthorizationDetails` 加载所有 principal,预过滤掉没有潜在 AWS KMS 访问权限的实体,然后通过 `SimulatePrincipalPolicy` 对每个实体进行模拟 4. **解析 key policy** — 通过 `kms:GetKeyPolicy` 获取,并在本地评估每个语句(IAM 模拟器无法评估 key policies) 5. **枚举 grants** — 对 `kms:ListGrants` 进行分页,根据 key 类型将操作映射到访问级别 6. **合并和去重** — 通过 principal ARN 合并所有三个来源,应用访问级别层次结构,合并 ViaService 约束 7. **解析 IAM Identity Center** *(可选)* — 担任跨账户角色,以映射 SSO 角色 → permission sets → 用户/组 8. **渲染输出** — 格式化为包含完整元数据的表格、JSON、CSV 或 PDF ## 架构 ``` ┌─────────────────────────────────────────────────────────┐ │ Production Account │ │ │ │ ┌──────────────┐ ┌─────────────┐ ┌───────────────┐ │ │ │ KMS │ │ IAM │ │ STS │ │ │ │ DescribeKey │ │ GetAccount │ │ GetCallerID │ │ │ │ GetKeyPolicy │ │ AuthDetails │ │ AssumeRole │ │ │ │ ListGrants │ │ Simulate │ └───────────────┘ │ │ │ ListResTags │ │ Principal │ │ │ └──────────────┘ └─────────────┘ │ └──────────────────────┬──────────────────────────────────┘ │ sts:AssumeRole (optional) ▼ ┌─────────────────────────────────────────────────────────┐ │ Management Account │ │ │ │ ┌──────────────────┐ ┌────────────────────────────┐ │ │ │ SSO Admin │ │ Identity Store │ │ │ │ ListInstances │ │ DescribeUser │ │ │ │ ListPermissionSets│ │ DescribeGroup │ │ │ │ ListAccountAssign │ │ ListGroupMemberships │ │ │ └──────────────────┘ └────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` 该工具**设计为只读**。它从不调用加密操作(`kms:Encrypt`、`kms:Decrypt`、`kms:GenerateDataKey`),也从不修改 IAM policies、key policies 或 grants。 ## 前置条件 - Python 3.11 或更高版本 - 通过 `aws configure`、环境变量或实例 profile 配置的 AWS 凭证 - 对于 IAM Identity Center 解析:管理账户中的跨账户 IAM 角色(请参阅[所需的 IAM 权限](#required-iam-permissions)) ## 安装说明 ``` # 从源码 pip install . # 用于开发(包含测试依赖) pip install -e ".[dev]" ``` ## 依赖项 运行时(在 `pyproject.toml` 中锁定): | Package | Version | Purpose | |---|---|---| | `boto3` | 1.43.6 | AWS SDK — 所有 API 调用 | | `click` | 8.3.3 | CLI 框架 — 参数解析、帮助文本、退出码 | | `reportlab` | 4.4.0 | PDF 报告生成 | 开发/测试: | Package | Version | Purpose | |---|---|---| | `hypothesis` | 6.152.4 | 基于属性的测试 | | `pytest` | 9.0.3 | 测试运行器 | | `ruff` | 0.15.12 | Linter | | `mypy` | 2.0.0 | 类型检查器 | | `bandit` | 1.9.4 | 安全 Linter | 除了 AWS API endpoints 之外,没有任何依赖项进行出站网络调用。 ## 用法 ### 基础用法(表格输出) ``` kms-audit --key alias/my-production-key ``` ### JSON 输出 ``` kms-audit --key alias/my-production-key --output json ``` ### CSV 输出(用于电子表格) ``` kms-audit --key alias/my-production-key --output csv ``` ### PDF 输出(用于审计提交) ``` kms-audit --key alias/my-production-key --output pdf --output-file report.pdf ``` ### 启用 IAM Identity Center 解析 ``` kms-audit --key alias/my-production-key \ --master-profile management-account \ --expand-groups ``` ### 写入文件 ``` kms-audit --key alias/my-production-key --output json --output-file report.json ``` ### 抑制进度消息(用于脚本) ``` kms-audit --key alias/my-production-key --quiet --output json > report.json ``` ### 调整大账户的并发 ``` kms-audit --key alias/my-production-key --workers 10 ``` ### CLI 参考 | Option | Required | Default | Description | |---|---|---|---| | `--key` | 是 | — | AWS KMS key ID (UUID)、key ARN、alias ARN 或 alias 引用 (`alias/`) | | `--output` | 否 | `table` | 输出格式:`table`、`json`、`csv` 或 `pdf` | | `--master-profile` | 否 | — | 用于管理账户的 AWS profile(IAM Identity Center 解析) | | `--expand-groups` | 否 | `false` | 展开 IAM Identity Center 组成员身份以列出单个用户 | | `--output-file` | 否 | — | 将报告写入文件而不是 stdout | | `--quiet` / `-q` | 否 | `false` | 抑制 stderr 上的进度消息 | | `--workers` / `-w` | 否 | `5` | 并发 SimulatePrincipalPolicy worker 的数量 | ## 支持的 Key 类型 该工具通过基于类型的访问级别映射,正确处理所有 AWS KMS key 类型: | Key Type | KeyUsage | Access Levels | |---|---|---| | 对称加密 | ENCRYPT_DECRYPT (SYMMETRIC_DEFAULT) | Admin, Full, Encrypt/Dec, Encrypt, Decrypt, Read | | 非对称签名 | SIGN_VERIFY (RSA, ECC) | Admin, Sign/Verify, Sign, Verify, Read | | 非对称加密 | ENCRYPT_DECRYPT (RSA) | Admin, Encrypt/Dec, Encrypt, Decrypt, Read | | HMAC | GENERATE_VERIFY_MAC (HMAC_256/384/512) | Admin, Mac, GenerateMac, VerifyMac, Read | ## 所需的 IAM 权限 ### 生产账户(key 所在位置) ``` { "Version": "2012-10-17", "Statement": [ { "Sid": "KmsAuditReadOnly", "Effect": "Allow", "Action": [ "kms:DescribeKey", "kms:GetKeyPolicy", "kms:ListGrants", "kms:ListResourceTags", "kms:ListKeys", "kms:ListAliases", "iam:SimulatePrincipalPolicy", "iam:GetAccountAuthorizationDetails", "sts:GetCallerIdentity", "sts:AssumeRole" ], "Resource": "*" } ] } ``` ### 管理账户(用于 IAM Identity Center 解析) ``` { "Version": "2012-10-17", "Statement": [ { "Sid": "KmsAuditIdentityCenterReadOnly", "Effect": "Allow", "Action": [ "sso-admin:ListInstances", "sso-admin:ListPermissionSets", "sso-admin:DescribePermissionSet", "sso-admin:ListAccountAssignments", "identitystore:DescribeUser", "identitystore:DescribeGroup", "identitystore:ListGroupMemberships" ], "Resource": "*" } ] } ``` ## 安全模型 | Guarantee | How it's enforced | |---|---| | 绝不访问 key material | 该工具从不调用任何加密的 AWS KMS 操作 | | 无凭证持久化 | 跨账户凭证仅保存在内存中。不写入任何文件。 | | 无修改操作 | 仅调用 read/list/describe/simulate API。不创建、更新或删除任何内容。 | | 输入验证 | 在任何 API 调用之前,所有 CLI 输入都会针对正则表达式进行验证 | | 输出安全 | 渲染后的输出绝不包含完整的 policy JSON、原始 STS 凭证或 session token | ## 优雅降级 | Scenario | Behavior | |---|---| | Key policy 访问被拒绝 | 生成来自 IAM + grants 的部分报告。包含警告。退出码 2。 | | Grant 枚举被拒绝 | 生成来自 IAM + key policy 的部分报告。包含警告。退出码 2。 | | IAM 模拟失败 | 生成来自 key policy + grants 的部分报告。包含警告。退出码 2。 | | 所有三个来源均失败 | 致命错误。退出码 1。 | | IAM Identity Center 解析失败 | 生成完整的访问报告,SSO 角色仅显示 permission set 名称。退出码 0。 | | Key 被禁用 | 生成报告并附带备注:“This key is currently DISABLED.” | | Key 待删除 | 生成报告并附带警告和计划删除日期。 | 退出码:`0` = 完整报告,`1` = 致命错误,`2` = 部分报告或输入错误。 ## 输出示例 ### 表格 ``` Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab Key ARN: arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab Alias: alias/prod-app-encryption Report generated: 2026-05-09T08:45:00-07:00 Generated by: arn:aws:iam::123456789012:user/audit-engineer Tool: kms-audit v1.0.0 PRINCIPAL TYPE PRINCIPAL NAME IC USER / GROUP ACCESS SOURCE ACCESS LEVEL VIA SERVICE -------------- --------------------------------- ------------------------ ----------------------- ------------ ----------- IAM Role EKSServiceAccount-prod-app-pod N/A IAM Policy Encrypt/Dec s3.us-east-1 IAM Role AWSReservedSSO_DatabaseAdmin_... Alice Smith IAM Policy + Key Policy Full - IAM Role RDSServiceRole N/A Grant Encrypt rds.us-east-1 AWS Service logs.us-east-1.amazonaws.com N/A Key Policy Encrypt/Dec - AWS Account 999888777666 N/A Key Policy Encrypt/Dec - ``` ## 项目结构 ``` kms_audit/ ├── __init__.py # Package version ├── cli.py # Click CLI entry point, input validation ├── orchestrator.py # Sequential audit workflow coordination ├── key_resolver.py # Key ID/ARN/alias resolution via DescribeKey ├── iam_simulator.py # GetAccountAuthorizationDetails + SimulatePrincipalPolicy ├── key_policy_parser.py # Key policy JSON parsing and statement evaluation ├── grant_enumerator.py # ListGrants pagination and grant processing ├── condition_evaluator.py # Local condition key evaluation (ViaService, CallerAccount, ResourceTag) ├── access_merger.py # Three-source merge and deduplication ├── access_level.py # Key-type-aware access level derivation ├── ic_resolver.py # Cross-account IAM Identity Center resolution ├── report_renderer.py # Table, JSON, CSV, and PDF output formatting ├── models.py # Dataclasses and enums └── validators.py # Input validation utilities ``` ## 开发 ``` # 安装 dev dependencies pip install -e ".[dev]" # 运行所有测试(563 个测试:unit + property-based) pytest # 仅运行 property-based tests pytest -m property # 类型检查 mypy kms_audit/ # Lint ruff check kms_audit/ # 安全扫描 bandit -r kms_audit/ ``` ## 已知限制 | Limitation | Impact | Workaround | |---|---|---| | IAM Policy Simulator 速率限制 | ~5 req/sec。拥有 200+ principal 的账户需要 40+ 秒。 | 预过滤减少了调用次数。使用 `--workers` 调整并发。 | | 模拟器不评估 key policies | Key policies 会在本地进行解析。 | 无需操作 — 该工具会自动处理此问题。 | | key policies 中不允许使用 `kms:ResourceTag` | KMS 在 key policies 中拒绝此条件(仅在 IAM policies 中有效)。 | 请改用 IAM policies 中的 `aws:ResourceTag`。该工具会评估两者。 | | 跨账户 principal 访问受警告提示 | 该工具可以在 key policy 中看到跨账户 principal,但无法评估他们在外部账户中的 IAM policies。 | 报告中包含解释此限制的备注。 | | 不支持的 condition keys 被视为已满足 | 支持集合之外的 condition keys 会被标记,但不会被拒绝。 | 保守方法 — 宁可出现假阳性,也不要假阴性。 | ## 常见问题 **该工具会访问我的 key material 吗?** 不会。该工具仅调用 `DescribeKey`、`GetKeyPolicy`、`ListGrants` 和 `ListResourceTags`。它从不调用任何加密操作。代码库明确排除了所有的 crypto API 调用。 **为什么生成报告需要 30+ 秒?** 瓶颈在于 `SimulatePrincipalPolicy`(约 5 req/sec 的速率限制)。该工具会预过滤掉没有 AWS KMS policies 的 principal(节省约 30% 的调用),并将其余的并行化处理。进度消息会向您展示正在进行的操作。 **如果我没有到管理账户的跨账户访问权限怎么办?** 该工具会生成一份完整的访问报告,但不包含 IAM Identity Center 解析。SSO 提供的角色将以它们的 IAM 角色名称显示。当您想将它们解析为真实人员姓名时,请使用 `--master-profile`。 **我可以一次审计多个 keys 吗?** 不能在一次调用中完成。可以编写脚本: ``` for key in alias/key-1 alias/key-2 alias/key-3; do kms-audit --key "$key" --output json --output-file "${key//\//-}.json" --quiet done ``` **为什么报告中会出现 AWS service-linked roles?** 如果 service-linked role 具有授予 `kms:DescribeKey` 的 policy(这对于审计/安全角色很常见),它将以 Read 访问权限出现。这是故意的 — 审计员需要了解全貌。 ## 版本控制 该项目遵循[语义化版本控制](https://semver.org/)。版本号定义在 `pyproject.toml` 和 `kms_audit/__init__.py` 中。它会在每个报告的页眉中显示为 `Tool: kms-audit v1.0.0`。 ``` kms-audit --version ``` ## 许可证 MIT
标签:AWS, DevSecOps, DPI, IAM权限分析, KMS, 上游代理, 云安全审计, 逆向工具