# awsmap
一个快速、全面的工具,用于映射和盘点跨 150 多种服务和所有区域的 AWS 资源。
## 功能特性
- **150 多种 AWS 服务**:涵盖计算、存储、数据库、网络、安全等
- **多区域**:跨所有已启用区域并行扫描
- **本地数据库**:每次扫描自动存储在 SQLite 中 - 可离线查询您的清单
- **SQL 查询引擎**:针对您的清单历史记录运行 SQL(`awsmap query "SELECT ..."`)
- **预置查询库**:30 个开箱即用的安全与合规查询(`awsmap query -n admin-users`)
- **自然语言查询**:用纯英文提问 - 零依赖,开箱即用(`awsmap ask show me all EC2 without Owner tag`)
- **示例库**:1381 个按服务组织的、随时可运行的问题(`awsmap examples lambda`)
- **多账户**:扫描多个账户,跨所有账户进行查询
- **标签筛选**:按标签筛选 - 同一标签的多个值满足“或”逻辑(Owner=John 或 Jane),不同标签满足“与”逻辑(Owner=John 且 Environment=Production)
- **精美的 HTML 报告**:支持搜索、筛选、深色模式和导出的交互式报告
- **多种输出格式**:支持 JSON、CSV 和 HTML 格式
- **快速**:40 个 worker 并行执行(对于典型账户约需 2 分钟)
- **漂移检测**:随时间比较快照 - 检测添加、删除和修改的资源(`awsmap diff`)
- **闲置资源检测**:从收集的数据中查找闲置或浪费的资源,无需额外调用 API(`awsmap waste`)
- **标签合规性**:审计标签覆盖情况并根据必需标签进行评分(`awsmap tags`)
- **基于扫描范围的查询**:可查询扫描历史中的任何时间点,而不仅仅是当前状态(`awsmap query --scan`、`awsmap ask --scan`)
- **支持控制台登录**:兼容 `aws login` 凭证提供程序
## 安装说明
### PyPI
```
pip install awsmap
```
**环境要求:** Python 3.9+,已配置 AWS 凭证
### Docker
```
docker pull tarekcheikh/awsmap
```
或者在本地构建:
```
git clone https://github.com/TocConsulting/awsmap.git
cd awsmap
docker build -t awsmap .
```
### 开发者安装
```
git clone https://github.com/TocConsulting/awsmap.git
cd awsmap
pip install -e .
```
## Docker 使用方法
```
# 使用 AWS credentials 文件
docker run --rm \
-v ~/.aws:/root/.aws:ro \
-v $(pwd)/output:/app/output \
-v ~/.awsmap:/root/.awsmap \
awsmap -p myprofile -o /app/output/inventory.html
# 使用环境变量
docker run --rm \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_DEFAULT_REGION=us-east-1 \
-v $(pwd)/output:/app/output \
-v ~/.awsmap:/root/.awsmap \
awsmap -o /app/output/inventory.html
# 查询存储的 inventory
docker run --rm \
-v ~/.awsmap:/root/.awsmap \
awsmap query "SELECT service, COUNT(*) as count FROM resources GROUP BY service ORDER BY count DESC"
# 列出可用服务
docker run --rm awsmap --list-services
```
## 用法
```
# 完整 account inventory(所有服务,所有区域,HTML 输出)
awsmap -p myprofile
# 特定服务(逗号分隔或多个 -s 标志)
awsmap -p myprofile -s ec2,s3,rds,lambda,iam
# 特定区域
awsmap -p myprofile -r us-east-1,eu-west-1
# 按 tags 过滤(同一 key 使用 OR 逻辑)
awsmap -p myprofile -t Owner=John -t Owner=Jane -t Environment=Production
# JSON 输出
awsmap -p myprofile -f json -o inventory.json
# 列出可用 collectors
awsmap --list-services
# 显示每个服务的耗时(用于 debugging)
awsmap -p myprofile --timings
# 排除默认的 AWS resources(默认 VPCs、security groups 等)
awsmap -p myprofile --exclude-defaults
# 跳过本地数据库存储
awsmap -p myprofile --no-db
```
## 多账户
扫描多个 AWS 账户。每次扫描都存储在同一个本地数据库中 - 您可以跨所有账户进行查询。
```
# 扫描不同的 accounts(不同的 profiles)
awsmap -p production
awsmap -p staging
awsmap -p dev-account
# 跨所有 accounts 查询
awsmap query -n resources-by-account
awsmap ask how many resources per account
# 限定到一个 account
awsmap query -n admin-users -a production
awsmap ask -a staging show me all Lambda functions
```
## 查询您的资源清单
每次扫描都会自动存储在本地 SQLite 数据库(`~/.awsmap/inventory.db`)中。可以使用原生 SQL 或自然语言离线查询。
### SQL 查询
```
# 统计每个 service 的 resources 数量
awsmap query "SELECT service, COUNT(*) as count FROM resources GROUP BY service ORDER BY count DESC"
# 查找特定区域内的所有 EC2 实例
awsmap query "SELECT id, name, region FROM resources WHERE service='ec2' AND type='instance'"
# 查看扫描历史
awsmap query "SELECT * FROM scans ORDER BY timestamp DESC"
# JSON 或 CSV 输出
awsmap query "SELECT * FROM resources WHERE service='s3'" -f json
awsmap query "SELECT service, id, name FROM resources" -f csv
# 查询 tags(过滤出具有该 tag 的 resources)
awsmap query "SELECT id, name, json_extract(tags, '$.Owner') as owner FROM resources WHERE service='ec2' AND json_extract(tags, '$.Owner') IS NOT NULL"
```
**更多 SQL 示例:** 请参阅 `examples/queries/*.sql` 获取可自定义的、开箱即用的查询模板。
### 预置查询库
awsmap 内置了 30 个预置查询,用于常见的安全、合规和运维任务。无需 SQL 知识。
```
# 列出所有可用查询
awsmap query --list
# 运行命名查询
awsmap query -n admin-users
awsmap query -n users-without-mfa
awsmap query -n open-security-groups
awsmap query -n untagged-resources
# 传递参数(查找带有 Owner tag 的 resources)
awsmap query -n resources-by-tag -P tag=Owner
# 多个参数(查找缺少 Environment tag 的 EC2)
awsmap query -n missing-tag -P tag=Environment -P service=ec2
# 限定到特定 account
awsmap query -n admin-users -a production
# 显示查询 SQL 而不运行
awsmap query --show admin-users
# 从文件运行 SQL
awsmap query -F my-query.sql
```
**参数格式:** 使用 `-P parameter=value`,其中 `parameter` 是查询参数名(例如 `tag`、`service`),而 `value` 是您要搜索的内容。示例:`-P tag=Owner` 表示“按 Owner 标签筛选”(而不是 `-P Owner=SomeValue`)。
**可用查询:**
| 查询 | 描述 | 示例 |
|-------|-------------|---------|
| **IAM / 安全** | | |
| `admin-users` | 具有管理员权限的 IAM 用户(直接权限和通过组获取的权限) | `awsmap query -n admin-users` |
| `admin-roles` | 具有管理员权限的 IAM 角色 | `awsmap query -n admin-roles` |
| `users-without-mfa` | 未启用 MFA 的 IAM 用户 | `awsmap query -n users-without-mfa` |
| `iam-inactive-users` | 没有登录凭证且没有访问密钥的 IAM 用户 | `awsmap query -n iam-inactive-users` |
| `old-access-keys` | 拥有访问密钥的 IAM 用户 | `awsmap query -n old-access-keys` |
| `cross-account-roles` | 信任策略允许外部账户访问的 IAM 角色 | `awsmap query -n cross-account-roles` |
| `open-security-groups` | 包含 0.0.0.0/0 入站规则的 Security group | `awsmap query -n open-security-groups` |
| `secrets-no-rotation` | 未开启自动轮换的 Secrets Manager 密钥 | `awsmap query -n secrets-no-rotation` |
| **S3** | | |
| `public-s3-buckets` | 启用了公开访问权限的 S3 存储桶 | `awsmap query -n public-s3-buckets` |
| `encryption-status` | S3 存储桶及其加密配置 | `awsmap query -n encryption-status` |
| `s3-no-versioning` | 未启用版本控制的 S3 存储桶 | `awsmap query -n s3-no-versioning` |
| `s3-no-logging` | 未启用访问日志记录的 S3 存储桶 | `awsmap query -n s3-no-logging` |
| **EC2 / EBS** | | |
| `stopped-instances` | 处于停止状态的 EC2 实例 | `awsmap query -n stopped-instances` |
| `unused-volumes` | 未挂载到任何实例的 EBS 卷 | `awsmap query -n unused-volumes` |
| `ebs-unencrypted` | 未加密的 EBS 卷 | `awsmap query -n ebs-unencrypted` |
| `unused-eips` | 未关联到任何实例的 Elastic IP | `awsmap query -n unused-eips` |
| `default-vpcs` | 跨所有区域的默认 VPC | `awsmap query -n default-vpcs` |
| **RDS** | | |
| `rds-public` | 启用了公开访问的 RDS 实例 | `awsmap query -n rds-public` |
| `rds-unencrypted` | 未加密的 RDS 实例 | `awsmap query -n rds-unencrypted` |
| `rds-no-multi-az` | 未启用 Multi-AZ 的 RDS 实例 | `awsmap query -n rds-no-multi-az` |
| `rds-engines` | 按引擎分组的 RDS 实例 | `awsmap query -n rds-engines` |
| **Lambda** | | |
| `lambda-runtimes` | 按 runtime 分组的 Lambda 函数 | `awsmap query -n lambda-runtimes` |
| `lambda-high-memory` | 内存大于 512 MB 的 Lambda 函数 | `awsmap query -n lambda-high-memory` |
| **标签** | | |
| `untagged-resources` | 没有任何标签的资源 | `awsmap query -n untagged-resources` |
| `missing-tag` | 缺少特定标签的资源 | `awsmap query -n missing-tag -P tag=Owner` |
| `resources-by-tag` | 包含特定标签的资源 | `awsmap query -n resources-by-tag -P tag=Owner` |
| **清单** | | |
| `resources-by-service` | 每个服务的资源数量 | `awsmap query -n resources-by-service` |
| `resources-by-region` | 每个区域的资源数量 | `awsmap query -n resources-by-region` |
| `resources-by-account` | 每个账户的资源数量 | `awsmap query -n resources-by-account` |
| `resources-per-account-service` | 每个账户中每个服务的资源数量 | `awsmap query -n resources-per-account-service` |
您也可以通过将 `.sql` 文件放在 `~/.awsmap/queries/` 目录中来添加您自己的查询。请使用与内置查询相同的头部格式(`-- name:`、`-- description:`、`-- params:`)。
### 自然语言查询
使用 `awsmap ask` 用简单的英文提问关于您的资源清单的问题。**无需任何设置** - 内置零依赖解析器,开箱即用。
```
awsmap ask how many resources per region
awsmap ask show me all EC2 instances without Owner tag
awsmap ask which S3 buckets are in eu-west-1
awsmap ask what services have the most resources
```
awsmap 使用**内置解析器**(零依赖)将您的问题转换为 SQL,向您展示生成的查询,并显示结果。
### 示例库
使用 `awsmap examples` 浏览并运行按 AWS 服务组织的 1381 个预置问题。
```
# 列出带有问题数量的所有服务
awsmap examples
# 浏览某个服务的问题
awsmap examples lambda
# 按编号运行特定问题
awsmap examples lambda 5
# 跨所有问题搜索
awsmap examples --search "public"
awsmap examples --search "encryption"
```
#### 多账户查询
当扫描了多个账户时,`awsmap ask` 默认会查询所有账户。使用 `-a` 限定在单个账户范围内:
```
# 跨所有 accounts 查询
awsmap ask show me all IAM users
# 限定到一个 account
awsmap ask -a production show me Lambda functions
```
## 漂移检测
随时间比较 AWS 清单快照,以检测发生了哪些变化 - 添加、删除或修改的资源。
```
# 最近一次扫描更改了什么?(无参数:上次扫描与当前的比较)
awsmap diff
# 过去 7 天内更改了什么?
awsmap diff --from 7d
# 比较两个特定日期
awsmap diff --from 2026-01-15 --to 2026-02-09
# 限定到特定服务
awsmap diff --from 30d -s ec2,s3
# 限定到特定 account(按 profile name、alias 或 account ID)
awsmap diff --from 7d -a production -r us-east-1
# 仅显示已添加或已移除的 resources
awsmap diff --from 7d --type added
awsmap diff --from 7d --type removed
# 仅显示摘要(无 resource 详情)
awsmap diff --from 7d --summary
# 忽略仅 tag 的更改
awsmap diff --from 30d --ignore-tags
# JSON 输出
awsmap diff --from 7d -f json -o drift-report.json
# HTML 报告(交互式,带 filters 和 dark mode)
awsmap diff --from 7d -f html -o drift-report.html
```
**工作原理:** awsmap 从您的扫描历史中重建时间点快照。对于每个 `(account, service)`,它会找到在给定日期或之前进行的最新扫描,然后逐字段比较两个快照。这能正确处理部分扫描 - 如果您在周一扫描了 EC2,在周二扫描了 S3,每个服务都会使用各自最新的扫描结果。
如果不指定 `--from`,`awsmap diff` 会将最近一次扫描之前的状态与当前状态进行比较,以便您准确查看最新扫描更改了什么。如果只指定 `--to` 而没有 `--from`,则默认将 `--from` 设为紧邻 `--to` 之前的扫描。
**相对日期:** `7d`、`30d`、`90d`、`yesterday`、`today`,或者精确日期如 `2026-01-15`。
**变更类型:**
- **Added** - 资源存在于较新的快照中,但在较旧的快照中不存在
- **Removed** - 资源存在于较旧的快照中,但在较新的快照中不存在
- **Modified** - 资源在两个快照中都存在,但详细信息、标签或名称发生了更改(带有字段级别的差异)
## 闲置资源检测
从 awsmap 已经收集的数据中查找闲置或可能浪费的资源。无需调用新的 AWS API - 规则将针对您最新存储的快照运行。
```
# 对当前 snapshot 运行所有 rules
awsmap waste
# 仅统计每条 rule 的数量
awsmap waste --summary
# 限定到一个 account(按 profile name、alias 或 account ID)
awsmap waste -a production
# 仅运行特定 rules
awsmap waste -t unattached-ebs -t available-eni
# 更改 snapshots 和 AMIs 的 age threshold(默认 90 天)
awsmap waste --min-age-days 180
# 包含默认的 AWS resources(默认排除)
awsmap waste --include-defaults
# HTML 报告(交互式,带 filters 和 dark mode)
awsmap waste -f html -o waste.html
```
**规则:**
| 规则 Key | 标记内容 |
|----------|---------------|
| `unattached-ebs` | 处于 `available` 状态的 EBS 卷 |
| `unassociated-eip` | 未绑定到实例或网卡的 Elastic IP |
| `available-eni` | 处于 `available`(未挂载)状态的网络接口 |
| `idle-target-group` | 没有注册目标的目标组 |
| `empty-classic-elb` | 没有实例的 Classic Load Balancer |
| `old-snapshot` | 存在时间超过 `--min-age-days`(默认为 90)的 EBS 快照 |
| `old-ami` | 存在时间超过 `--min-age-days`(默认为 90)的 AMI |
| `stopped-instance` | 处于 `stopped` 状态的 EC2 实例 |
awsmap 会报告数量以及需要处理的资源。它不会估算资金成本。输出格式可以是 `table`(默认)、`json` 或 `html`;除非您传入 `--include-defaults`,否则将排除 `is_default` 资源。
## 标签合规性
审计整个资源清单中的标签覆盖情况,并根据一组必需的标签进行评分。基于已收集的数据运行。
```
# “至少有一个 tag”的覆盖率
awsmap tags
# 针对所需 tags 的合规性
awsmap tags -R Owner,Environment,CostCenter
# 限定到一个 account 和 service,仅列出不合规模 resources
awsmap tags -a production -s ec2 --noncompliant-only
# 仅列出没有 tags 的 resources
awsmap tags --untagged-only
# 仅显示分数,不列出 resources
awsmap tags -R Owner --summary
# HTML 报告
awsmap tags -R Owner,Environment -f html -o tag-compliance.html
```
报告会显示总体合规性评分、每个必需标签的覆盖率(以便您找出差距所在)、各服务的分类明细,以及不合规资源及其缺失标签的列表。
- 必需标签来源于 `-R/--required`(逗号分隔或可重复使用)或 `required_tags` 配置项。如果两者都未设置,合规性检查将退化为“至少拥有一个标签”。
- 空的标签值(例如 `Owner=`)将被视为缺失。
- 默认情况下排除 `is_default` 资源;传入 `--include-defaults` 可保留它们。
- 设置一次默认的必需标签集:`awsmap config set required_tags Owner,Environment,CostCenter`。
- 输出格式为 `table`(默认)、`json` 或 `html`。
## 查询特定扫描
默认情况下,`query` 和 `ask` 针对当前快照(`is_current`)运行。使用 `--scan` 可以指向您历史记录中的任何一次扫描。
```
# 列出存储的 scans
awsmap query --list-scans
# 对上次 scan 运行命名查询
awsmap query --scan previous -n admin-users
# 针对最新 scan 的原始 SQL(使用 {scan_filter} 占位符)
awsmap query --scan latest "SELECT service, COUNT(*) FROM resources WHERE {scan_filter} GROUP BY service"
# 针对第一次(最旧)scan 的自然语言
awsmap ask --scan first show me ec2 instances
```
选择器:`latest`、`previous`、`first`,或者显式指定 `
`(参见 `--list-scans`)。命名查询、文件和 `ask` 会自动应用该范围。对于原始内联 SQL,请在范围应用的位置包含 `{scan_filter}` 占位符;如果在没有占位符的原始 SQL 上使用 `--scan`,将会报错,而不是运行未加限制查询。
## 演示数据库
生成一个真实的合成数据库,无需 AWS 账户即可试用 awsmap。涵盖所有 150 多种服务、多个账户以及带有漂移的多次扫描。
```
# 使用默认值生成(3 个 accounts,3 个 scans,约 12,000 个 resources)
awsmap demo
# 自定义选项
awsmap demo --accounts 2 --scans 5 --db ./demo.db
# 覆盖现有的
awsmap demo --force
```
生成后,使用 `--db` 将任何命令指向演示数据库:
```
awsmap query --db ~/.awsmap/demo.db -n admin-users
awsmap ask --db ~/.awsmap/demo.db show me all EC2 instances
awsmap diff --db ~/.awsmap/demo.db --from 30d
awsmap examples lambda 5 --db ~/.awsmap/demo.db
```
或者将其设置为默认数据库:
```
awsmap config set db ~/.awsmap/demo.db
```
### 演示选项 (`awsmap demo`)
| 选项 | 描述 |
|--------|-------------|
| `--db` | 数据库路径(默认:`~/.awsmap/demo.db`) |
| `--accounts` | 要生成的账户数量(1-5,默认:3) |
| `--scans` | 每个账户用于生成漂移的扫描次数(1-5,默认:3) |
| `--seed` | 用于结果可重复的随机种子(默认:42) |
| `--force` | 覆盖现有的演示数据库 |
## CLI 选项
### 扫描选项
| 选项 | 描述 |
|--------|-------------|
| `-p, --profile` | AWS profile 名称 |
| `-r, --region` | 要扫描的区域(逗号分隔或使用多个标志) |
| `-s, --services` | 要扫描的服务(逗号分隔或使用多个标志) |
| `-t, --tag` | 按 Key=Value 过滤标签(允许多次使用) |
| `-f, --format` | 输出格式:`html`(默认)、`json`、`csv` |
| `-o, --output` | 输出文件路径 |
| `-w, --workers` | 并行 worker 数量(默认:40) |
| `-q, --quiet` | 抑制进度输出 |
| `--timings` | 显示每个服务的时间摘要 |
| `--include-global` | 在按非全局区域过滤时包含全局服务 |
| `--exclude-defaults` | 排除默认的 AWS 资源(默认 VPC、安全组等) |
| `--no-db` | 跳过本地数据库存储 |
| `--list-services` | 列出可用的服务收集器 |
### 查询选项 (`awsmap query`)
| 选项 | 描述 |
|--------|-------------|
| `-n, --name` | 运行预置的命名查询 |
| `-F, --file` | 从文件运行 SQL |
| `-l, --list` | 列出可用的预置查询 |
| `-S, --show` | 显示命名查询的 SQL 而不运行它 |
| `-P, --param` | 命名查询的参数(`key=value`,允许多次使用) |
| `-a, --account` | 限定在一个账户范围内(账户 ID、账户别名或 AWS profile) |
| `--scan` | 限定在一次扫描范围内:`latest`、`previous`、`first` 或 ``(原生 SQL 需要包含 `{scan_filter}` 占位符) |
| `--list-scans` | 列出已存储的扫描并退出 |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
| `-f, --format` | 输出格式:`table`(默认)、`json`、`csv` |
### 提问选项 (`awsmap ask`)
| 选项 | 描述 |
|--------|-------------|
| `-a, --account` | 限定在一个账户范围内(账户 ID、账户别名或 AWS profile) |
| `--scan` | 限定在一次扫描范围内:`latest`、`previous`、`first` 或 `` |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
### 差异选项 (`awsmap diff`)
| 选项 | 描述 |
|--------|-------------|
| `--from` | 用于比较的起始日期。支持:`YYYY-MM-DD`、`7d`、`30d`、`yesterday`、`today`。如省略,则将上一次扫描与当前状态进行比较 |
| `--to` | 结束日期(默认:当前状态)。日期格式与 `--from` 相同 |
| `-a, --account` | 限定在一个账户范围内(账户 ID、别名或 profile) |
| `-s, --service` | 要比较的服务(逗号分隔或使用多个标志) |
| `-r, --region` | 要比较的区域(逗号分隔或使用多个标志) |
| `--type` | 仅显示一种变更类型:`all`(默认)、`added`、`removed` 或 `modified` |
| `--summary` | 仅显示汇总数量,无资源详细信息 |
| `--ignore-tags` | 忽略仅有标签变更的情况 |
| `-f, --format` | 输出格式:`table`(默认)、`json`、`html` |
| `-o, --output` | 输出文件路径 |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
### 闲置检测选项 (`awsmap waste`)
| 选项 | 描述 |
|--------|-------------|
| `-a, --account` | 限定在一个账户范围内(账户 ID、别名或 profile) |
| `-t, --type` | 仅运行特定的规则 key(逗号分隔或使用多个标志) |
| `--min-age-days` | 针 `old-snapshot` 和 `old-ami` 的存在天数阈值(默认:90) |
| `--include-defaults` | 包含默认的 AWS 资源(默认排除) |
| `--summary` | 仅显示每条规则的数量,不列出具体资源 |
| `-f, --format` | 输出格式:`table`(默认)、`json`、`html` |
| `-o, --output` | 输出文件路径 |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
### 标签选项 (`awsmap tags`)
| 选项 | 描述 |
|--------|-------------|
| `-R, --required` | 必需的标签 key(逗号分隔或可多次使用)。退化为使用 `required_tags` 配置项 |
| `-a, --account` | 限定在一个账户范围内(账户 ID、别名或 profile) |
| `-s, --service` | 限定在特定服务范围内(逗号分隔或使用多个标志) |
| `--untagged-only` | 仅列出没有任何标签的资源 |
| `--noncompliant-only` | 仅列出缺少必需标签的资源 |
| `--include-defaults` | 包含默认的 AWS 资源(默认排除) |
| `--summary` | 仅显示评分,不列出具体资源 |
| `-f, --format` | 输出格式:`table`(默认)、`json`、`html` |
| `-o, --output` | 输出文件路径 |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
### 示例选项 (`awsmap examples`)
| 参数 / 选项 | 描述 |
|-------------------|-------------|
| `` | 显示特定服务的问题 |
| ` ` | 针对数据库运行第 N 个问题 |
| `-s, --search` | 按关键字搜索所有问题 |
| `--db` | 数据库路径(默认:`~/.awsmap/inventory.db`) |
### 配置命令 (`awsmap config`)
设置持久化默认值,这样就不必重复输入 CLI 参数。CLI 参数始终会覆盖配置值。
仅接受下面列出的 key - 未知的 key 和无效的值将被拒绝。如果手动编辑了配置文件且包含无效条目,`awsmap config list` 会检测到它们,向您发出警告,并自动清理该文件。
| 命令 | 描述 |
|---------|-------------|
| `awsmap config set key value` | 设置配置值(已验证) |
| `awsmap config get key` | 获取配置值 |
| `awsmap config list` | 列出所有配置值(检测并清理无效条目) |
| `awsmap config delete key` | 删除配置值 |
**可用的配置 key(仅接受这些项):**
| Key | 应用对象 | 描述 | 示例 |
|-----|-----------|-------------|---------|
| `profile` | `awsmap` (扫描) | 默认 AWS profile | `awsmap config set profile production` |
| `regions` | `awsmap` (扫描) | 默认区域(逗号分隔) | `awsmap config set regions us-east-1,eu-west-1` |
| `services` | `awsmap` (扫描) | 默认服务(逗号分隔) | `awsmap config set services ec2,s3,lambda` |
| `format` | `awsmap` (扫描) | 默认输出格式(`html`、`json`、`csv`) | `awsmap config set format json` |
| `workers` | `awsmap` (扫描) | 默认并行 worker 数 | `awsmap config set workers 20` |
| `exclude_defaults` | `awsmap` (扫描) | 排除默认的 AWS 资源(`true`/`false`) | `awsmap config set exclude_defaults true` |
| `db` | `query`、`ask` | 默认数据库路径 | `awsmap config set db /path/to/inventory.db` |
| `query_format` | `query` | 默认查询输出格式(`table`、`json`、`csv`) | `awsmap config set query_format csv` |
| `required_tags` | `tags` | 默认必需标签 key(逗号分隔) | `awsmap config set required_tags Owner,Environment,CostCenter` |
```
# 设置您常用的 profile 和 regions
awsmap config set profile production
awsmap config set regions us-east-1,eu-west-1
# 现在只需运行:
awsmap
# 等同于:awsmap -p production -r us-east-1,eu-west-1
# CLI 标志仍然覆盖 config:
awsmap -p staging # Uses staging profile, but regions from config
```
## Shell 自动补全
awsmap 支持 bash、zsh 和 fish 的 Tab 键补全。可补全子命令、服务名称、区域、AWS profile、查询名称、账户名称和配置 key。
```
# Bash
eval "$(awsmap completion bash)" # add to ~/.bashrc
# Zsh
eval "$(awsmap completion zsh)" # add to ~/.zshrc
# Fish
awsmap completion fish > ~/.config/fish/completions/awsmap.fish
```
**补全内容:**
| 上下文 | 补全项 |
|---------|-------------|
| `awsmap ` | 子命令:ask、config、completion、demo、diff、examples、query |
| `awsmap -s ` | 服务名称(ec2、s3、lambda、...) |
| `awsmap -r ` | AWS 区域名称 |
| `awsmap -p ` | 来自 ~/.aws/credentials 和 ~/.aws/config 的 AWS profile 名称 |
| `awsmap query -n ` | 预置查询名称 |
| `awsmap query -a ` | 来自数据库的账户别名、profile 和 ID |
| `awsmap config set ` | 有效的配置 key |
| `awsmap examples ` | 来自示例库的服务名称 |
## 支持的服务
| 类别 | 服务 |
|----------|----------|
| **计算** | ec2, lambda, ecs, eks, ecr, ecr-public, lightsail, autoscaling, application-autoscaling, elasticbeanstalk, batch, apprunner, imagebuilder |
| **存储** | s3, efs, fsx, backup, datasync, dlm, storagegateway |
| **数据库** | rds, dynamodb, elasticache, memorydb, docdb, neptune, redshift, redshift-serverless, keyspaces, opensearch, opensearch-serverless, dax, dsql, timestream-influxdb |
| **网络** | vpc, elbv2, elb, route53, route53resolver, route53domains, cloudfront, globalaccelerator, apigateway, apigatewayv2, appsync, directconnect, network-firewall, servicediscovery, vpc-lattice, networkmanager |
| **安全** | iam, sso, kms, secretsmanager, acm, acm-pca, wafv2, guardduty, inspector2, securityhub, ds, cognito, accessanalyzer, macie2, detective, shield, fms, cloudhsmv2, auditmanager, securitylake |
| **管理与监控** | cloudwatch, logs, cloudtrail, ssm, config, sns, sqs, events, xray, grafana, amp, ce, budgets, compute-optimizer, service-quotas, resource-groups, health, synthetics, appconfig, organizations, servicecatalog, resiliencehub |
| **Serverless** | stepfunctions, kinesis, firehose, kafka, serverlessrepo, eventbridge-scheduler, eventbridge-pipes, schemas |
| **开发者工具** | cloudformation, codeartifact, codebuild, codepipeline, codedeploy, devicefarm |
| **数据分析** | athena, glue, mwaa, lakeformation, emr, emr-serverless, cleanrooms, quicksight, datazone |
| **AI/ML** | sagemaker, bedrock, lexv2, rekognition, textract, transcribe, translate, comprehend, polly, personalize, kendra, frauddetector |
| **媒体** | mediaconvert, mediaconnect, mediapackage, medialive, mediastore, mediatailor ivs |
| **迁移与传输** | transfer, dms |
| **终端用户计算** | workspaces, amplify, connect |
| **IoT** | iot, iotsitewise |
| **其他** | ram, resource-explorer-2, mq, sesv2, appflow, gamelift, outposts, fis, location |
有关各服务详细的资源类型,请参见 [SERVICES.md](SERVICES.md)。
## 输出格式
### HTML(默认)
交互式报告包含:
- 带有资源数量和图表的仪表板
- 跨所有资源的全局搜索
- 按服务和区域筛选
- 可折叠的服务部分
- 点击复制 ARN/ID
- 可点击的标签徽章(显示所有标签)
- 深色/浅色模式切换
- 将筛选后的视图导出为 CSV
- 适合打印
### JSON
```
{
"metadata": {
"account_id": "123456789012",
"timestamp": "2024-12-24 15:30:00 UTC",
"resource_count": 1590
},
"resources": [
{
"service": "ec2",
"type": "instance",
"id": "i-1234567890abcdef0",
"arn": "arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0",
"name": "my-instance",
"region": "us-east-1",
"is_default": false,
"details": {...},
"tags": {"Owner": "John", "Environment": "Production"}
}
]
}
```
### CSV
扁平格式,包含列:service, type, id, name, region, arn, is_default, tags
## 标签筛选
```
# 单个 tag
awsmap -t Environment=Production
# 同一 key 的多个值(OR 逻辑)
awsmap -t Owner=John -t Owner=Jane
# 返回 Owner 为 "John" 或 "Jane" 的 resources
# 多个 keys(AND 逻辑)
awsmap -t Owner=John -t Environment=Production
# 返回 Owner 为 "John" 且 Environment 为 "Production" 的 resources
# 组合
awsmap -t Owner=John -t Owner=Jane -t Environment=Production
# 返回 (Owner 为 "John" 或 "Jane") 且 Environment 为 "Production" 的 resources
```
## 全局服务与区域服务
AWS 有两种类型的服务:
- **区域服务**(EC2、RDS、Lambda 等) - 资源存在于特定区域
- **全局服务**(IAM、Route53、CloudFront 等) - 资源是账户级别的,不特定于某个区域
### awsmap 如何处理全局服务
当您按区域过滤时,awsmap 会根据它们的**控制面位置**智能地包含全局服务:
| 命令 | 行为 |
|---------|----------|
| `awsmap`(无区域) | 所有服务(区域 + 全局) |
| `awsmap -r us-east-1` | us-east-1 中的区域服务 + 控制面位于 us-east-1 的全局服务 |
| `awsmap -r us-west-2` | us-west-2 中的区域服务 + 控制面位于 us-west-2 的全局服务 |
| `awsmap -r eu-west-1` | 仅 eu-west-1 中的区域服务(无全局服务) |
| `awsmap -r eu-west-1 --include-global` | eu-west-1 中的区域服务 + 所有全局服务 |
### 按控制面分类的全局服务
基于 [AWS Global Services 文档](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/global-services.html):
| 控制面 | 全局服务 |
|---------------|-----------------|
| **us-east-1** | IAM, Organizations, Route53, Route53 Domains, CloudFront, Shield, Budgets, Cost Explorer, Health |
| **us-west-2** | Network Manager, Global Accelerator |
### S3 存储桶
S3 存储桶名称是全局唯一的,但**每个存储桶都有特定的区域**。awsmap 将 S3 视为区域服务:
```
# 仅 eu-west-1 中的 S3 buckets
awsmap -r eu-west-1 -s s3
# 所有 S3 buckets
awsmap -s s3
```
## 性能表现
并行扫描跨所有区域的 **150 多种服务**。
| 账户规模 | 资源数量 | 预计耗时 |
|--------------|-----------|----------------|
| 小型 | <500 | ~1.5 分钟 |
| 中型 | 500-5,000 | ~2 分钟 |
| 大型 | 5,000-20,000 | ~3-5 分钟 |
| 企业级 | 20,000+ | ~5-10 分钟 |
**调优选项:**
```
# 提高 parallelism 以加快扫描速度
awsmap -p myprofile -w 50
# 为受速率限制的 accounts 降低 parallelism
awsmap -p myprofile -w 20
# 仅扫描特定服务(速度更快)
awsmap -p myprofile -s ec2,s3,lambda,iam
# 仅扫描特定区域
awsmap -p myprofile -r us-east-1,eu-west-1
```
**为什么扫描很快?**
- 可配置 worker 的并行执行(默认:40)
- 感知区域的收集器会自动跳过不支持的 region
- 全局服务(IAM、Route53 等)只收集一次,而不是按区域收集
- 智能区域过滤在不相关时排除全局服务
- 优化的 API 调用(在可用时使用批量操作)
## IAM 权限
只有扫描操作(`awsmap`)会调用 AWS,并且它需要对您想要盘点的服务具有只读访问权限。分析命令(`query`、`ask`、`diff`、`waste`、`tags`)完全在本地数据库上运行,不需要任何 AWS 权限。
除了针对具体服务的读取操作外,扫描过程还会调用 `sts:GetCallerIdentity`、`account:ListRegions`(用于发现已启用的区域;如果被拒绝,则回退到内置区域列表),以及 `iam:ListAccountAliases`(用于获取账户别名)。
### 推荐:ReadOnlyAccess 加少量补充
挂载 AWS 托管的 [`ReadOnlyAccess`](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html) 策略。它由 AWS 维护,涵盖了 awsmap 绝大多数的读取调用。
然而,`ReadOnlyAccess` 并没有覆盖所有内容:它在一些较新的服务上存在滞后(Amazon Location、MediaTailor、Timestream for InfluxDB、Textract adapters),并且故意省略了一些读取操作(例如 `glue:GetConnections`)。awsmap 调用了 26 个未被 `ReadOnlyAccess` 授权的读取操作。这些操作是通过对 awsmap 确切的 API 调用与实时的 `ReadOnlyAccess` 文档进行差异对比得出的,因此该列表是精确的差异结果,而不是猜测。
将此补充策略与 `ReadOnlyAccess` 一并挂载:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "awsmapSupplementalReadOnly",
"Effect": "Allow",
"Action": [
"airflow:GetEnvironment",
"bedrock:ListTagsForResource",
"codeartifact:ListPackageGroups",
"fms:GetResourceSet",
"fms:ListResourceSets",
"geo:ListGeofenceCollections",
"geo:ListMaps",
"geo:ListPlaceIndexes",
"geo:ListRouteCalculators",
"geo:ListTrackers",
"glue:GetConnections",
"mediatailor:ListChannels",
"mediatailor:ListPlaybackConfigurations",
"mediatailor:ListSourceLocations",
"quicksight:ListAnalyses",
"quicksight:ListDashboards",
"quicksight:ListDataSets",
"quicksight:ListDataSources",
"quicksight:ListTagsForResource",
"rekognition:DescribeCollection",
"textract:GetAdapter",
"textract:ListAdapters",
"timestream-influxdb:GetDbInstance",
"timestream-influxdb:ListDbInstances",
"timestream-influxdb:ListDbParameterGroups",
"timestream-influxdb:ListTagsForResource"
],
"Resource": "*"
}
]
}
```
将两者都挂载到角色上(或者对用户使用 `attach-user-policy`):
```
# 1. 附加 AWS 托管的 ReadOnlyAccess policy
aws iam attach-role-policy \
--role-name YourRoleName \
--policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
# 2. 从上面的 JSON 创建补充 policy 并附加它
aws iam create-policy \
--policy-name awsmap-supplemental-readonly \
--policy-document file://awsmap-supplemental-readonly.json
aws iam attach-role-policy \
--role-name YourRoleName \
--policy-arn arn:aws:iam:::policy/awsmap-supplemental-readonly
```
每个收集器调用都经过了封装,因此拒绝权限永远不会中断扫描:受影响的资源只会被跳过。该补充策略仅消除了这些盲区,从而使资源清单完整。所有 26 个操作均为只读。
### 替代方案:不使用托管策略
如果您无法使用 `ReadOnlyAccess`,请为 awsmap 扫描的服务授予读取操作(`Describe*`、`List*`、`Get*`,以及适用的 `BatchGet*`/`Search*`),并加上上述的补充操作。完整的独立列表涵盖大约 150 个服务前缀;有关具体服务的读取操作,请参见 [IAM Service Authorization Reference](https://docs.aws.amazon.com/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html)。
## 不会被收集的内容
此工具仅收集**用户拥有的资源**,不包括:
- AWS 托管策略(仅限客户托管策略)
- AWS 托管的 KMS key(仅限客户托管)
- 默认的参数组和选项组
- AWS 服务相关角色
- 预留实例产品(定价目录)
- 基础模型(Bedrock 目录)
- 自动备份(仅限手动快照)
- AWS 系统 keyspace(Keyspaces:`system_*`)
- AWS 默认队列/组(MediaConvert、X-Ray)
- AWS 托管域列表(Route53 Resolver:`AWSManagedDomains*`)
- 默认数据湖设置(Lake Formation)
**默认 VPC 资源**(默认 VPC、子网、安全组、路由表、互联网网关、NACL、DHCP 选项)默认会被收集,并在 HTML 报告中带有“DEFAULT”徽章标记。使用 `--exclude-defaults` 将其过滤掉。
有关已过滤资源的完整列表,请参见 [SERVICES.md](SERVICES.md#filtered-resources)。
## 为什么使用内置 NLQ 解析器而不是 AI/LLM?
我们评估了自然语言查询的三种方法:
| 方法 | 准确率 | 成本 | 延迟 | 离线支持 |
|----------|----------|------|---------|---------|
| **Ollama(本地 LLM)** | ~80% | 免费 | 慢(数秒) | 是 |
| **OpenAI / Anthropic APIs** | ~95% | 按次查询付费 | 依赖网络 | 否 |
| **内置解析器 (awsmap)** | **100%** | **免费** | **即时** | **是** |
- **Ollama** 模型是免费的并且在本地运行,但在针对真实的 AWS 清单查询进行测试时,准确率约为 80% - 五分之一的查询会生成错误的 SQL 或静默失败。对于一个用户信任其输出的 CLI 工具来说,这是不可接受的。
- **OpenAI / Anthropic APIs** 会产生更好的结果,但需要 API key,每次查询都要花钱,并且依赖于网络连接。对于一个本该正常工作的基础设施工具来说,这并不理想。
- **内置解析器** 是一个零依赖、确定性的 NL-to-SQL 引擎。它通过了 **1500 个真实测试问题(100% 通过率)**(与 1381 个示例库分开)。它涵盖了列表、计数、聚合、区域过滤、否定、标签、多服务查询、同义词、拼写错误容错、相对时间、数字字段、关键字-值模式以及 150 多种 AWS 服务。无需 API key,无需网络,无成本,即时返回结果。
这 1500 个测试问题(在开发期间用于验证解析器)旨在涵盖绝大多数的真实使用场景。该解析器还包括拼写错误容错、同义词支持和模糊匹配,以处理人们在表达问题时的自然变化。
## 支持
- **文档**:查阅本 README 和 [SERVICES.md](SERVICES.md)
- **问题**:通过 [GitHub Issues](https://github.com/TocConsulting/awsmap/issues) 报告 Bug
- **讨论**:在 [GitHub Discussions](https://github.com/TocConsulting/awsmap/discussions) 中参与交流
## 许可证
本项目基于 MIT 许可证授权 - 详情请参阅 [LICENSE](LICENSE) 文件。