DEV Community

Tarek CHEIKH
Tarek CHEIKH

Posted on • Originally published at aws.plainenglish.io on

awsmap v1.5.0: Your AWS Inventory Now Has a Brain

A few weeks ago I published awsmap. Scan your AWS account. 140 services. One command.

2,300 pip installs. 650 Docker pulls. 35 GitHub stars. Two pull requests from strangers. A few comments. Some feature requests. People were actually using it.

So I kept building. This is v1.5.0.

New Report

The HTML report got rebuilt from the ground up. The design now follows the Cloudscape design system, same design language used by the AWS Console.

Dashboard cards. Top services chart. Top regions chart. Region-coded badges, blue for us-*, green for eu-*, orange for ap-*. Dark mode. Global search across every resource. Filter by service, region, or tag. Click an ARN, it copies. Click a tag badge, it expands. Export the filtered view to CSV. Print it.

Still a single HTML file. No dependencies. Open it in any browser, share it on Slack, attach it to a ticket.

Everything Goes to SQLite

This is the biggest change in v1.5.0.

Every time you scan, every resource goes into a local SQLite database. Automatically. No setup. No config.

~/.awsmap/inventory.db
Enter fullscreen mode Exit fullscreen mode

Scan again next week, both scans are stored. Scan a different account, same database. You’re building an inventory history without trying.

Why does this matter? Because the scan is no longer a one-shot event. The data lives. You can query it tomorrow, next week, next month.

Don’t want the database? -- **_no-db_** skips it. You still get your HTML/JSON/CSV report, same as before. Nothing breaks.

awsmap query

New command. Raw SQL against your inventory.

awsmap query "SELECT service, COUNT(*) as count FROM resources GROUP BY service ORDER BY count DESC"

service count
------------- -----
vpc 1047
iam 842
lambda 631
logs 551
Enter fullscreen mode Exit fullscreen mode

Want JSON? **_-f json_**. CSV? - **_f csv_**. Pipe it. Script it. Cron it.

awsmap query "SELECT * FROM resources WHERE service='lambda'" -f json
awsmap query "SELECT service, id, name FROM resources" -f csv
Enter fullscreen mode Exit fullscreen mode

But I realized something. Most people don’t want to write SQL.

Pre-Built Queries

Security audit Monday morning. You need to know which IAM users have admin permissions. Including users who get admin through group membership. That’s a self-join with EXISTS subqueries. Nobody wants to type that.

So awsmap ships 30 pre-built queries. One flag:

awsmap query -n admin-users

name account_id mfa groups admin_source
--------- ------------ --- ------------ ------------
tarek-adm 012345678912 0 ["adminGrp"] DIRECT
tarek 012345678912 0 ["adminGrp"] VIA GROUP
tarek 000011112222 1 [] DIRECT
Enter fullscreen mode Exit fullscreen mode

That tells you which users have admin directly and which get it through group membership. No MFA on an admin account? That’s a finding.

Security

awsmap query -n admin-users
awsmap query -n admin-roles
awsmap query -n users-without-mfa
awsmap query -n iam-inactive-users
awsmap query -n old-access-keys
awsmap query -n cross-account-roles
awsmap query -n open-security-groups
awsmap query -n secrets-no-rotation
Enter fullscreen mode Exit fullscreen mode

s3

awsmap query -n public-s3-buckets
awsmap query -n encryption-status
awsmap query -n s3-no-versioning
awsmap query -n s3-no-logging
Enter fullscreen mode Exit fullscreen mode

EC2 / EBS

awsmap query -n stopped-instances
awsmap query -n unused-volumes
awsmap query -n ebs-unencrypted
awsmap query -n unused-eips
awsmap query -n default-vpcs
Enter fullscreen mode Exit fullscreen mode

RDS

awsmap query -n rds-public
awsmap query -n rds-unencrypted
awsmap query -n rds-no-multi-az
awsmap query -n rds-engines
Enter fullscreen mode Exit fullscreen mode

Lambda & Inventory

awsmap query -n lambda-runtimes
awsmap query -n lambda-high-memory
awsmap query -n resources-by-service
awsmap query -n resources-by-region
awsmap query -n resources-by-account
awsmap query -n resources-per-account-service
Enter fullscreen mode Exit fullscreen mode

Tags & Compliance

awsmap query -n untagged-resources
awsmap query -n missing-tag -P tag=Environment
awsmap query -n resources-by-tag -P tag=Owner
Enter fullscreen mode Exit fullscreen mode

List them all with awsmap query — list. See the SQL behind any query with **_awsmap query -n admin-users_**.

You can add your own. Drop a **_.sql_** file in **_~/.awsmap/queries/_** and it shows up in the list.

awsmap ask

Some people don’t want SQL at all. They want to ask a question in English.

awsmap ask how many Lambda functions per region

region count
------------- -----
eu-west-1 45
us-east-1 32
eu-central-1 12
Enter fullscreen mode Exit fullscreen mode

awsmap translates your question to SQL using a built-in zero-dependency parser. Everything runs on your machine. No API keys. No cloud calls. Your data stays on your laptop.

