AWS Infrastructure Inventory
Ported from the power-aws-inventory Kiro Power (github.com/aquavis12/power-aws-inventory). Same 109-category scan logic and Excel output — adapted here to run over the Bash tool and AWS CLI/boto3 directly, since Claude Code doesn't need an MCP proxy for this: it already has native shell access.
Step 1: Validate AWS Session
- Run
aws sts get-caller-identity via Bash to confirm credentials.
- Record account ID, caller ARN, and default region.
- Report: "Authenticated as
<arn> in account <accountId>"
Profile handling: If the default profile points to the wrong account, check aws configure list-profiles, verify with aws sts get-caller-identity --profile <name>, and ask the user which profile/region to use — pass --profile explicitly on every subsequent call rather than mutating their environment.
If credentials are expired, tell the user to re-authenticate (aws sso login or equivalent) and stop.
Step 2: Configure Scope & Regions
Load context-templates/inventory-scope.json if the user has copied it into their workspace; otherwise ask:
| Setting |
Options |
Default |
| Scan mode |
full / category / quick |
full |
| Region scope |
single / multi / all |
all |
| Include tags |
yes / no |
yes |
| Include cost data |
yes / no (requires Cost Explorer) |
no |
| Output dir |
path |
./inventory-reports |
Region resolution:
single → use the specified region directly
multi → validate via aws ec2 describe-regions, use the listed regions
all → call aws ec2 describe-regions to discover all enabled regions, then exclude me-south-1 and me-central-1 (Bahrain/Dubai — historically outage-prone for this power; skip unless the user explicitly asks to include them)
Global services (IAM, S3, Route53, CloudFront, Organizations, Shield, GlobalAccelerator, TrustedAdvisor, HealthDashboard, Cost Management) always scan once regardless of region scope.
Category-based scanning (category mode): user can specify groups ("Scan all Security services"), individual services ("Scan EC2 and RDS"), or mixed. See references/inventory-workflow.md for the full category groupings.
Present the scope summary and confirm before proceeding on any full or all-region scan — these can take 10-20 minutes and make hundreds of API calls.
Step 3: Execute Inventory Scan
Full per-service API call reference: references/inventory-workflow.md (all 109 categories, exact operations and columns).
Execution approach:
- Use the Bash tool to call AWS CLI (
--output json) or a small boto3 script per service.
- For multi-region scans, batch regions (e.g. 8-10 at a time in a single Python/boto3 script using
concurrent.futures or a simple loop) rather than one Bash call per region — far fewer tool round-trips.
- Handle pagination fully: watch for
NextToken / Marker / IsTruncated and keep paging. Never truncate results.
- Report progress as groups complete: "Scanning [Service] in [Region]... found N resources"
Critical implementation notes (carried over from the original power)
| Service |
Gotcha |
Solution |
| S3 |
ListBuckets has no region |
Call GetBucketLocation per bucket. null/None = us-east-1. Batch to avoid throttling. |
| ECS |
ListClusters returns ARNs only |
Follow with DescribeClusters(clusters=<arns>) for details. |
| EBS |
Attachment is nested |
Access Attachments[0].InstanceId. State available = orphaned volume. |
| EC2 |
Instances nested in Reservations |
Flatten Reservations[].Instances[]. Name comes from Tags[?Key=='Name'].Value. |
| DynamoDB |
ListTables returns names only |
Follow with DescribeTable per table for item count/size. |
| EKS |
ListClusters returns names only |
Follow with DescribeCluster per name for version/status/endpoint. |
Handling errors
- AccessDenied → log in ScanNotes, continue — never fail the whole scan for one denied call.
- No resources found → skip that sheet (don't create an empty one).
- Region unreachable / timeout → note and continue with other regions.
- Service not available in region → note as
NOT_AVAILABLE, continue.
- Throttled → back off 2-5s, retry up to 3 times.
Step 4: Generate Excel Report
- Write the collected data to
inventory-reports/inventory-data.json.
- Run
scripts/generate_excel.py --input inventory-reports/inventory-data.json --output inventory-reports/aws-inventory-<accountId>-<YYYYMMDD-HHMM>.xlsx (requires pip install openpyxl --break-system-packages if not already present).
- Delete the temp JSON after success.
Formatting rules (headers, colors, freeze panes, column widths): references/excel-output.md.
File locking: if the target file is open elsewhere, write to a new filename rather than failing.
Completeness: every sheet must contain every discovered resource — never sample or truncate.
Step 5: Present Results
Report:
- Path to the Excel file
- Total resources discovered
- Top 5 categories by count
- Regions scanned
- Any errors or skipped services from ScanNotes
Guardrails
- Read-only, always. Only ever call
List*, Describe*, Get* operations. Never create, modify, tag, or delete any AWS resource under any circumstance in this skill.
- No secrets in output — mask any tag whose key contains "password", "secret", "key", "token", or "credential".
- Environment variable values: for Lambda/ECS/Batch, record only variable names, never values.
- IAM policy documents: capture name/ARN/attachment count only — never embed full policy JSON.
- Secrets Manager / SSM SecureString: metadata only (name, ARN, rotation status). Never call with decryption or
GetSecretValue.
- Output stays local — everything lands in
inventory-reports/ on the user's machine; nothing is uploaded anywhere.
- Complete pagination — never truncate.
Scan mode quick reference
| Mode |
Categories scanned |
Estimated time |
full |
All 109 |
5-15 min (all regions) |
category |
User-specified groups/services |
Varies |
quick |
EC2, SGs, Lambda, ECS, EKS, S3, EBS, EFS, VPC, LBs, Route53, CloudFront |
< 2 min |
Large account strategy
For large accounts (many regions, 500+ resources), write incrementally instead of waiting for the full scan:
- One workbook per category group as it finishes (
*-Compute.xlsx, *-Storage.xlsx, etc.)
- Generate a MASTER workbook at the end with every sheet plus Summary and ScanNotes.
Use this for full mode or category mode with 3+ groups; not needed for quick.
1---2name: aws-inventory3description: AWS Infrastructure Inventory — discovers all resources across configured regions and services, then generates a comprehensive Excel workbook with one sheet per service category. Supports full scan, category-based scan, quick scan, multi-region, configurable scope, and resource tagging. Use when the user says "inventory my AWS", "list all resources", "generate infrastructure report", "what's in my account", "export AWS resources to Excel", "full scan", "scan everything", "scan by category", or any request to discover and catalog AWS infrastructure.4---56# AWS Infrastructure Inventory78Ported from the `power-aws-inventory` Kiro Power (github.com/aquavis12/power-aws-inventory). Same 109-category scan logic and Excel output — adapted here to run over the Bash tool and AWS CLI/boto3 directly, since Claude Code doesn't need an MCP proxy for this: it already has native shell access.910## Step 1: Validate AWS Session11121. Run `aws sts get-caller-identity` via Bash to confirm credentials.132. Record **account ID**, **caller ARN**, and **default region**.143. Report: "Authenticated as `<arn>` in account `<accountId>`"1516**Profile handling**: If the default profile points to the wrong account, check `aws configure list-profiles`, verify with `aws sts get-caller-identity --profile <name>`, and ask the user which profile/region to use — pass `--profile` explicitly on every subsequent call rather than mutating their environment.1718If credentials are expired, tell the user to re-authenticate (`aws sso login` or equivalent) and stop.1920## Step 2: Configure Scope & Regions2122Load `context-templates/inventory-scope.json` if the user has copied it into their workspace; otherwise ask:2324| Setting | Options | Default |25|---------|---------|---------|26| Scan mode | `full` / `category` / `quick` | full |27| Region scope | `single` / `multi` / `all` | all |28| Include tags | yes / no | yes |29| Include cost data | yes / no (requires Cost Explorer) | no |30| Output dir | path | `./inventory-reports` |3132**Region resolution:**33- `single` → use the specified region directly34- `multi` → validate via `aws ec2 describe-regions`, use the listed regions35- `all` → call `aws ec2 describe-regions` to discover all enabled regions, then **exclude** `me-south-1` and `me-central-1` (Bahrain/Dubai — historically outage-prone for this power; skip unless the user explicitly asks to include them)3637Global services (IAM, S3, Route53, CloudFront, Organizations, Shield, GlobalAccelerator, TrustedAdvisor, HealthDashboard, Cost Management) always scan once regardless of region scope.3839**Category-based scanning** (`category` mode): user can specify groups ("Scan all Security services"), individual services ("Scan EC2 and RDS"), or mixed. See `references/inventory-workflow.md` for the full category groupings.4041Present the scope summary and confirm before proceeding on any `full` or `all`-region scan — these can take 10-20 minutes and make hundreds of API calls.4243## Step 3: Execute Inventory Scan4445Full per-service API call reference: `references/inventory-workflow.md` (all 109 categories, exact operations and columns).4647**Execution approach:**48- Use the Bash tool to call AWS CLI (`--output json`) or a small boto3 script per service.49- For multi-region scans, batch regions (e.g. 8-10 at a time in a single Python/boto3 script using `concurrent.futures` or a simple loop) rather than one Bash call per region — far fewer tool round-trips.50- Handle pagination fully: watch for `NextToken` / `Marker` / `IsTruncated` and keep paging. Never truncate results.51- Report progress as groups complete: "Scanning [Service] in [Region]... found N resources"5253### Critical implementation notes (carried over from the original power)5455| Service | Gotcha | Solution |56|---------|--------|----------|57| **S3** | `ListBuckets` has no region | Call `GetBucketLocation` per bucket. `null`/`None` = `us-east-1`. Batch to avoid throttling. |58| **ECS** | `ListClusters` returns ARNs only | Follow with `DescribeClusters(clusters=<arns>)` for details. |59| **EBS** | Attachment is nested | Access `Attachments[0].InstanceId`. State `available` = orphaned volume. |60| **EC2** | Instances nested in Reservations | Flatten `Reservations[].Instances[]`. Name comes from `Tags[?Key=='Name'].Value`. |61| **DynamoDB** | `ListTables` returns names only | Follow with `DescribeTable` per table for item count/size. |62| **EKS** | `ListClusters` returns names only | Follow with `DescribeCluster` per name for version/status/endpoint. |6364### Handling errors6566- **AccessDenied** → log in ScanNotes, continue — never fail the whole scan for one denied call.67- **No resources found** → skip that sheet (don't create an empty one).68- **Region unreachable / timeout** → note and continue with other regions.69- **Service not available in region** → note as `NOT_AVAILABLE`, continue.70- **Throttled** → back off 2-5s, retry up to 3 times.7172## Step 4: Generate Excel Report73741. Write the collected data to `inventory-reports/inventory-data.json`.752. Run `scripts/generate_excel.py --input inventory-reports/inventory-data.json --output inventory-reports/aws-inventory-<accountId>-<YYYYMMDD-HHMM>.xlsx` (requires `pip install openpyxl --break-system-packages` if not already present).763. Delete the temp JSON after success.7778Formatting rules (headers, colors, freeze panes, column widths): `references/excel-output.md`.7980**File locking**: if the target file is open elsewhere, write to a new filename rather than failing.8182**Completeness**: every sheet must contain every discovered resource — never sample or truncate.8384## Step 5: Present Results8586Report:87- Path to the Excel file88- Total resources discovered89- Top 5 categories by count90- Regions scanned91- Any errors or skipped services from ScanNotes9293## Guardrails9495- **Read-only, always.** Only ever call `List*`, `Describe*`, `Get*` operations. Never create, modify, tag, or delete any AWS resource under any circumstance in this skill.96- **No secrets in output** — mask any tag whose key contains "password", "secret", "key", "token", or "credential".97- **Environment variable values**: for Lambda/ECS/Batch, record only variable **names**, never values.98- **IAM policy documents**: capture name/ARN/attachment count only — never embed full policy JSON.99- **Secrets Manager / SSM SecureString**: metadata only (name, ARN, rotation status). Never call with decryption or `GetSecretValue`.100- **Output stays local** — everything lands in `inventory-reports/` on the user's machine; nothing is uploaded anywhere.101- **Complete pagination** — never truncate.102103## Scan mode quick reference104105| Mode | Categories scanned | Estimated time |106|------|--------------------|--------|107| `full` | All 109 | 5-15 min (all regions) |108| `category` | User-specified groups/services | Varies |109| `quick` | EC2, SGs, Lambda, ECS, EKS, S3, EBS, EFS, VPC, LBs, Route53, CloudFront | < 2 min |110111## Large account strategy112113For large accounts (many regions, 500+ resources), write incrementally instead of waiting for the full scan:1141. One workbook per category group as it finishes (`*-Compute.xlsx`, `*-Storage.xlsx`, etc.)1152. Generate a MASTER workbook at the end with every sheet plus Summary and ScanNotes.116117Use this for `full` mode or `category` mode with 3+ groups; not needed for `quick`.