You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add SQLite database, NLQ engine, query library, examples, and config system
Major new features for v1.5.0:
1. Local SQLite database (db.py)
Scan results are now stored locally in ~/.awsmap/inventory.db.
Query historical scans, compare across accounts, and track changes
over time. Multi-account support: each scan records its account ID.
2. Built-in Natural Language Query engine (nlq.py)
Ask questions in plain English with zero dependencies — no LLM,
no API keys, no network. Deterministic NL-to-SQL parser tested
against 1500 realistic questions with 100% pass rate.
awsmap ask show me all EC2 instances without Owner tag
awsmap ask how many Lambda functions per region
awsmap ask -a production show me S3 buckets
3. Pre-built query library (30 SQL queries)
Ready-to-use security, compliance, and operational queries:
awsmap query -n admin-users
awsmap query -n open-security-groups
awsmap query -n resources-by-tag -P tag=Owner
awsmap query --list
Users can add custom queries in ~/.awsmap/queries/.
4. Examples library (1381 questions across 51 services)
Browse and run pre-built questions organized by AWS service:
awsmap examples
awsmap examples lambda
awsmap examples lambda 5
awsmap examples --search "public"
5. Configuration system (config.py)
Persistent defaults so users don't repeat CLI flags:
awsmap config set profile production
awsmap config set regions us-east-1,eu-west-1
Other changes:
- Add --version flag
- Add --workers minimum validation (must be >= 1)
- Fix S3 Tables region filtering
- Fix timestream-influxdb type naming (db_instance → db-instance) to match all other services
- Remove unused pyyaml dependency
- Remove double service validation in collect_all
- Align collect_all default max_workers to 40 (matches CLI)
- Update requires-python to >=3.9, add Python 3.13 classifier
- Update ROADMAP: remove 5 already-implemented services
New files:
src/aws_inventory/db.py — SQLite database layer
src/aws_inventory/nlq.py — NL-to-SQL parser (3000+ lines)
src/aws_inventory/config.py — Configuration system
src/aws_inventory/examples.py — Examples library (1381 questions)
src/aws_inventory/queries_lib.py — Query library loader
src/aws_inventory/queries/*.sql — 30 pre-built SQL queries
examples/queries/*.sql — 7 sample custom queries
-**Natural Language Queries**: Ask questions in plain English — zero dependencies, works out of the box (`awsmap ask show me all EC2 without Owner tag`)
27
+
-**Examples Library**: 1381 ready-to-run questions organized by service (`awsmap examples lambda`)
28
+
-**Multi-Account**: Scan multiple accounts, query across all of them
29
+
-**Tag Filtering**: Filter by tags — multiple values for same tag match ANY (Owner=John OR Jane), different tags match ALL (Owner=John AND Environment=Production)
24
30
-**Beautiful HTML Reports**: Interactive reports with search, filters, dark mode, and export
25
31
-**Multiple Outputs**: JSON, CSV, and HTML formats
26
32
-**Fast**: Parallel execution with 40 workers (~2 minutes for typical accounts)
@@ -65,6 +71,7 @@ pip install -e .
65
71
docker run --rm \
66
72
-v ~/.aws:/root/.aws:ro \
67
73
-v $(pwd)/output:/app/output \
74
+
-v ~/.awsmap:/root/.awsmap \
68
75
awsmap -p myprofile -o /app/output/inventory.html
69
76
70
77
# Using environment variables
@@ -73,8 +80,14 @@ docker run --rm \
73
80
-e AWS_SECRET_ACCESS_KEY \
74
81
-e AWS_DEFAULT_REGION=us-east-1 \
75
82
-v $(pwd)/output:/app/output \
83
+
-v ~/.awsmap:/root/.awsmap \
76
84
awsmap -o /app/output/inventory.html
77
85
86
+
# Query stored inventory
87
+
docker run --rm \
88
+
-v ~/.awsmap:/root/.awsmap \
89
+
awsmap query "SELECT service, COUNT(*) as count FROM resources GROUP BY service ORDER BY count DESC"
Scan multiple AWS accounts. Each scan is stored in the same local database — query across all of them.
129
+
130
+
```bash
131
+
# Scan different accounts (different profiles)
132
+
awsmap -p production
133
+
awsmap -p staging
134
+
awsmap -p dev-account
135
+
136
+
# Query across all accounts
137
+
awsmap query -n resources-by-account
138
+
awsmap ask how many resources per account
139
+
140
+
# Scope to one account
141
+
awsmap query -n admin-users -a production
142
+
awsmap ask -a staging show me all Lambda functions
143
+
```
144
+
145
+
## Query Your Inventory
146
+
147
+
Every scan is automatically stored in a local SQLite database (`~/.awsmap/inventory.db`). Query it offline with raw SQL or natural language.
148
+
149
+
### SQL Queries
150
+
151
+
```bash
152
+
# Count resources per service
153
+
awsmap query "SELECT service, COUNT(*) as count FROM resources GROUP BY service ORDER BY count DESC"
154
+
155
+
# Find all EC2 instances in a specific region
156
+
awsmap query "SELECT id, name, region FROM resources WHERE service='ec2' AND type='instance'"
157
+
158
+
# View scan history
159
+
awsmap query "SELECT * FROM scans ORDER BY timestamp DESC"
160
+
161
+
# JSON or CSV output
162
+
awsmap query "SELECT * FROM resources WHERE service='s3'" -f json
163
+
awsmap query "SELECT service, id, name FROM resources" -f csv
164
+
165
+
# Query tags (filter to resources that have the tag)
166
+
awsmap query "SELECT id, name, json_extract(tags, '$.Owner') as owner FROM resources WHERE service='ec2' AND json_extract(tags, '$.Owner') IS NOT NULL"
167
+
```
168
+
169
+
**More SQL examples:** See `examples/queries/*.sql` for ready-to-use query templates you can customize.
170
+
171
+
### Pre-Built Query Library
172
+
173
+
awsmap ships with 30 pre-built queries for common security, compliance, and operational tasks. No SQL knowledge required.
**Parameter format:** Use `-P parameter=value` where `parameter` is the query parameter name (e.g., `tag`, `service`) and `value` is what you're searching for. Example: `-P tag=Owner` means "filter by the Owner tag" (NOT `-P Owner=SomeValue`).
202
+
203
+
**Available queries:**
204
+
205
+
| Query | Description | Example |
206
+
|-------|-------------|---------|
207
+
|**IAM / Security**|||
208
+
|`admin-users`| IAM users with admin permissions (direct + via group) |`awsmap query -n admin-users`|
209
+
|`admin-roles`| IAM roles with admin permissions |`awsmap query -n admin-roles`|
210
+
|`users-without-mfa`| IAM users without MFA enabled |`awsmap query -n users-without-mfa`|
211
+
|`iam-inactive-users`| IAM users with no login and no access keys |`awsmap query -n iam-inactive-users`|
212
+
|`old-access-keys`| IAM users with access keys |`awsmap query -n old-access-keys`|
213
+
|`cross-account-roles`| IAM roles with trust policies allowing external accounts |`awsmap query -n cross-account-roles`|
214
+
|`open-security-groups`| Security groups with 0.0.0.0/0 ingress rules |`awsmap query -n open-security-groups`|
215
+
|`secrets-no-rotation`| Secrets Manager secrets without auto-rotation |`awsmap query -n secrets-no-rotation`|
216
+
|**S3**|||
217
+
|`public-s3-buckets`| S3 buckets with public access enabled |`awsmap query -n public-s3-buckets`|
218
+
|`encryption-status`| S3 buckets and their encryption configuration |`awsmap query -n encryption-status`|
219
+
|`s3-no-versioning`| S3 buckets without versioning |`awsmap query -n s3-no-versioning`|
220
+
|`s3-no-logging`| S3 buckets without access logging |`awsmap query -n s3-no-logging`|
221
+
|**EC2 / EBS**|||
222
+
|`stopped-instances`| EC2 instances in stopped state |`awsmap query -n stopped-instances`|
223
+
|`unused-volumes`| EBS volumes not attached to any instance |`awsmap query -n unused-volumes`|
224
+
|`ebs-unencrypted`| EBS volumes without encryption |`awsmap query -n ebs-unencrypted`|
225
+
|`unused-eips`| Elastic IPs not associated with any instance |`awsmap query -n unused-eips`|
226
+
|`default-vpcs`| Default VPCs across all regions |`awsmap query -n default-vpcs`|
227
+
|**RDS**|||
228
+
|`rds-public`| RDS instances with public access enabled |`awsmap query -n rds-public`|
229
+
|`rds-unencrypted`| RDS instances without encryption |`awsmap query -n rds-unencrypted`|
230
+
|`rds-no-multi-az`| RDS instances without Multi-AZ |`awsmap query -n rds-no-multi-az`|
231
+
|`rds-engines`| RDS instances grouped by engine |`awsmap query -n rds-engines`|
232
+
|**Lambda**|||
233
+
|`lambda-runtimes`| Lambda functions grouped by runtime |`awsmap query -n lambda-runtimes`|
|`untagged-resources`| Resources with no tags |`awsmap query -n untagged-resources`|
237
+
|`missing-tag`| Resources missing a specific tag |`awsmap query -n missing-tag -P tag=Owner`|
238
+
|`resources-by-tag`| Resources that have a specific tag |`awsmap query -n resources-by-tag -P tag=Owner`|
239
+
|**Inventory**|||
240
+
|`resources-by-service`| Resource count per service |`awsmap query -n resources-by-service`|
241
+
|`resources-by-region`| Resource count per region |`awsmap query -n resources-by-region`|
242
+
|`resources-by-account`| Resource count per account |`awsmap query -n resources-by-account`|
243
+
|`resources-per-account-service`| Resource count per account per service |`awsmap query -n resources-per-account-service`|
244
+
245
+
You can also add your own queries by placing `.sql` files in `~/.awsmap/queries/`. Use the same header format as the built-in queries (`-- name:`, `-- description:`, `-- params:`).
246
+
247
+
### Natural Language Queries
248
+
249
+
Ask questions about your inventory in plain English using `awsmap ask`. **No setup required** — works out of the box with a built-in zero-dependency parser.
250
+
251
+
```bash
252
+
awsmap ask how many resources per region
253
+
awsmap ask show me all EC2 instances without Owner tag
254
+
awsmap ask which S3 buckets are in eu-west-1
255
+
awsmap ask what services have the most resources
256
+
```
257
+
258
+
awsmap translates your question to SQL using a **built-in parser** (zero dependencies), shows you the generated query, and displays the results.
259
+
260
+
### Examples Library
261
+
262
+
Browse and run 1381 pre-built questions organized by AWS service using `awsmap examples`.
263
+
264
+
```bash
265
+
# List all services with question counts
266
+
awsmap examples
267
+
268
+
# Browse questions for a service
269
+
awsmap examples lambda
270
+
271
+
# Run a specific question by number
272
+
awsmap examples lambda 5
273
+
274
+
# Search across all questions
275
+
awsmap examples --search "public"
276
+
awsmap examples --search "encryption"
277
+
```
278
+
279
+
#### Multi-Account Queries
280
+
281
+
When multiple accounts have been scanned, `awsmap ask` queries all of them by default. Use `-a` to scope to a single account:
Set persistent defaults so you don't have to repeat CLI flags. CLI flags always override config values.
343
+
344
+
Only the keys listed below are accepted — unknown keys and invalid values are rejected. If the config file is manually edited and contains invalid entries, `awsmap config list` detects them, warns you, and auto-cleans the file.
345
+
346
+
| Command | Description |
347
+
|---------|-------------|
348
+
|`awsmap config set key value`| Set a configuration value (validated) |
349
+
|`awsmap config get key`| Get a configuration value |
350
+
|`awsmap config list`| List all values (detects and cleans invalid entries) |
351
+
|`awsmap config delete key`| Delete a configuration value |
352
+
353
+
**Available config keys (only these are accepted):**
-**Ollama** models are free and run locally, but when tested against real AWS inventory queries, accuracy was around 80% — one in five queries would generate wrong SQL or fail silently. Not acceptable for a CLI tool where users trust the output.
582
+
-**OpenAI / Anthropic APIs** produce better results, but require API keys, cost money per query, and depend on network connectivity. Not ideal for an infrastructure tool that should just work.
583
+
-**Built-in parser** is a zero-dependency, deterministic NL-to-SQL engine. It's tested against **1500 realistic test questions with a 100% pass rate** (separate from the 1381 examples library). It covers listing, counting, aggregation, region filters, negation, tags, multi-service queries, synonyms, typo tolerance, relative time, numeric fields, keyword-value patterns, and 150+ AWS services. No API keys, no network, no cost, instant results.
584
+
585
+
The 1500 test questions (used during development to validate the parser) are designed to cover the vast majority of real-world use cases. The parser also includes typo tolerance, synonym support, and fuzzy matching to handle natural variations in how people phrase questions.
586
+
587
+
> **Found a bug or an inaccurate query?** Please [open an issue](https://github.com/TocConsulting/awsmap/issues) and report it! Every report helps improve the parser for everyone. **If you have ideas for a better approach than the built-in NLQ, we're always open to suggestions.**
588
+
319
589
## Support
320
590
321
591
-**Documentation**: Check this README and [SERVICES.md](SERVICES.md)
Copy file name to clipboardExpand all lines: ROADMAP.md
+3-8Lines changed: 3 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,12 @@
1
1
# Roadmap
2
2
3
-
We currently cover **146 AWS services**. Below are the **91 services** we still need to add: **67 new collectors** and **24 extensions** to existing collectors.
3
+
We currently cover **150 AWS services**. Below are the **86 services** we still need to add: **64 new collectors** and **22 extensions** to existing collectors.
4
4
5
5
This list was built by comparing all **417 services available in boto3** against what awsmap already covers, then filtering out deprecated/sunset services and data-plane-only APIs that don't have inventoriable resources.
6
6
7
7
To contribute: pick a service, write a collector in `src/aws_inventory/collectors/`, and open a PR.
8
8
9
-
## New collectors (67)
9
+
## New collectors (64)
10
10
11
11
-**aiops** — AI Operations
12
12
-**appfabric** — App bundles, ingestions
@@ -21,10 +21,8 @@ To contribute: pick a service, write a collector in `src/aws_inventory/collector
0 commit comments