awsmap ask show me all EC2 instances without Owner tag
awsmap ask which S3 buckets are in eu-west-1
awsmap ask find IAM users without MFA
awsmap ask count RDS instances using mysql per region
awsmap ask show me my databases
awsmap ask show me secrets older than 90 days
Enter fullscreen mode Exit fullscreen mode

Why Not Use an LLM?

I tried. Ollama with local models gave ~80% accuracy. One in five queries returned wrong SQL. OpenAI and Anthropic APIs were better but cost money and require network.

So I built a deterministic parser from scratch. Zero dependencies. Tested against 1500 realistic questions with 100% pass rate. It handles:

  • Synonyms : “databases” finds RDS, “containers” finds ECS, “certs” finds ACM
  • Typo tolerance : “lamda” matches Lambda, “instaces” matches instances
  • Engine patterns : “RDS using postgres”, “ElastiCache using redis”
  • Numeric fields : “with allocated_storage greater than 50”, “with iops greater than 3000”
  • Relative time : “created in the last 30 days”, “older than 90 days”
  • Keyword-value : “with storage type gp3”, “with scheduling strategy REPLICA”

No API keys. No network. No cost. Instant results.

awsmap examples

1381 pre-built questions, organized by service. Browse them, search them, run them.

# List all services with question counts
awsmap examples

# Browse questions for a service
awsmap examples lambda

# Run question #5 directly
awsmap examples lambda 5

# Search across everything
awsmap examples --search "public"
awsmap examples --search "encryption"
Enter fullscreen mode Exit fullscreen mode

You don’t have to memorize the query syntax. Just browse and pick.

awsmap config

Set persistent defaults so you stop repeating flags.

awsmap config set profile production
awsmap config set regions us-east-1,eu-west-1
awsmap config set exclude_defaults true

# Now just run:
awsmap
# Equivalent to: awsmap -p production -r us-east-1,eu-west-1 --exclude-defaults
Enter fullscreen mode Exit fullscreen mode

Available keys: **_profile_**, **_regions_**, **_services_**, **_format_**, **workers**, **_exclude\_defaults_**, **db**, **_query\_format_**. CLI flags always override config.

Multi-Account

In Part 1, awsmap scanned one account at a time. Now it scans many and stores them in the same database.

awsmap -p production
awsmap -p staging
awsmap -p dev
Enter fullscreen mode Exit fullscreen mode

Three scans. One database. Query across all of them:

awsmap query -n resources-by-account
awsmap ask how many resources per account
Enter fullscreen mode Exit fullscreen mode

Or scope to one:

awsmap query -n admin-users -a production
awsmap ask -a staging show me all Lambda functions
Enter fullscreen mode Exit fullscreen mode

Tag Filtering

You tag your AWS resources. Now you can scan by tags.

awsmap -p prod -t Owner=John -t Environment=Production
Enter fullscreen mode Exit fullscreen mode

Same key = OR logic. Different keys = AND logic. So **_-t Owner=John -t Owner=Jane -t Environment=Production_** returns resources where Owner is John OR Jane, AND Environment is Production.

Typo Protection

Small thing, big time saver.

$ awsmap -s labda
Error: Unknown service 'labda'. Did you mean: lambda?

$ awsmap -r eu-wst-1
Error: Unknown region 'eu-wst-1'. Did you mean: eu-west-1?
Enter fullscreen mode Exit fullscreen mode

No more silent failures from mistyped service names. awsmap validates against real AWS service names and regions before making a single API call.

Default Resource Filtering

Every AWS account has default VPCs, default security groups, default route tables, default NACLs in every region. They clutter every inventory report.

awsmap -p prod --exclude-defaults
Enter fullscreen mode Exit fullscreen mode

When you don’t use the flag, defaults are still collected but marked with a “DEFAULT” badge in the HTML report so you can tell them apart.

Quick Reference

| What | Command |
|-------------------|-----------------------------------------| 
| Full scan | `awsmap -p profile` |
| Specific services | `awsmap -p profile -s ec2,rds,lambda` |
| Filter by tags | `awsmap -p profile -t Owner=DevOps` |
| Exclude defaults | `awsmap -p profile --exclude-defaults` |
| SQL query | `awsmap query "SELECT ..."` |
| Named query | `awsmap query -n admin-users` |
| List queries | `awsmap query --list` |
| Ask in English | `awsmap ask how many Lambda per region` |
| Browse examples | `awsmap examples lambda` |
| Run example | `awsmap examples lambda 5` |
| Set config | `awsmap config set profile production` |
| Scope to account | `awsmap query -n admin-users -a prod` |
Enter fullscreen mode Exit fullscreen mode

Upgrade

pip install --upgrade awsmap

docker pull tarekcheikh/awsmap
Enter fullscreen mode Exit fullscreen mode

Links

GitHub: https://github.com/TocConsulting/awsmap

PyPI: https://pypi.org/project/awsmap/

Docker: https://hub.docker.com/r/tarekcheikh/awsmap

Part 1: https://aws.plainenglish.io/awsmap-find-everything-running-in-your-aws-account-3294c5326baa


Top comments (0)