Metadata-Version: 2.4
Name: tarmac-cli
Version: 0.4.1
Summary: Enterprise AWS Governance & Multi-Account Landing Zone CLI
Author-email: Nicholas Christian <nicholasdchristian@gmail.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/nickdchristian/tarmac-cli
Project-URL: Documentation, https://github.com/nickdchristian/tarmac-cli#readme
Project-URL: Repository, https://github.com/nickdchristian/tarmac-cli.git
Project-URL: Issues, https://github.com/nickdchristian/tarmac-cli/issues
Keywords: aws,aws-organizations,landing-zone,governance,cloudformation,iam-identity-center,finops,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Intended Audience :: Information Technology
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: boto3>=1.42.0
Requires-Dist: botocore>=1.42.0
Requires-Dist: typer>=0.16.0
Requires-Dist: rich>=13.8.0
Requires-Dist: pydantic[email]>=2.8.0
Requires-Dist: pyyaml>=6.0.2
Dynamic: license-file

# Tarmac

[![PyPI version](https://img.shields.io/pypi/v/tarmac-cli)](https://pypi.org/project/tarmac-cli/)
[![Python versions](https://img.shields.io/pypi/pyversions/tarmac-cli)](https://pypi.org/project/tarmac-cli/)
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE)

Tarmac sets up and maintains a multi-account AWS Organization from three YAML files: OUs, accounts, guardrail
SCPs, an organization CloudTrail, security services and IAM Identity Center. Change the YAML, run
`tarmac deploy`, and tarmac makes AWS match. Every run is safe to repeat.

## Install

```bash
uv tool install tarmac-cli     # or: pip install tarmac-cli
tarmac --help
```

## Quick start: a brand-new AWS account

Tarmac runs in the organization's management account. It can't run as the root user, because root can't reach
member accounts, so you first create an IAM Identity Center login for yourself. AWS CloudShell is the easiest
place to do this.

1. Sign in as root, turn on MFA, and add a payment method.
2. In the console, enable **IAM Identity Center**. Pick its Region carefully: moving it later means starting
   over. This also creates the organization.
3. In CloudShell:
   ```bash
   pip install tarmac-cli
   tarmac init          # writes config/organization.yaml, accounts.yaml, identity.yaml
   ```
   Edit the files. Put yourself in `admin_user` in `identity.yaml`, and give every account in `accounts.yaml` a
   real, unique email (plus addresses such as `aws+prod@example.com` work if your mail provider supports them).
4. Still in CloudShell, as root:
   ```bash
   tarmac bootstrap
   ```
   This creates your Identity Center user, gives it two permission sets on the management account
   (`TarmacDeployment` for tarmac, `ManagementAdministrator` for the console), and adds a `tarmac` profile to
   `~/.aws/config`. It ends by printing the steps for your first sign-in.
5. Follow those steps to sign in, then deploy:
   ```bash
   export AWS_PROFILE=tarmac
   tarmac preflight           # checks the account is ready
   tarmac deploy --dry-run    # shows what would change, changes nothing
   tarmac deploy
   ```

**CloudShell tips:** always use `aws sso login --use-device-code`, because the normal login can't call back to
your browser. Re-run `export AWS_PROFILE=tarmac` after CloudShell restarts; without it, tarmac sees root and
stops.

## Using an existing organization

`tarmac import` reads your organization and writes matching config files, keeping any file it changes as
`<name>.bak`. It changes nothing in AWS.

```bash
tarmac import --config-dir my-org
cd my-org
tarmac status --detail
tarmac deploy --dry-run
```

Read what it reports, and check the dry run before the first real deploy. Keep in mind:

- **Declare existing accounts with their real emails.** If a name matches but the email doesn't, tarmac stops
  rather than guess.
- **Accounts you don't declare are left alone,** except ones tarmac created earlier and you have since removed
  from `accounts.yaml`. Those are moved to the Suspended OU (`quarantine_removed_accounts: false` turns this off).
- **Never change `organization.name` after the first deploy.** Every stack is named after it.
- **An existing organization trail isn't replaced.** Tarmac adds its own; delete the old one once the new one is
  delivering logs.
- **Set `delete_default_vpc: false`** for accounts that already run workloads.

## What it deploys

`tarmac deploy` runs six phases in order. `--phase N` runs one, and `--phase 4 --account NAME` updates a single
account.

| Phase | What it does |
| :--- | :--- |
| 1 | Organization settings, contacts, trusted services, root access management, cost tags, the inventory bucket |
| 2 | OUs and service control policies |
| 3 | Log archive buckets and the organization CloudTrail |
| 4 | Member accounts, their tags, budgets and default VPC cleanup |
| 5 | Terraform state backend, audit account, AWS Config, GuardDuty, Security Hub, root user alert |
| 6 | Identity Center permission sets, users, groups and assignments |

Following AWS's guidance, the management account holds only what has to live there:

- **Management account:** Organizations, SCPs, Identity Center, the trail's stack, the AWS Config StackSet, and
  the inventory bucket, which records the OUs, users, groups and settings tarmac created so everyone running
  tarmac shares it.
- **Audit account:** delegated administrator for CloudTrail, AWS Config, GuardDuty, Security Hub and IAM root
  access management.
- **Log archive account:** the CloudTrail and Config log buckets.

`tarmac init` starts you with the OUs AWS recommends: Security, Infrastructure, Workloads (Prod and Test),
Deployments, Sandbox, Policy Staging and Suspended.

Everything comes from the [CloudFormation templates](src/tarmac/templates/cloudformation) and
[SCPs](src/tarmac/templates/policies/scp) bundled with tarmac. `tarmac init --with-templates` copies them into your
project; tarmac then uses your copies, so you can review and version them.

Tarmac itself runs with the least-privilege policy in
[`tarmac-deployment.json`](src/tarmac/templates/policies/iam/tarmac-deployment.json). After upgrading tarmac,
run `tarmac bootstrap` again to update it; `tarmac preflight` warns when it's out of date.

## Commands

| Command | What it does |
| :--- | :--- |
| `tarmac init` | Write starter config files |
| `tarmac validate` | Check the config files, without AWS |
| `tarmac bootstrap` | Once, as root: create your Identity Center login and the `tarmac` profile |
| `tarmac preflight` | Check the management account is ready |
| `tarmac deploy` | Apply the config (`--dry-run` to preview, `--phase N` for one phase) |
| `tarmac status` | Compare AWS with the config (`--detail` lists every difference) |
| `tarmac import` | Write config files from an existing organization |
| `tarmac destroy` | Remove what tarmac deployed (see [Tearing down](#tearing-down)) |
| `tarmac info` | Show who you're signed in as (`--strict` fails if tarmac can't run) |
| `tarmac account list` | List accounts in the organization |
| `tarmac account suspend NAME` | Move an account to the Suspended OU (`--close` closes it) |
| `tarmac logs FILE` | Summarize runs recorded with `--log-file` |
| `tarmac inventory` | Show what tarmac has recorded creating |

## Options

All of these go in `organization.yaml`. Options with a real cost are off until you turn them on.

**Log retention and locking.** CloudTrail logs are kept forever unless you set a retention. Object Lock stops anyone
deleting logs during the lock period. It's recommended, but S3 can never turn it off again, so tarmac asks you to
decide (`object_lock: null` to say no).

```yaml
cloudtrail:
  retention_days: 365
  object_lock: {mode: GOVERNANCE, retention_days: 365}   # COMPLIANCE can't be bypassed, even by root
  enable_kms: true   # encrypt logs with a KMS key (~$1/month); CIS and Security Hub ask for it
```

**Security services.**

```yaml
security_services:
  delegated_account: audit
  guardduty:
    enabled: true
    features: {s3_data_events: true}   # optional paid protections stay off unless listed
  securityhub:
    enabled: true
    standards: [aws-foundational-security-best-practices]   # applied to every account
  config_recorder:
    enabled: true                    # AWS Config in every account; Security Hub needs it
    recording_frequency: CONTINUOUS  # usually cheaper than DAILY
  root_alert:
    enabled: true                    # emails contacts.security.email when root is used (on by default)
```

**Terraform state.** Phase 5 creates a state bucket in the deployment account. Its name is in the
`<org>-terraform-backend` stack's `BucketName` output. Locking uses S3 (`use_lockfile = true`, Terraform 1.10+);
set `terraform_backend.enable_dynamodb: true` if you need a DynamoDB lock table.

**Example SCPs.** [`examples/policies/scp`](examples/policies/scp) has two optional policies, one restricting
Regions and one stopping member accounts turning off GuardDuty or Security Hub. Keep their
`OrganizationAccountAccessRole` exemption (tarmac works through that role), and test them on one OU before
attaching them to the root.

## Tearing down

```bash
tarmac destroy --dry-run
tarmac destroy
```

`destroy` removes the stacks, buckets, budgets, SCPs and permission sets tarmac deployed, so `deploy` can rebuild
them. It keeps the organization, OUs and member accounts. It also refuses to touch anything tagged as production
unless you pass `--force`, and skips anything tarmac didn't create.

- `--preserve-backend` keeps the Terraform state.
- `--disable-security-services` also turns off GuardDuty, Security Hub and Config. This deletes their findings.
- `--everything` also removes the OUs, Identity Center users and groups, and organization settings tarmac created,
  plus the `tarmac bootstrap` permission sets (except the one you're signed in with), and finally the inventory
  bucket once everything it records is gone. It never closes accounts.

## Logging

Add `-v` to see each change as it happens, or `--log-file run.jsonl` (or set `TARMAC_LOG_FILE`) to record a run.
Both go before the command. Inspect the results with `tarmac logs`:

```bash
tarmac -v --log-file run.jsonl deploy
tarmac logs run.jsonl --run latest            # what the last run did, and what failed
tarmac logs run.jsonl --outcome failed
```

## Development

```bash
uv sync --locked
uv run pytest
uv run ruff check . && uv run ruff format --check . && uv run basedpyright
uv run cfn-lint src/tarmac/templates/cloudformation/*.yaml
uv run tarmac validate --config-dir examples/config
```

## License

[Apache License 2.0](LICENSE)
