Production-inspired AWS infrastructure auditing and cost optimization CLI
Project description
________ ____ __ ______
/ ____/ / / __ \/ / / / __ \
/ / / / / / / / / / / / / /
/ /___/ /___/ /_/ / /_/ / /_/ /
\____/_____/\____/\____/_____/
___ __ ______ ______________ ____
/ | / / / / __ \/ _/_ __/ __ \/ __ \
/ /| |/ / / / / / // / / / / / / / /_/ /
/ ___ / /_/ / /_/ // / / / / /_/ / _, _/
/_/ |_\____/_____/___/ /_/ \____/_/ |_|
// cloud-infra-auditor ||| scan → audit → report → cleanup //
cloud-infra-auditor
AWS infrastructure auditing and cost optimization — from the terminal.
Overview
Cloud accounts accumulate waste quietly — unattached volumes, orphaned Elastic IPs, instances running at 2% CPU for months. Most teams discover this on the billing page.
cloud-infra-auditor connects to your AWS account, scans for unused and underutilized resources, and surfaces findings as a Rich terminal report, a JSON export, or a CSV. It follows a deliberate scan → analyze → report → review → cleanup workflow. Nothing is modified unless you explicitly confirm it.
As of v1.1.0, multi-region scans run in parallel via a shared ThreadPoolExecutor-backed utility, cutting typical scan time from 60–65 seconds down to 8–10 seconds.
What's New in v1.1.0
- Parallel multi-region scanning — regions are scanned concurrently instead of sequentially.
- Shared parallel scanning utility (
auditor/utils/parallel.py) — replaces duplicated concurrency logic across scanners. - Rich CLI progress bar — live progress feedback while scans run.
- Rich scan summary panel (
auditor/ui/summary.py) — a consolidated summary view after each scan. - Faster execution — scan time improved from ~60–65 seconds to ~8–10 seconds on multi-region scans.
- Cleaner CLI UX — clearer output and more consistent formatting across commands.
- Refactored concurrency logic — duplicated threading code consolidated into one shared module.
- General maintainability improvements — clearer separation of concerns across the
auditor/package.
Features
| Category | Capability |
|---|---|
| Scanning | Unattached EBS volumes, unassociated Elastic IPs, underutilized EC2 instances |
| Concurrency | Parallel multi-region scanning via ThreadPoolExecutor |
| Metrics | CloudWatch-backed CPU utilization detection |
| Multi-region | Scan resources across multiple AWS regions in parallel |
| CLI UX | Rich terminal progress bar and scan summary panel |
| Reporting | Rich terminal tables, JSON export, CSV export |
| Cleanup | Dry-run preview; explicit --execute required — nothing deleted silently |
| Retry | Configurable retry logic for AWS API calls |
| Testing | Pytest + Moto + unittest.mock — no real AWS account needed |
| CI | GitHub Actions pipeline |
| Packaging | pyproject.toml, wheel + source dist, cloud-auditor entry point |
Summary:
✔ Parallel AWS region scanning ✔ Rich terminal progress ✔ Rich summary panel ✔ ThreadPoolExecutor concurrency ✔ JSON export ✔ CSV export ✔ Cleanup commands ✔ Multi-region support ✔ Installable CLI
CLI Preview
Help Command
Scan EBS
Scan EC2
Scan EIP
Cleanup Example
JSON or CSV Report
Architecture
┌─────────────────────────────────────────────────────────────┐
│ CLI (Typer) │
│ auditor/cli/main.py ← scan / report / cleanup │
│ auditor/cli/scan.py | auditor/cli/report.py │
│ auditor/cli/cleanup.py | auditor/cli/auth.py │
│ auditor/cli/aws.py │
└──────────────────────────┬──────────────────────────────────┘
│
┌────────────────▼────────────────┐
│ AWS Layer │
│ auditor/aws/session.py │
│ auditor/aws/auth.py │
│ auditor/aws/regions.py │
│ auditor/aws/cloudwatch.py │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Parallel Scan Utility │
│ auditor/utils/parallel.py │
│ (ThreadPoolExecutor, shared │
│ across all scanners) │
└────────────────┬────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌──────▼──────┐ ┌────────▼──────┐ ┌───────▼──────┐
│ ebs_scanner │ │ eip_scanner │ │ ec2_scanner │
│ .py │ │ .py │ │ .py │
└──────┬──────┘ └────────┬──────┘ └───────┬──────┘
│ │ │
└───────────────────▼───────────────────┘
auditor/models/findings.py
auditor/models/resource.py
│
┌────────────────▼────────────────┐
│ Reports Layer │
│ report_generator.py │
│ report_transformer.py │
│ rich_formatter.py │
│ json_exporter.py │
│ csv_exporter.py │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ UI Layer │
│ auditor/ui/summary.py │
│ (Rich progress bar + summary │
│ panel) │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Cleanup Layer │
│ auditor/cleanup/dry_run.py │
│ auditor/cleanup/ebs_cleanup.py │
│ auditor/cleanup/eip_cleanup.py │
└─────────────────────────────────┘
Project Structure
cloud-infra-auditor/
├── .github/ # GitHub Actions CI workflows
├── auditor/
│ ├── aws/
│ │ ├── auth.py # AWS credential handling
│ │ ├── cloudwatch.py # CloudWatch metric queries
│ │ ├── regions.py # Region resolution
│ │ └── session.py # Boto3 session management
│ ├── cli/
│ │ ├── main.py # Typer app entrypoint
│ │ ├── scan.py # scan command
│ │ ├── report.py # report command
│ │ ├── cleanup.py # cleanup command
│ │ ├── auth.py # auth command
│ │ └── aws.py # aws command
│ ├── cleanup/
│ │ ├── ebs_cleanup.py # EBS volume deletion
│ │ └── eip_cleanup.py # Elastic IP release
│ ├── reports/
│ │ ├── report_generator.py # Aggregates scan findings
│ │ ├── report_transformer.py # Transforms findings for export
│ │ ├── rich_formatter.py # Rich terminal output
│ │ ├── json_exporter.py # JSON export
│ │ └── csv_exporter.py # CSV export
│ ├── scanners/
│ │ ├── ebs_scanner.py # Unattached EBS detection
│ │ ├── eip_scanner.py # Unassociated EIP detection
│ │ └── ec2_scanner.py # Underutilized EC2 detection
│ ├── ui/
│ │ └── summary.py # Rich progress bar + scan summary panel
│ ├── utils/
│ │ ├── exceptions.py # Custom exceptions
│ │ ├── helpers.py # Shared utilities
│ │ ├── logger.py # Logging configuration
│ │ ├── retry.py # AWS API retry logic
│ │ └── parallel.py # Shared ThreadPoolExecutor scanning utility
│ └── constants.py # Project-wide constants
├── tests/
│ ├── conftest.py
│ ├── test_cleanup.py
│ ├── test_csv_exporter.py
│ ├── test_ebs_scanner.py
│ ├── test_ec2_scanner.py
│ ├── test_eip_scanner.py
│ ├── test_json_exporter_.py
│ ├── test_regions.py
│ ├── test_report_generator.py
│ ├── test_report_transformer.py
│ └── test_session.py
├── config/ # YAML thresholds and region defaults
├── docs/
├── audit_reports/ # Runtime audit output (gitignored)
├── reports/ # Generated exports (gitignored)
├── manual_testing/
├── dist/
│ ├── cloud_infra_auditor-1.1.0.tar.gz
│ └── cloud_infra_auditor-1.1.0-py3-none-any.whl
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
└── LICENSE
Getting Started
Prerequisites
| Requirement | Version |
|---|---|
| Python | 3.11+ |
| Git | Latest |
| AWS CLI | v2 |
| pip | Latest |
python --version
pip --version
git --version
aws --version
Clone
git clone https://github.com/harshil6-lab/cloud-infra-auditor.git
cd cloud-infra-auditor
Virtual Environment
Windows
python -m venv venv
venv\Scripts\activate
Linux / macOS
python3 -m venv venv
source venv/bin/activate
Install
# Runtime only
pip install -r requirements.txt
# Development (recommended)
pip install -e ".[dev]"
The development install includes Pytest, Moto, Ruff, and Black.
Verify
cloud-auditor --help
Expected output:
Usage: cloud-auditor [OPTIONS] COMMAND [ARGS]...
Cloud Infrastructure Auditor & Cost Optimizer
AWS Configuration
# Configure credentials interactively
aws configure
For detailed AWS credential setup and IAM configuration, see:
- **[AWS Configuration Guide](docs/AWS_CONFIG.md)**
# Verify authentication
aws sts get-caller-identity
Minimum IAM permissions for scanning (read-only):
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"cloudwatch:GetMetricStatistics"
],
"Resource": "*"
}
Cleanup operations additionally require ec2:ReleaseAddress and ec2:DeleteVolume. These are only invoked after explicit --execute confirmation.
Usage
Scan
cloud-auditor scan ebs
cloud-auditor scan eip
cloud-auditor scan ec2
Multi-region scans now run in parallel by default, with a live Rich progress bar and a summary panel printed at the end of the scan.
Report
cloud-auditor report export --format csv
cloud-auditor report export --format json
Cleanup
# Preview — no changes made
cloud-auditor cleanup ebs --dry-run
cloud-auditor cleanup eip --dry-run
# Execute after confirmation
cloud-auditor cleanup ebs --execute
cloud-auditor cleanup eip --execute
Auth
cloud-auditor auth identity
cloud-auditor auth profiles
AWS
cloud-auditor aws regions
Help
cloud-auditor --help
cloud-auditor scan --help
cloud-auditor cleanup --help
cloud-auditor report --help
Testing
All tests run against Moto-mocked AWS services. No live AWS account or credentials required.
# Full test suite
pytest
# With terminal coverage summary
pytest --cov=auditor --cov-report=term-missing
# HTML coverage report
pytest --cov=auditor --cov-report=html
# Open htmlcov/index.html in your browser to inspect line-by-line code coverage.
Test files:
| File | Covers |
|---|---|
test_ebs_scanner.py |
EBS unattached volume detection |
test_eip_scanner.py |
Elastic IP unassociated detection |
test_ec2_scanner.py |
EC2 underutilization detection |
test_cleanup.py |
Dry-run and cleanup execution |
test_report_generator.py |
Report aggregation |
test_report_transformer.py |
Report transformation |
test_json_exporter_.py |
JSON export |
test_csv_exporter.py |
CSV export |
test_session.py |
Boto3 session management |
test_regions.py |
Region resolution |
conftest.py |
Shared fixtures |
Code Quality
black .
ruff check .
Build
pip install build
python -m build
Artifacts generated in dist/:
dist/
├── cloud_infra_auditor-1.1.0.tar.gz
└── cloud_infra_auditor-1.1.0-py3-none-any.whl
Technology Stack
| Category | Technology | Version |
|---|---|---|
| Language | Python | 3.11+ |
| CLI Framework | Typer | 0.16+ |
| Cloud SDK | Boto3 | 1.40+ |
| Terminal UI | Rich | 14.0+ |
| Concurrency | ThreadPoolExecutor | stdlib |
| Testing | Pytest | 9.1+ |
| AWS Mocking | Moto | 5.1+ |
| Mock Library | unittest.mock | stdlib |
| Formatter | Black | 25.1+ |
| Linter | Ruff | 0.12+ |
| Packaging | setuptools + build | 68+ |
| Distribution | Wheel + source dist | PEP 427 |
| CI | GitHub Actions | — |
| Config Format | TOML (pyproject.toml) |
PEP 621 |
| AWS Auth | AWS CLI | v2 |
| Cloud Services | EC2, EBS, Elastic IP, CloudWatch | AWS |
Design Decisions
Why Typer?
Type-annotated commands, zero boilerplate, auto-generated --help that stays accurate without maintenance.
Why Rich? Tables, progress bars, and summary panels that degrade cleanly in CI environments. No custom rendering code.
Why a shared auditor/utils/parallel.py?
Each scanner originally implemented its own threading logic for multi-region scans. Consolidating this into a single ThreadPoolExecutor-backed utility removed duplicated code and made concurrency behavior consistent and independently testable across all scanners.
Why report_transformer.py separate from report_generator.py?
Generation and transformation are distinct responsibilities. report_generator.py aggregates raw findings; report_transformer.py shapes them for a specific output format. Keeping these separate makes each independently testable.
Why dry-run by default?
Audit tools carry asymmetric risk. Scanning is always safe; deletion is not. The default posture is read-only. Cleanup requires --execute explicitly.
Why Moto for tests? Real AWS calls in tests are slow, costly, and non-deterministic. Moto provides accurate service simulation — tests run offline with no live account.
Security
- Read-only by default.
scanrequires onlyDescribe*andGetMetricStatistics. No write permissions needed. - Explicit execution gate.
--dry-runshows what would be affected;--executeprompts per resource before acting. Cleanup never runs from a scan. - No credential storage. The tool delegates entirely to boto3's credential chain — no secrets are read, copied, or logged by the application.
- Least privilege. Minimum IAM policy for read-only audit is documented above. Write permissions should be granted only when cleanup is required.
Roadmap
[x] AWS session management and credential resolution
[x] EBS unattached volume scanner
[x] Elastic IP unassociated scanner
[x] EC2 underutilization scanner (CloudWatch-backed)
[x] Rich terminal formatter
[x] JSON and CSV export
[x] Report generator and transformer
[x] Dry-run and confirmation-gated cleanup
[x] Pytest + Moto test coverage (11 tests)
[x] GitHub Actions CI
[x] pyproject.toml packaging, wheel + source dist
[x] Parallel scanning via ThreadPoolExecutor
[x] Rich CLI progress bar and scan summary panel
[ ] S3 lifecycle analysis
[ ] Multi-account support via assume-role
[ ] HTML report output
[ ] Slack / PagerDuty alerting integration
Author
Harshil Kalsariya github.com/harshil6-lab
Sravya Maddipati github.com/sravya-77
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloud_infra_auditor-1.1.0.tar.gz.
File metadata
- Download URL: cloud_infra_auditor-1.1.0.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ade4b2ed3df60ff9c7acb23ed89b2f00913c616c93fe706741157c7b68880c5a
|
|
| MD5 |
bf1101fa73f817a4499893cb8482ad71
|
|
| BLAKE2b-256 |
93abc0b9404f78e84bf4925b43aa6795df7a38cf4e871bb4b22a8d9c5b1b0aa8
|
File details
Details for the file cloud_infra_auditor-1.1.0-py3-none-any.whl.
File metadata
- Download URL: cloud_infra_auditor-1.1.0-py3-none-any.whl
- Upload date:
- Size: 21.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fd01a9f3a6f726be768ece7b8f30bbd1a7f4388f47f675561d661f1714ae22c
|
|
| MD5 |
2fbbe4cbf73515afe38e737a2f8c0f02
|
|
| BLAKE2b-256 |
cd2897d3d794918145034ae7752ce76f2bed5fb6fa5cc5d1b6b772a46e44e5dc
|