Metadata-Version: 2.5
Name: vpcatlas
Version: 0.5.0
Summary: Read-only AWS network discovery: inventory, cross-account links and AWS-style diagrams (draw.io and Lucidchart) from the CLI or a live dashboard.
Author-email: Karina Pérez <mail@karina-perez.es>
License-Expression: MIT
License-File: LICENSE
Keywords: aws,diagram,drawio,inventory,lucidchart,network,transit-gateway,vpc
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Networking
Requires-Python: >=3.12
Requires-Dist: boto3>=1.35
Requires-Dist: fastapi>=0.115
Requires-Dist: jinja2>=3.1
Requires-Dist: mangum>=0.17
Requires-Dist: networkx>=3.3
Requires-Dist: pydantic>=2.8
Requires-Dist: rich>=13.7
Requires-Dist: typer>=0.12
Requires-Dist: uvicorn[standard]>=0.30
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: moto[ec2,elbv2,iam,route53resolver,sts]>=5.0; extra == 'dev'
Requires-Dist: mypy>=2.4; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Description-Content-Type: text/markdown

# vpcatlas

[![ci](https://github.com/karina-pp/vpcatlas/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/karina-pp/vpcatlas/actions/workflows/ci.yml)
[![release](https://github.com/karina-pp/vpcatlas/actions/workflows/release.yml/badge.svg)](https://github.com/karina-pp/vpcatlas/actions/workflows/release.yml)
[![CodeQL](https://github.com/karina-pp/vpcatlas/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/karina-pp/vpcatlas/actions/workflows/codeql.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/karina-pp/vpcatlas/badge)](https://securityscorecards.dev/viewer/?uri=github.com/karina-pp/vpcatlas)
[![Docker Hub pulls](https://img.shields.io/docker/pulls/vpcatlas/vpcatlas)](https://hub.docker.com/r/vpcatlas/vpcatlas)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

[Website](https://vpcatlas.com) · [Documentation](https://vpcatlas.com/docs/) · [Releases](https://github.com/karina-pp/vpcatlas/releases) · [Docker Hub](https://hub.docker.com/r/vpcatlas/vpcatlas) · MIT licence

Read-only AWS network discovery. `vpcatlas` connects to one AWS account with auditor
permissions, maps its whole network (accounts, regions, VPCs, subnets, routing, gateways, endpoints,
load balancers, firewalls, DNS resolver, shared resources, the DNS and edge layer (Route 53, CloudFront, WAF, ACM, Shield), compute (ECS, EKS, EC2 instance groups, Lambda, API Gateway), data stores (RDS, ElastiCache, EFS, S3, DynamoDB) and account services (CloudTrail, GuardDuty, Config, CloudWatch, KMS, ECR)) and produces:

- a detailed inventory (JSON, Markdown and HTML), with a section for every external account that is linked to yours;
- architecture diagrams in draw.io (`.drawio`) and Lucidchart (`.lucid`) with the AWS Architecture Icons look,
  following the layout of the AWS Managed Services multi-account landing zone network reference:
  <https://docs.aws.amazon.com/managedservices/latest/onboardingguide/malz-network-arch.html>;
- a live dashboard (FastAPI) that refreshes the diagrams periodically and exports them.

Cross-account links are tracked as well: Transit Gateways shared through AWS RAM, VPC peering with accounts
you do not own, endpoints and Resolver rules shared with you. They show up as external accounts in the diagrams
and in the inventory.

## Manifesto

Six rules the tool is built on (the long form is on [the site](https://vpcatlas.com/#manifesto)):

1. **Read-only by design.** It only calls read APIs and prints the auditor policy it needs.
2. **Nobody should draw the map.** A drawn map is wrong a week later; the tool rebuilds it from the live account.
3. **Same input, same drawing.** Nothing moves between two runs unless the network moved, so a diff means something.
4. **Honest about gaps.** A denied call becomes a documented gap, never a silent hole in the map.
5. **It runs where you run it.** A command line tool, a binary and a container image; no agents, no telemetry.
6. **Built with AI, runs without it.** AI helped write this tool. The tool itself needs none: no model, no API key,
   no account with anyone, no bill per token. It works where AI tools are not allowed, or nobody pays for them.

## What it looks like

![Recording of vpcatlas discover running against a simulated AWS account, then listing the generated diagram files](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/demo.gif)

| Inventory only | Diagrams again from a saved graph |
| --- | --- |
| ![Recording of vpcatlas inventory writing the JSON, Markdown and HTML inventory, then the first lines of the Markdown file](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/demo-inventory.gif) | ![Recording of vpcatlas diagram drawing the Lucidchart diagrams again from a saved graph file, with no AWS calls](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/demo-diagram.gif) |

| Dashboard | Region diagram (eu-west-1) |
| --- | --- |
| ![The vpcatlas dashboard showing the live diagrams, run history and downloads](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/dashboard.png) | ![The eu-west-1 region diagram in draw.io: VPCs, Transit Gateway, endpoints and gateways](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/region-eu-west-1.png) |

![The diagram of the prod VPC in draw.io, with subnets, route tables and numbered flows](https://raw.githubusercontent.com/karina-pp/vpcatlas/main/docs/assets/vpc-prod.png)

*One VPC page: subnets, routing and numbered flows.*

The recordings and the diagrams come from `scripts/demo.sh` running against a simulated AWS account (moto), and the dashboard image is a capture of `vpcatlas serve` on the same account, so the ids you see are examples. See [demo/README.md](demo/README.md).

Status: alpha. Only read API calls are made. Nothing is created, changed or deleted in AWS.

## Install

Every channel includes the dashboard (`vpcatlas serve`), so there is nothing extra to install for it.

**Binary** (Linux and macOS, x86_64 and arm64; Windows x86_64). A folder with Python and every dependency inside, so no Python is
needed, and it starts in a few seconds. The script checks the SHA-256 of the download against the release
before it installs anything:

```bash
curl -fsSL https://vpcatlas.com/install.sh | sh
vpcatlas --version
```

On Windows, in PowerShell:

```powershell
irm https://vpcatlas.com/install.ps1 | iex
vpcatlas --version
```

On Linux and macOS it puts the folder in `~/.local/share/vpcatlas/<version>/` and links `vpcatlas` to it from
`/usr/local/bin` when that is writable and from `~/.local/bin` otherwise. Set `VPCATLAS_INSTALL_DIR` to choose the
directory of the link, `VPCATLAS_HOME` to choose where the folder goes and `VPCATLAS_VERSION` (for example `0.1.0`)
to pin a version. On Windows it puts the folder in `%LOCALAPPDATA%\vpcatlas\<version>\`, writes the launcher
`vpcatlas.cmd` in `%LOCALAPPDATA%\Programs\vpcatlas` and adds that directory to your user `PATH`; the same variables
work there, for example `$env:VPCATLAS_INSTALL_DIR`.
The archives, including the Windows one, are also on the [releases page](https://github.com/karina-pp/vpcatlas/releases)
with a `SHA256SUMS` file.

**Python package** (Python 3.12 or newer):

```bash
pipx install vpcatlas
vpcatlas --help
```

**Docker** (linux/amd64 and linux/arm64). The image runs the `vpcatlas` command; with no arguments it serves the
dashboard on port 8080:

```bash
# Dashboard on http://127.0.0.1:8080, reading AWS with the profile "audit"
docker run --rm -p 127.0.0.1:8080:8080 -v "$HOME/.aws:/home/atlas/.aws:ro" \
  vpcatlas/vpcatlas serve --host 0.0.0.0 --profile audit

# Any other command, with the diagrams written to ./vpcatlas-out
docker run --rm -v "$HOME/.aws:/home/atlas/.aws:ro" -v "$PWD/vpcatlas-out:/data" \
  vpcatlas/vpcatlas discover --profile audit --regions eu-west-1 --output-dir /data
```

On Linux add `--user "$(id -u):$(id -g)" -e HOME=/home/atlas` so the container can read `~/.aws` and write to the
output folder. A `credential_process` profile needs its helper binary, which the image does not contain. An SSO profile
works from the mounted cache while its token is valid; for a long run, or when the token may expire, pass short-lived keys
instead with `-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN`.

**Kubernetes** (Helm chart on GitHub Container Registry, signed and attested). Create the Secret
`vpcatlas-auth` with the password first; the pod does not start without it. [The Helm page](docs/deploy/helm.md)
has the values:

```bash
helm install atlas oci://ghcr.io/karina-pp/charts/vpcatlas --version 0.5.0
```

## CLI

```bash
# Discover the account and write every output format
vpcatlas discover --profile audit --regions eu-west-1,us-east-1 --output-dir ./out --format all

# Assume a role in the target account instead of using a profile
vpcatlas discover --role-arn arn:aws:iam::111122223333:role/AtlasAuditor --regions eu-west-1 \
  --output-dir ./out --format drawio

# Inventory and diagrams from a previous discovery
vpcatlas inventory --cache ./out/vpcatlas-graph.json --format md
vpcatlas diagram --cache ./out/vpcatlas-graph.json --format lucid

# Print the minimal auditor policy
vpcatlas iam-policy > auditor-policy.json
```

`vpcatlas discover` accepts `--format drawio|lucid|json|md|html|all`. Progress is shown with Rich.

### Service filters

A large account draws hundreds of nodes, and one repeated icon (API Gateway, say) can take most of the page.
`vpcatlas discover`, `vpcatlas inventory` and `vpcatlas diagram` take a service filter, a comma separated
list of service keys. The VPC core (regions, VPCs, subnets, route tables, gateways, interfaces, security
groups and network ACLs) is always kept.

| Option | Commands | Effect |
| --- | --- | --- |
| `--exclude-services apigateway,lambda` | `discover`, `inventory`, `diagram` | Leave these services out. `discover` skips their AWS calls, so the scan is shorter. |
| `--include-services lambda,s3` | `discover`, `inventory`, `diagram` | Keep only these services besides the VPC core. |

The two options exclude each other, and an unknown key is an error that lists the valid ones:
`acm`, `apigateway`, `cloudfront`, `cloudtrail`, `cloudwatch`, `config`, `directconnect`, `dynamodb`, `ec2`
(the instances), `ecr`, `ecs`, `efs`, `eks`, `elasticache`, `elbv2` (load balancers and target groups),
`endpoints`, `guardduty`, `kms`, `lambda`, `network-firewall`, `peering`, `prefix-lists`, `ram`, `rds`,
`route53`, `route53resolver`, `s3`, `shield`, `tgw`, `vpn` and `wafv2`.

```bash
# A scan and diagrams without API Gateway and Lambda
vpcatlas discover --exclude-services apigateway,lambda

# The same filter on a graph that was discovered in full
vpcatlas diagram --cache ./out/vpcatlas-graph.json --exclude-services apigateway
```

The filter is recorded in the metadata of `vpcatlas-graph.json` (`excluded_services`). Drawing from a graph
that lacks services prints a warning on stderr, so a partial diagram is not mistaken for a complete one.

### Diagram levels

Diagrams come at two levels. `vpcatlas discover` and `vpcatlas diagram` pick them with
`--level account|vpc|all` (default `all`).

| Level | Pages | Files |
| --- | --- | --- |
| `account` | The Global overview and one page per Region: VPCs, subnets, gateways, peerings and the Transit Gateway topology | `vpcatlas-global`, `vpcatlas-<region>` |
| `vpc` | One page per VPC, in more detail: route tables with their routes and associations, network ACLs per subnet, security groups, the subnets in full and every interface endpoint by name | `vpcatlas-vpc-<id>` |

```bash
# Only the VPC pages, as draw.io files
vpcatlas diagram --cache ./out/vpcatlas-graph.json --level vpc --format drawio
```

The summary prints how many pages each level produced. The dashboard lists both levels in its sidebar,
under "Account level" and "VPC level", and serves the very files `vpcatlas diagram` writes. On its History
page, "View changes on diagram" draws the changes between two snapshots on those pages
(`/diff/<older>/<newer>`): what was added is framed in green and what changed in orange.

### Layers and simple detail

Every draw.io page has one layer per family of services: Network (the containers and the VPC plumbing), Edge
(CloudFront, Route 53, ACM, WAF, Shield, load balancers), API Gateway, Compute, Data and Security; a family
the page does not use has no layer. Open the file in diagrams.net and use the layers panel (Ctrl+Shift+L) to
hide a family with one click, no new scan or render. An edge sits on the layer of its source, except an edge
that ends on API Gateway, which sits with it, so hiding API Gateway hides its edges too. Boxes carry absolute
coordinates, so a container does not drag its contents along when you move it.

`vpcatlas diagram --detail simple` draws a card instead of a crowd: inside a container, more than 3 resources
of one service become one icon captioned `API Gateway ×77`, and their edges are merged into one per pair,
labelled with the count. The default, `--detail full`, draws every resource. The edge lane (APIs, distributions)
is folded before the page is laid out, so the page is smaller and quicker to draw; Lucid files fold the lane
too, but not the crowds inside the VPCs.

```bash
vpcatlas diagram --cache ./out/vpcatlas-graph.json --format drawio --detail simple
```

## Credentials

vpcatlas reads credentials the way the AWS CLI does, and secret keys are never command flags: keys come
from the standard credential chain, so they stay out of your shell history and process list.

```bash
# 1. Default chain: AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (and AWS_SESSION_TOKEN) in the environment,
#    or the shared files ~/.aws/credentials and ~/.aws/config
export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
vpcatlas discover --regions eu-west-1

# 2. A named profile, including SSO profiles (run "aws sso login --profile audit" first)
vpcatlas discover --profile audit

# 3. Assume a role, with an external ID when the trust policy asks for one
vpcatlas discover --role-arn arn:aws:iam::111122223333:role/AtlasAuditor --external-id my-external-id

# 4. A role that requires MFA
vpcatlas discover --role-arn arn:aws:iam::111122223333:role/AtlasAuditor \
  --mfa-serial arn:aws:iam::999988887777:mfa/alice --mfa-token 123456

# 5. Length and name of the assumed-role session (900 to 43200 seconds, default 3600; name default "vpcatlas")
vpcatlas discover --role-arn arn:aws:iam::111122223333:role/AtlasAuditor \
  --session-duration 7200 --role-session-name audit-2026

# 6. Several accounts into one graph: repeat --profile, or repeat --role-arn
vpcatlas discover --profile prod --profile staging
vpcatlas discover --profile hub --role-arn arn:aws:iam::111122223333:role/AtlasAuditor \
  --role-arn arn:aws:iam::444455556666:role/AtlasAuditor
```

Roles that come with the runtime need no option at all, because the chain finds them: the instance profile
on EC2, the task role on ECS and Fargate, the pod role on EKS (IRSA through web identity, or EKS Pod
Identity) and the execution role of a Lambda function. Run `vpcatlas serve` or `vpcatlas discover` there
as is, and add `--role-arn` only to reach other accounts from that identity.

`--external-id`, `--session-duration` and `--role-session-name` also read `VPCATLAS_EXTERNAL_ID`,
`VPCATLAS_SESSION_DURATION` and `VPCATLAS_ROLE_SESSION_NAME`, which is how the dashboard container is
configured. `--mfa-serial` and `--mfa-token` belong to `discover`, `inventory` and `diagram`: a one-time code
cannot be reused, so the long-running `vpcatlas serve` does not take them.

## Dashboard

```bash
vpcatlas serve --port 8080
# or with a periodic refresh every 15 minutes
VPCATLAS_REFRESH_SECONDS=900 vpcatlas serve --port 8080
```

Routes:

| Route | Content |
| --- | --- |
| `GET /` | List of diagrams and an interactive viewer (diagrams.net viewer) |
| `GET /api/graph` | Network graph as JSON |
| `GET /api/inventory` | Inventory as JSON |
| `GET /export/{region}.drawio` | Regional diagram, draw.io format (`?detail=simple` folds crowded services into cards) |
| `GET /export/{region}.lucid` | Regional diagram, Lucidchart format |
| `POST /refresh` | Run a discovery now |

Above each diagram, one check box per family of services the page draws (Network, Edge, API Gateway, Compute,
Data, Security) hides or shows that family in the browser, with no new scan; the choice is remembered in the
browser, and "Simple detail" draws and downloads the page with `detail=simple`.

## Permissions

The tool needs read-only access. Use the policy this project publishes in
[`deploy/iam/auditor-policy.json`](deploy/iam/auditor-policy.json) (printed by `vpcatlas iam-policy`); the AWS managed
`ReadOnlyAccess` also works for a short run of the CLI in a sandbox account, but it reads far more than the tool needs.
Details, including cross-account `AssumeRole` trust policies, are in [`docs/iam.md`](docs/iam.md).

Access denied on a single service is logged and skipped, so the rest of the discovery still runs.

## Output formats

| Format | File | Use |
| --- | --- | --- |
| JSON | `vpcatlas-graph.json`, `vpcatlas-inventory.json` | Versioned schema, for automation |
| Markdown | `vpcatlas-inventory.md` | Review and pull requests |
| HTML | `vpcatlas-inventory.html` | Browsable inventory |
| draw.io | `diagrams/vpcatlas-<region>.drawio`, `diagrams/vpcatlas-global.drawio`, `diagrams/vpcatlas-vpc-<id>.drawio` | Editable diagrams in diagrams.net |
| Lucidchart | `diagrams/vpcatlas-<region>.lucid`, `diagrams/vpcatlas-global.lucid`, `diagrams/vpcatlas-vpc-<id>.lucid` | Import with Lucid Standard Import |

One diagram is produced per region, plus a global diagram with the Transit Gateway and peering topology
(account level), and one per VPC (VPC level, see [Diagram levels](#diagram-levels)).

## Documentation

- [Architecture](docs/architecture.md): pipeline and modules
- [Diagram style](docs/diagram-style.md): AWS look rules for draw.io and Lucid
- [Coverage](docs/coverage.md): AWS APIs read by each collector
- [IAM](docs/iam.md): permissions and cross-account access
- [Deploy](docs/deploy.md): Docker, Lambda, Kubernetes and ECS

## How it is built and released

Every change goes through the same public pipeline, and you can check what comes out of it.

- **On every change:** lint (ruff, actionlint, zizmor), type check (mypy), the tests on Linux, macOS and Windows with a
  coverage gate, the docs and the Python package build, both Docker images with their smoke tests (the Lambda one
  through the Runtime Interface Emulator) and a Trivy scan, the installers on three systems, and a dependency review.
- **On every release:** binaries for five platforms, `SHA256SUMS`, an SBOM, signed and attested images, a Trivy gate
  before anything is pushed, and a last job that installs the published release with the live installers.
- **Every night:** `pip-audit`, a link check, the layout benchmark and a scan of the published image. CodeQL,
  OpenSSF Scorecard and Dependabot run weekly.

### Verify what you install

```bash
gh attestation verify vpcatlas-X.Y.Z-linux-x86_64.tar.gz --owner karina-pp
gh attestation verify SHA256SUMS --owner karina-pp
gh attestation verify oci://index.docker.io/vpcatlas/vpcatlas:X.Y.Z --owner karina-pp
cosign verify index.docker.io/vpcatlas/vpcatlas:X.Y.Z --certificate-identity-regexp '^https://github.com/karina-pp/vpcatlas/' --certificate-oidc-issuer https://token.actions.githubusercontent.com
```

Images and SBOMs are signed and attested from 0.4.1 on, the first release made by this pipeline; earlier releases
carry only the attestations of the archives and `SHA256SUMS`. Verifying the image signature needs cosign 3 or newer.

More in [How VPC Atlas is built and released](docs/engineering.md); the runs are on the
[Actions page](https://github.com/karina-pp/vpcatlas/actions). To report a vulnerability, see [SECURITY.md](SECURITY.md);
to contribute, see [CONTRIBUTING.md](CONTRIBUTING.md).

## Roadmap

**v1 (0.x):** discovery of networking resources and cross-account links, JSON/Markdown/HTML inventory,
draw.io and Lucid diagrams, CLI, FastAPI dashboard, container images and a Helm chart for Kubernetes, Lambda
and ECS.

**v2:** Network Manager and Cloud WAN topologies, Direct Connect and VPN path tracing, drift between two
snapshots, diagram diffs in pull requests, multi-account runs from an AWS Organizations list.

## License

MIT. Copyright Karina Pérez.
