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, 上游代理, 云安全审计, 逆向工具