aac-cli 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aac_cli-0.1.2 → aac_cli-0.1.4}/PKG-INFO +208 -10
- {aac_cli-0.1.2 → aac_cli-0.1.4}/README.md +206 -9
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/__init__.py +1 -1
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/cli.py +250 -34
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/config.py +45 -2
- aac_cli-0.1.4/aac_cli/config_render.py +266 -0
- aac_cli-0.1.4/aac_cli/dev_material.py +405 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/idp_recovery.py +4 -50
- aac_cli-0.1.4/aac_cli/init_cli.py +1392 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/profiles.py +12 -2
- aac_cli-0.1.4/aac_cli/secure_files.py +200 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/sso_login.py +85 -16
- aac_cli-0.1.4/aac_cli/workspace_cli.py +525 -0
- aac_cli-0.1.4/aac_cli/workspace_health.py +156 -0
- aac_cli-0.1.4/aac_cli/workspace_layout.py +467 -0
- aac_cli-0.1.4/aac_cli/workspace_manifest.py +144 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/PKG-INFO +208 -10
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/SOURCES.txt +16 -1
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/requires.txt +1 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/pyproject.toml +7 -1
- aac_cli-0.1.4/tests/test_b241_edge_paths.py +925 -0
- aac_cli-0.1.4/tests/test_config_render.py +177 -0
- aac_cli-0.1.4/tests/test_dev_material.py +127 -0
- aac_cli-0.1.4/tests/test_hosted_domains_cli.py +569 -0
- aac_cli-0.1.4/tests/test_init_cli.py +1417 -0
- aac_cli-0.1.4/tests/test_inventory_docs.py +70 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_sso_login_cli.py +121 -1
- aac_cli-0.1.4/tests/test_workspace_cli.py +400 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/LICENSE +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/__main__.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/admin_key_pem.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/api_key_rotation_state.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli/registration_state.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/dependency_links.txt +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/entry_points.txt +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/aac_cli.egg-info/top_level.txt +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/setup.cfg +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_aac_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_admin_key_pem.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_api_key_reissue_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_api_key_rotation_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_api_key_rotation_state.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_idp_recovery_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_profile_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_registration_recovery_cli.py +0 -0
- {aac_cli-0.1.2 → aac_cli-0.1.4}/tests/test_registration_state.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aac-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: The aac platform CLI — headless operator interface to the AAC control plane (tenant registration, chain audit).
|
|
5
5
|
Author: Agent Authority Cloud Project
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,6 +9,7 @@ Description-Content-Type: text/markdown
|
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: httpx>=0.28
|
|
11
11
|
Requires-Dist: cryptography>=42.0
|
|
12
|
+
Requires-Dist: PyYAML>=6.0
|
|
12
13
|
Provides-Extra: test
|
|
13
14
|
Requires-Dist: pytest>=8.0; extra == "test"
|
|
14
15
|
Requires-Dist: pytest-httpx>=0.30; extra == "test"
|
|
@@ -99,14 +100,14 @@ aac sso login --profile dev # thereafter: plain login
|
|
|
99
100
|
# Tenant ids are the server-allocated canonical tnt-<uuid> form
|
|
100
101
|
# (B154 PR 5) — captured at registration / shown by `aac profile show`.
|
|
101
102
|
aac tenant list # which tenant ids exist (no 409 probe)
|
|
102
|
-
aac tenant describe --
|
|
103
|
+
aac tenant describe --profile dev # assigned domain, workloads + key METADATA
|
|
103
104
|
aac tenant update --tenant-id tnt-<uuid> --display-name "ACME Manufacturing Inc"
|
|
104
105
|
|
|
105
106
|
# B121/B228 — business-domain control proof and bounded claim lifecycle.
|
|
106
107
|
# Registration can capture up to 16 pending rows with repeatable --tenant-domain.
|
|
107
108
|
# The issue/verify/release/revoke commands
|
|
108
109
|
# require the owning tenant's tenant-admin session and default --tenant-id from
|
|
109
|
-
# the profile;
|
|
110
|
+
# the profile; tenant describe also uses the selected profile by default.
|
|
110
111
|
aac tenant register --display-name "ACME" --contact ops@acme.example \
|
|
111
112
|
--tenant-domain acme.example
|
|
112
113
|
aac tenant issue-domain-challenge --domain acme.example
|
|
@@ -117,7 +118,7 @@ aac tenant verify-domain --domain acme.example
|
|
|
117
118
|
# never performs an implicit binding write.
|
|
118
119
|
aac tenant bind-trust-domain --trust-domain acme.example
|
|
119
120
|
aac tenant list-trust-domains --output table
|
|
120
|
-
aac tenant describe --
|
|
121
|
+
aac tenant describe --profile dev --output table # assigned binding status + TXT
|
|
121
122
|
aac tenant release-domain --domain acme.example --reason "planned transfer"
|
|
122
123
|
aac tenant revoke-domain --domain acme.example --reason "DNS control incident"
|
|
123
124
|
|
|
@@ -272,16 +273,17 @@ aac sso register-idp --shared --file shared-github.json \
|
|
|
272
273
|
# admin verb (tenant list/describe/update, self-serve register-idp)
|
|
273
274
|
# then rides the session automatically.
|
|
274
275
|
aac sso login --tenant-id tnt-550e8400-e29b-41d4-a716-446655440000
|
|
275
|
-
aac sso login --
|
|
276
|
+
aac sso login --idp github # developer tenant: GitHub or Google sign-in
|
|
277
|
+
aac sso login --issuer https://login.microsoftonline.com/<tid>/v2.0 # enterprise IdP, by issuer URL
|
|
276
278
|
aac sso login --flow pkce --no-browser # print the URL, don't launch
|
|
277
279
|
|
|
278
280
|
# Sessions are REFRESH-LESS by design (Eng Spec §XVII.2): on expiry
|
|
279
281
|
# any admin verb tells you to re-run `aac sso login` — there is no
|
|
280
282
|
# refresh token to steal, and no silent re-authentication.
|
|
281
283
|
|
|
282
|
-
# B155 — session
|
|
283
|
-
#
|
|
284
|
-
aac sso whoami --
|
|
284
|
+
# B155/B239 — local session/profile inspection; no server call or JWT parsing.
|
|
285
|
+
# whoami exits 0 = unexpired cache, 3 = expired/none (§14).
|
|
286
|
+
aac sso whoami --profile dev --output table # cached session + saved assigned domain
|
|
285
287
|
aac sso logout --tenant-id tnt-550e8400-e29b-41d4-a716-446655440000
|
|
286
288
|
```
|
|
287
289
|
|
|
@@ -495,8 +497,9 @@ coexistence, Eng Spec §XVII.9):
|
|
|
495
497
|
expiry fails fast locally with the re-login message instead of
|
|
496
498
|
dialing out; the server's own session 401s carry the same
|
|
497
499
|
remediation (the server stays authoritative). `aac sso logout`
|
|
498
|
-
removes the file; `aac sso whoami` reports its tenant + expiry
|
|
499
|
-
|
|
500
|
+
removes the file; `aac sso whoami` reports its tenant + expiry and, when
|
|
501
|
+
available, the matching profile's saved AAC-assigned domain. Both commands
|
|
502
|
+
operate locally; `whoami` does not verify current server-side binding status.
|
|
500
503
|
|
|
501
504
|
## Your tenant_id
|
|
502
505
|
|
|
@@ -547,3 +550,198 @@ ceremony-only, and existing binding history remains B181.
|
|
|
547
550
|
needed. Against a live stack: bring up the joined topology
|
|
548
551
|
(`./bin/run-wedge-a-control-plane-compose.sh --keep-up`) and point the
|
|
549
552
|
flags at localhost.
|
|
553
|
+
|
|
554
|
+
## Guided setup: `aac init` and `aac workspace`
|
|
555
|
+
|
|
556
|
+
`aac init` takes a developer from an installed CLI to a complete, runnable
|
|
557
|
+
local workload in one command. It signs you in, registers a developer tenant
|
|
558
|
+
(or reuses the one your profile is already bound to), takes the AAC-assigned
|
|
559
|
+
hosted trust domain, registers the sample workload, generates development
|
|
560
|
+
keys and certificates, registers the tenant-admin public key together with a
|
|
561
|
+
new tenant, and writes a complete sidecar configuration plus the publisher
|
|
562
|
+
environment and a Compose variable file.
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
# Developer tier: sign in with GitHub or Google. The command shows what it
|
|
566
|
+
# will create and asks before registering the tenant.
|
|
567
|
+
aac init --profile stage --admin-url https://api.stage.cascadeauth.dev \
|
|
568
|
+
--data-plane-url https://api.stage.cascadeauth.dev \
|
|
569
|
+
--trust-url https://trust.stage.cascadeauth.dev \
|
|
570
|
+
--display-name 'YOUR TEAM' --contact 'YOUR EMAIL' --idp github
|
|
571
|
+
|
|
572
|
+
# Scripted: every prompt has a flag; --create-tenant acknowledges creating a
|
|
573
|
+
# permanent tenant when stdin is not a terminal.
|
|
574
|
+
aac init --profile stage --admin-url ... --trust-url ... \
|
|
575
|
+
--display-name 'YOUR TEAM' --contact 'YOUR EMAIL' --idp github --create-tenant
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
Progress lines `[1/5]` to `[5/5]` name the five steps: tenant, sign-in, hosted trust
|
|
579
|
+
domain, workload, material and rendering. A rerun prints every step, marking the ones
|
|
580
|
+
already done. The sign-in you chose with `--idp` is remembered in the workspace, so a
|
|
581
|
+
rerun (or `aac sso login --idp github` by hand when a session expires) never asks you
|
|
582
|
+
to pick between GitHub and Google. Workspace commands take `--workspace <name>`; the
|
|
583
|
+
profile is recorded in the workspace, so `--profile` is optional there and only checked.
|
|
584
|
+
|
|
585
|
+
What it creates, and where:
|
|
586
|
+
|
|
587
|
+
* `~/.aac/workspaces/<name>/` — the **workspace** for one workload (default
|
|
588
|
+
name `starter`): `pki/` with what the sidecar container mounts — the
|
|
589
|
+
workload, terminal-attestation and localhost TLS key pairs, this
|
|
590
|
+
workspace's root-signing key and the outbound CA bundle; `pair/` with what
|
|
591
|
+
both containers mount at `/run/secrets` — the pairing secret and the public
|
|
592
|
+
development CA certificate; `ca/` with the development CA private key (kept
|
|
593
|
+
out of both mounts so no container ever sees the key that mints
|
|
594
|
+
identities); `sidecar-config.yaml`; `compose.env` (non-secret variables for
|
|
595
|
+
a Compose consumer); and an internal manifest that lets a rerun resume.
|
|
596
|
+
* `~/.aac/tenants/<tenant-id>/` — **tenant-level** material shared by every
|
|
597
|
+
workspace of that tenant: the tenant-admin signing key, the publisher's
|
|
598
|
+
input directories (`root-keys/`, `spiffe-bundle/` — public halves only) and
|
|
599
|
+
the rendered `publisher.env`.
|
|
600
|
+
* The tenant API key stays where the CLI always kept it,
|
|
601
|
+
`~/.aac/credentials/<tenant-id>`; the rendered configuration references it
|
|
602
|
+
by path.
|
|
603
|
+
|
|
604
|
+
### What each file is for, and what to back up
|
|
605
|
+
|
|
606
|
+
The table below is rendered from the CLI's own layout module and checked by a test, so it
|
|
607
|
+
cannot drift from the code. `<workspace>` is the workspace name (default `starter`) and
|
|
608
|
+
`<tenant-id>` the server-allocated tenant id.
|
|
609
|
+
|
|
610
|
+
<!-- inventory-table:start -->
|
|
611
|
+
| Material | Where | Used for | Lifetime | Back up? |
|
|
612
|
+
|---|---|---|---|---|
|
|
613
|
+
| tenant_api_key | `~/.aac/credentials/<tenant-id>` | CLI data-plane calls; the sidecar's workload projection | until retired or rotated; `aac tenant reissue-api-key` | **Yes.** save a protected copy in your secret manager; loss needs `aac tenant reissue-api-key` |
|
|
614
|
+
| tenant_admin_session | `~/.aac/credentials/<tenant-id>.session` | CLI admin calls | hours; `aac sso login` | No. sign in again |
|
|
615
|
+
| tenant_admin_signing_key | `~/.aac/tenants/<tenant-id>/tenant-admin.pem`, `~/.aac/tenants/<tenant-id>/tenant-admin.pub.pem` | the publisher signs trust-material uploads; the public half is registered with AAC | until rotated; `aac tenant rotate-admin-key` | **Recommended.** recommended for developer tenants (loss needs `aac tenant rotate-admin-key`); production custody belongs in an HSM/KMS, not a password manager |
|
|
616
|
+
| root_signing_key | `~/.aac/workspaces/<workspace>/pki/root.pem`, `~/.aac/workspaces/<workspace>/pki/root.pub.pem`, `~/.aac/tenants/<tenant-id>/root-keys/<workspace>-root-v1.pub.pem` | the sidecar mints authority chains; the public half is published under the key id | until you retire its key id (root key ids are fixed per workspace name) | No. never restore: a replacement workspace gets a new name and therefore a new key id, published alongside the old one until the old one is retired |
|
|
617
|
+
| development_ca | `~/.aac/workspaces/<workspace>/ca/dev-ca.key`, `~/.aac/workspaces/<workspace>/pki/dev-ca.crt`, `~/.aac/workspaces/<workspace>/pair/dev-ca.crt`, `~/.aac/tenants/<tenant-id>/spiffe-bundle/<workspace>-dev-ca.ca.pem` | signs the workload, terminal and TLS certificates; peers trust it via the published bundle | 7 days; `aac workspace renew --ca` | No. development only; reissue |
|
|
618
|
+
| workload_svid | `~/.aac/workspaces/<workspace>/pki/workload.key`, `~/.aac/workspaces/<workspace>/pki/workload.crt` | the sidecar's SPIFFE identity: proves on every live request that this workload holds the key behind its certificate | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
619
|
+
| terminal_attestation | `~/.aac/workspaces/<workspace>/pki/terminal.key`, `~/.aac/workspaces/<workspace>/pki/terminal.crt` | signs the receipt (terminal attestation) the sidecar issues when this workload completes a delegated request; auditors verify it offline against your published CA; kept separate from the workload key so neither can forge the other's role | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
620
|
+
| localhost_tls | `~/.aac/workspaces/<workspace>/pki/server.key`, `~/.aac/workspaces/<workspace>/pki/server.crt` | the sidecar's HTTPS listener | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
621
|
+
| outbound_ca_bundle | `~/.aac/workspaces/<workspace>/pki/outbound-ca.pem` | the sidecar verifies TLS to AAC and to itself | rebuilt by renew; `aac workspace renew` | No. derived |
|
|
622
|
+
| pairing_secret | `~/.aac/workspaces/<workspace>/pair/pairing.secret` | the sidecar and its agent authenticate each other (same bytes in both) | until regenerated | No. regenerable; both processes must read the same file |
|
|
623
|
+
| workspace_manifest | `~/.aac/workspaces/<workspace>/manifest.json` | the workspace's identities and progress; every `workspace` verb reads it first | for the life of the workspace | **Recommended.** cannot be recreated by any command; without it start a new workspace under a new name (see the machine-loss procedure) |
|
|
624
|
+
| published_public_inputs | `~/.aac/tenants/<tenant-id>/root-keys`, `~/.aac/tenants/<tenant-id>/spiffe-bundle` | the publisher's input directories: every root public key and CA certificate this tenant has published, across all workspaces | for the life of the tenant | **Recommended.** back up with the tenant directory: a replacement workspace must publish its new root key alongside a still-ACTIVE previous one (the control plane refuses a root-key set that drops every ACTIVE key at once) |
|
|
625
|
+
| rendered_files | `~/.aac/workspaces/<workspace>/sidecar-config.yaml`, `~/.aac/workspaces/<workspace>/compose.env`, `~/.aac/tenants/<tenant-id>/publisher.env` | non-secret configuration derived from the manifest | re-rendered on demand; `aac workspace render --force` | No. derived; `aac workspace render --force` recreates them |
|
|
626
|
+
<!-- inventory-table:end -->
|
|
627
|
+
|
|
628
|
+
#### If you lose this machine
|
|
629
|
+
|
|
630
|
+
Back up two things while the machine is healthy: the tenant API key at
|
|
631
|
+
`~/.aac/credentials/<tenant-id>`, and the whole tenant directory
|
|
632
|
+
`~/.aac/tenants/<tenant-id>/` (the admin signing key plus the `root-keys/` and
|
|
633
|
+
`spiffe-bundle/` public inputs the publisher has already published). The workspace
|
|
634
|
+
manifest is worth keeping too, but a workspace can always be replaced. Then, on the new
|
|
635
|
+
machine:
|
|
636
|
+
|
|
637
|
+
1. Install the CLI and `aac profile create <name> --admin-url … --data-plane-url …`.
|
|
638
|
+
Sign in with `aac sso login --idp github --tenant-id <tenant-id> --profile <name>`
|
|
639
|
+
(or `--issuer <url>` for an enterprise connection): the remaining
|
|
640
|
+
steps register a workload and read the tenant's admin-key state, which need a
|
|
641
|
+
tenant-admin session whatever way the tenant was registered (a ceremony bootstrap
|
|
642
|
+
token only covers registration and hosted-domain assignment).
|
|
643
|
+
2. Restore the tenant API key to `~/.aac/credentials/<tenant-id>` (mode `0600`), or issue a
|
|
644
|
+
new one with `aac tenant reissue-api-key` if it was not backed up. Restore
|
|
645
|
+
`~/.aac/tenants/<tenant-id>/` from the backup (directories `0700`, files `0600`).
|
|
646
|
+
3. Run `aac init --profile <name> --workspace <new-name>` with a **new** workspace name.
|
|
647
|
+
Root key ids are fixed per workspace name and the control plane never accepts new key
|
|
648
|
+
material under an old id, so the replacement workspace publishes a new id
|
|
649
|
+
(`<new-name>-root-v1`) and a new development CA anchor.
|
|
650
|
+
4. Start the publisher from the restored tenant directory. Its root-key set now holds the
|
|
651
|
+
old and the new public keys, which is what the control plane requires: a set that
|
|
652
|
+
drops every currently ACTIVE key at once is refused. Retire the old key later by
|
|
653
|
+
removing its public file once nothing signs with it.
|
|
654
|
+
|
|
655
|
+
Reusing the old workspace name on the new machine is refused on purpose: the restored
|
|
656
|
+
tenant directory still holds that name's published root key, and `init` never generates
|
|
657
|
+
different key material under an existing key id. The development certificates and the
|
|
658
|
+
pairing secret are regenerated by step 3; they are never restored.
|
|
659
|
+
|
|
660
|
+
Every private file is created once at mode `0600` under `0700` directories
|
|
661
|
+
and is never overwritten; before generating anything, `init` checks every
|
|
662
|
+
destination and refuses with the full list if one already exists. Rerunning
|
|
663
|
+
`aac init` resumes an interrupted setup (outcome `resumed`), reports a
|
|
664
|
+
complete workspace (outcome `complete`, exit 0), or names the exact conflict
|
|
665
|
+
(exit 3). Every post-registration step is pinned to the workspace's tenant,
|
|
666
|
+
so a profile that has since been pointed at another tenant is refused rather
|
|
667
|
+
than mixed in. A rerun on a complete workspace validates it offline (binding,
|
|
668
|
+
files, permissions, certificate validity, CA fitness) and exits 3 with the
|
|
669
|
+
next command if it is no longer usable. Missing flags for a new tenant are
|
|
670
|
+
usage errors (exit 2).
|
|
671
|
+
|
|
672
|
+
**`aac init` never installs or replaces a tenant-admin authority for an
|
|
673
|
+
existing tenant.** For a new tenant it generates the admin key first and
|
|
674
|
+
registers the public half together with the tenant, which the control plane
|
|
675
|
+
creates in one transaction, so no competing authority can ever be retired by
|
|
676
|
+
setup. For an existing tenant it only checks: the key on this machine must
|
|
677
|
+
already be the tenant's ACTIVE admin key. If the tenant's ACTIVE key is not on
|
|
678
|
+
this machine, `init` stops and tells you to restore that key to
|
|
679
|
+
`~/.aac/tenants/<tenant-id>/tenant-admin.pem` (or pass
|
|
680
|
+
`--tenant-admin-key-file`); if the tenant has no admin key at all, it tells
|
|
681
|
+
you to install one deliberately with `aac tenant rotate-admin-key`. Replacing
|
|
682
|
+
an authority is always that deliberate command, never a side effect of setup. Managed directories under `~/.aac/workspaces/` and
|
|
683
|
+
`~/.aac/tenants/` must be real directories at mode `0700`; a symlink or a
|
|
684
|
+
looser mode is refused before anything is written.
|
|
685
|
+
A second workspace for the same tenant (`--workspace other`) reuses the
|
|
686
|
+
tenant-admin key and gets its own root key id. Each key has an
|
|
687
|
+
`--<role>-key-file` flag to use existing material instead of generating it.
|
|
688
|
+
|
|
689
|
+
**Everything generated is development material.** The CA lives seven days and
|
|
690
|
+
the leaf certificates one day; nothing here qualifies for production
|
|
691
|
+
regardless of the tenant's hosted domain. Moving to production means
|
|
692
|
+
`aac tenant rotate-admin-key` with a key under production custody, a new root
|
|
693
|
+
key id published by your publisher, and certificates from your approved
|
|
694
|
+
issuer.
|
|
695
|
+
|
|
696
|
+
Inspect and maintain a workspace with the `workspace` noun:
|
|
697
|
+
|
|
698
|
+
```bash
|
|
699
|
+
aac workspace status --workspace starter # what exists, expiry, permissions, next command
|
|
700
|
+
aac workspace status --workspace starter --remote # also: is the public trust material visible?
|
|
701
|
+
aac workspace renew --workspace starter # fresh leaf keys + certificates; old ones archived
|
|
702
|
+
aac workspace render --workspace starter --layout container --force # container path layout
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
`status` is offline by default and exits 3 when material is missing, expired
|
|
706
|
+
or unsafely permissioned. `renew` reissues the one-day certificates with fresh
|
|
707
|
+
keys and reissues the development CA only when it is expired or within a day
|
|
708
|
+
of expiry (or with `--ca`); a new CA is published under the next anchor id and
|
|
709
|
+
needs the publisher restarted. `render` never touches keys and refuses to
|
|
710
|
+
overwrite rendered files unless `--force` is given. Command, flag and path
|
|
711
|
+
names are provisional until the public starter example has consumed them.
|
|
712
|
+
|
|
713
|
+
## Assigned tenant domains (B239)
|
|
714
|
+
|
|
715
|
+
Registration automatically saves the server-assigned `hosted_trust_domain` in
|
|
716
|
+
the selected profile. The CLI displays the full name, explains its purpose in
|
|
717
|
+
SPIFFE identities/certificates/trust configuration, and prints the command for
|
|
718
|
+
finding it again. No manual copy is required. With JSON output, this guidance
|
|
719
|
+
goes to stderr and stdout remains one JSON document; table output includes it
|
|
720
|
+
inline. Completed-registration recovery provides the same saved-name guidance
|
|
721
|
+
without changing credential-reissue requirements.
|
|
722
|
+
|
|
723
|
+
```sh
|
|
724
|
+
aac profile show dev --output table # saved locally, offline
|
|
725
|
+
aac tenant describe --profile dev --output table # assigned name + current binding status
|
|
726
|
+
aac tenant list-trust-domains --profile dev --output table # current ACTIVE bindings
|
|
727
|
+
aac tenant list-trust-domains --profile dev --all --output table # includes revoked history
|
|
728
|
+
aac sso whoami --profile dev --output table # cached session + matching saved name
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
`tenant describe` accepts an optional `--tenant-id`; the usual flag → environment
|
|
732
|
+
→ selected profile precedence applies. Its response comes from AAC. Binding
|
|
733
|
+
table output labels AAC-assigned/custom origin, ACTIVE/REVOKED status and
|
|
734
|
+
inherited scope. Registration, describe, profile show and binding-list JSON
|
|
735
|
+
fields retain their existing shapes. `whoami` adds optional
|
|
736
|
+
`hosted_trust_domain` and `hosted_trust_domain_source: "profile:<name>"` fields
|
|
737
|
+
when that profile's saved tenant matches the inspected session. These fields
|
|
738
|
+
describe locally saved metadata, not current binding eligibility. Tenant
|
|
739
|
+
overrides never display another tenant's saved domain; session exit codes and
|
|
740
|
+
offline operation are unchanged. Profile show says "not saved in this profile"
|
|
741
|
+
when metadata is absent, without asserting that AAC has no allocation.
|
|
742
|
+
|
|
743
|
+
Existing tenant admins use `aac tenant assign-hosted-domain --profile dev`;
|
|
744
|
+
explicit eligible restoration uses `aac tenant reactivate-hosted-domain --profile dev`.
|
|
745
|
+
Neither command registers another tenant or asks for a DNS name.
|
|
746
|
+
See [the hosted-domain guide](../../docs/b239-hosted-trust-domains.md) for
|
|
747
|
+
custom-domain progression, recovery compatibility and lifecycle limits.
|
|
@@ -83,14 +83,14 @@ aac sso login --profile dev # thereafter: plain login
|
|
|
83
83
|
# Tenant ids are the server-allocated canonical tnt-<uuid> form
|
|
84
84
|
# (B154 PR 5) — captured at registration / shown by `aac profile show`.
|
|
85
85
|
aac tenant list # which tenant ids exist (no 409 probe)
|
|
86
|
-
aac tenant describe --
|
|
86
|
+
aac tenant describe --profile dev # assigned domain, workloads + key METADATA
|
|
87
87
|
aac tenant update --tenant-id tnt-<uuid> --display-name "ACME Manufacturing Inc"
|
|
88
88
|
|
|
89
89
|
# B121/B228 — business-domain control proof and bounded claim lifecycle.
|
|
90
90
|
# Registration can capture up to 16 pending rows with repeatable --tenant-domain.
|
|
91
91
|
# The issue/verify/release/revoke commands
|
|
92
92
|
# require the owning tenant's tenant-admin session and default --tenant-id from
|
|
93
|
-
# the profile;
|
|
93
|
+
# the profile; tenant describe also uses the selected profile by default.
|
|
94
94
|
aac tenant register --display-name "ACME" --contact ops@acme.example \
|
|
95
95
|
--tenant-domain acme.example
|
|
96
96
|
aac tenant issue-domain-challenge --domain acme.example
|
|
@@ -101,7 +101,7 @@ aac tenant verify-domain --domain acme.example
|
|
|
101
101
|
# never performs an implicit binding write.
|
|
102
102
|
aac tenant bind-trust-domain --trust-domain acme.example
|
|
103
103
|
aac tenant list-trust-domains --output table
|
|
104
|
-
aac tenant describe --
|
|
104
|
+
aac tenant describe --profile dev --output table # assigned binding status + TXT
|
|
105
105
|
aac tenant release-domain --domain acme.example --reason "planned transfer"
|
|
106
106
|
aac tenant revoke-domain --domain acme.example --reason "DNS control incident"
|
|
107
107
|
|
|
@@ -256,16 +256,17 @@ aac sso register-idp --shared --file shared-github.json \
|
|
|
256
256
|
# admin verb (tenant list/describe/update, self-serve register-idp)
|
|
257
257
|
# then rides the session automatically.
|
|
258
258
|
aac sso login --tenant-id tnt-550e8400-e29b-41d4-a716-446655440000
|
|
259
|
-
aac sso login --
|
|
259
|
+
aac sso login --idp github # developer tenant: GitHub or Google sign-in
|
|
260
|
+
aac sso login --issuer https://login.microsoftonline.com/<tid>/v2.0 # enterprise IdP, by issuer URL
|
|
260
261
|
aac sso login --flow pkce --no-browser # print the URL, don't launch
|
|
261
262
|
|
|
262
263
|
# Sessions are REFRESH-LESS by design (Eng Spec §XVII.2): on expiry
|
|
263
264
|
# any admin verb tells you to re-run `aac sso login` — there is no
|
|
264
265
|
# refresh token to steal, and no silent re-authentication.
|
|
265
266
|
|
|
266
|
-
# B155 — session
|
|
267
|
-
#
|
|
268
|
-
aac sso whoami --
|
|
267
|
+
# B155/B239 — local session/profile inspection; no server call or JWT parsing.
|
|
268
|
+
# whoami exits 0 = unexpired cache, 3 = expired/none (§14).
|
|
269
|
+
aac sso whoami --profile dev --output table # cached session + saved assigned domain
|
|
269
270
|
aac sso logout --tenant-id tnt-550e8400-e29b-41d4-a716-446655440000
|
|
270
271
|
```
|
|
271
272
|
|
|
@@ -479,8 +480,9 @@ coexistence, Eng Spec §XVII.9):
|
|
|
479
480
|
expiry fails fast locally with the re-login message instead of
|
|
480
481
|
dialing out; the server's own session 401s carry the same
|
|
481
482
|
remediation (the server stays authoritative). `aac sso logout`
|
|
482
|
-
removes the file; `aac sso whoami` reports its tenant + expiry
|
|
483
|
-
|
|
483
|
+
removes the file; `aac sso whoami` reports its tenant + expiry and, when
|
|
484
|
+
available, the matching profile's saved AAC-assigned domain. Both commands
|
|
485
|
+
operate locally; `whoami` does not verify current server-side binding status.
|
|
484
486
|
|
|
485
487
|
## Your tenant_id
|
|
486
488
|
|
|
@@ -531,3 +533,198 @@ ceremony-only, and existing binding history remains B181.
|
|
|
531
533
|
needed. Against a live stack: bring up the joined topology
|
|
532
534
|
(`./bin/run-wedge-a-control-plane-compose.sh --keep-up`) and point the
|
|
533
535
|
flags at localhost.
|
|
536
|
+
|
|
537
|
+
## Guided setup: `aac init` and `aac workspace`
|
|
538
|
+
|
|
539
|
+
`aac init` takes a developer from an installed CLI to a complete, runnable
|
|
540
|
+
local workload in one command. It signs you in, registers a developer tenant
|
|
541
|
+
(or reuses the one your profile is already bound to), takes the AAC-assigned
|
|
542
|
+
hosted trust domain, registers the sample workload, generates development
|
|
543
|
+
keys and certificates, registers the tenant-admin public key together with a
|
|
544
|
+
new tenant, and writes a complete sidecar configuration plus the publisher
|
|
545
|
+
environment and a Compose variable file.
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
# Developer tier: sign in with GitHub or Google. The command shows what it
|
|
549
|
+
# will create and asks before registering the tenant.
|
|
550
|
+
aac init --profile stage --admin-url https://api.stage.cascadeauth.dev \
|
|
551
|
+
--data-plane-url https://api.stage.cascadeauth.dev \
|
|
552
|
+
--trust-url https://trust.stage.cascadeauth.dev \
|
|
553
|
+
--display-name 'YOUR TEAM' --contact 'YOUR EMAIL' --idp github
|
|
554
|
+
|
|
555
|
+
# Scripted: every prompt has a flag; --create-tenant acknowledges creating a
|
|
556
|
+
# permanent tenant when stdin is not a terminal.
|
|
557
|
+
aac init --profile stage --admin-url ... --trust-url ... \
|
|
558
|
+
--display-name 'YOUR TEAM' --contact 'YOUR EMAIL' --idp github --create-tenant
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
Progress lines `[1/5]` to `[5/5]` name the five steps: tenant, sign-in, hosted trust
|
|
562
|
+
domain, workload, material and rendering. A rerun prints every step, marking the ones
|
|
563
|
+
already done. The sign-in you chose with `--idp` is remembered in the workspace, so a
|
|
564
|
+
rerun (or `aac sso login --idp github` by hand when a session expires) never asks you
|
|
565
|
+
to pick between GitHub and Google. Workspace commands take `--workspace <name>`; the
|
|
566
|
+
profile is recorded in the workspace, so `--profile` is optional there and only checked.
|
|
567
|
+
|
|
568
|
+
What it creates, and where:
|
|
569
|
+
|
|
570
|
+
* `~/.aac/workspaces/<name>/` — the **workspace** for one workload (default
|
|
571
|
+
name `starter`): `pki/` with what the sidecar container mounts — the
|
|
572
|
+
workload, terminal-attestation and localhost TLS key pairs, this
|
|
573
|
+
workspace's root-signing key and the outbound CA bundle; `pair/` with what
|
|
574
|
+
both containers mount at `/run/secrets` — the pairing secret and the public
|
|
575
|
+
development CA certificate; `ca/` with the development CA private key (kept
|
|
576
|
+
out of both mounts so no container ever sees the key that mints
|
|
577
|
+
identities); `sidecar-config.yaml`; `compose.env` (non-secret variables for
|
|
578
|
+
a Compose consumer); and an internal manifest that lets a rerun resume.
|
|
579
|
+
* `~/.aac/tenants/<tenant-id>/` — **tenant-level** material shared by every
|
|
580
|
+
workspace of that tenant: the tenant-admin signing key, the publisher's
|
|
581
|
+
input directories (`root-keys/`, `spiffe-bundle/` — public halves only) and
|
|
582
|
+
the rendered `publisher.env`.
|
|
583
|
+
* The tenant API key stays where the CLI always kept it,
|
|
584
|
+
`~/.aac/credentials/<tenant-id>`; the rendered configuration references it
|
|
585
|
+
by path.
|
|
586
|
+
|
|
587
|
+
### What each file is for, and what to back up
|
|
588
|
+
|
|
589
|
+
The table below is rendered from the CLI's own layout module and checked by a test, so it
|
|
590
|
+
cannot drift from the code. `<workspace>` is the workspace name (default `starter`) and
|
|
591
|
+
`<tenant-id>` the server-allocated tenant id.
|
|
592
|
+
|
|
593
|
+
<!-- inventory-table:start -->
|
|
594
|
+
| Material | Where | Used for | Lifetime | Back up? |
|
|
595
|
+
|---|---|---|---|---|
|
|
596
|
+
| tenant_api_key | `~/.aac/credentials/<tenant-id>` | CLI data-plane calls; the sidecar's workload projection | until retired or rotated; `aac tenant reissue-api-key` | **Yes.** save a protected copy in your secret manager; loss needs `aac tenant reissue-api-key` |
|
|
597
|
+
| tenant_admin_session | `~/.aac/credentials/<tenant-id>.session` | CLI admin calls | hours; `aac sso login` | No. sign in again |
|
|
598
|
+
| tenant_admin_signing_key | `~/.aac/tenants/<tenant-id>/tenant-admin.pem`, `~/.aac/tenants/<tenant-id>/tenant-admin.pub.pem` | the publisher signs trust-material uploads; the public half is registered with AAC | until rotated; `aac tenant rotate-admin-key` | **Recommended.** recommended for developer tenants (loss needs `aac tenant rotate-admin-key`); production custody belongs in an HSM/KMS, not a password manager |
|
|
599
|
+
| root_signing_key | `~/.aac/workspaces/<workspace>/pki/root.pem`, `~/.aac/workspaces/<workspace>/pki/root.pub.pem`, `~/.aac/tenants/<tenant-id>/root-keys/<workspace>-root-v1.pub.pem` | the sidecar mints authority chains; the public half is published under the key id | until you retire its key id (root key ids are fixed per workspace name) | No. never restore: a replacement workspace gets a new name and therefore a new key id, published alongside the old one until the old one is retired |
|
|
600
|
+
| development_ca | `~/.aac/workspaces/<workspace>/ca/dev-ca.key`, `~/.aac/workspaces/<workspace>/pki/dev-ca.crt`, `~/.aac/workspaces/<workspace>/pair/dev-ca.crt`, `~/.aac/tenants/<tenant-id>/spiffe-bundle/<workspace>-dev-ca.ca.pem` | signs the workload, terminal and TLS certificates; peers trust it via the published bundle | 7 days; `aac workspace renew --ca` | No. development only; reissue |
|
|
601
|
+
| workload_svid | `~/.aac/workspaces/<workspace>/pki/workload.key`, `~/.aac/workspaces/<workspace>/pki/workload.crt` | the sidecar's SPIFFE identity: proves on every live request that this workload holds the key behind its certificate | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
602
|
+
| terminal_attestation | `~/.aac/workspaces/<workspace>/pki/terminal.key`, `~/.aac/workspaces/<workspace>/pki/terminal.crt` | signs the receipt (terminal attestation) the sidecar issues when this workload completes a delegated request; auditors verify it offline against your published CA; kept separate from the workload key so neither can forge the other's role | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
603
|
+
| localhost_tls | `~/.aac/workspaces/<workspace>/pki/server.key`, `~/.aac/workspaces/<workspace>/pki/server.crt` | the sidecar's HTTPS listener | 1 day; `aac workspace renew` | No. development only; reissue |
|
|
604
|
+
| outbound_ca_bundle | `~/.aac/workspaces/<workspace>/pki/outbound-ca.pem` | the sidecar verifies TLS to AAC and to itself | rebuilt by renew; `aac workspace renew` | No. derived |
|
|
605
|
+
| pairing_secret | `~/.aac/workspaces/<workspace>/pair/pairing.secret` | the sidecar and its agent authenticate each other (same bytes in both) | until regenerated | No. regenerable; both processes must read the same file |
|
|
606
|
+
| workspace_manifest | `~/.aac/workspaces/<workspace>/manifest.json` | the workspace's identities and progress; every `workspace` verb reads it first | for the life of the workspace | **Recommended.** cannot be recreated by any command; without it start a new workspace under a new name (see the machine-loss procedure) |
|
|
607
|
+
| published_public_inputs | `~/.aac/tenants/<tenant-id>/root-keys`, `~/.aac/tenants/<tenant-id>/spiffe-bundle` | the publisher's input directories: every root public key and CA certificate this tenant has published, across all workspaces | for the life of the tenant | **Recommended.** back up with the tenant directory: a replacement workspace must publish its new root key alongside a still-ACTIVE previous one (the control plane refuses a root-key set that drops every ACTIVE key at once) |
|
|
608
|
+
| rendered_files | `~/.aac/workspaces/<workspace>/sidecar-config.yaml`, `~/.aac/workspaces/<workspace>/compose.env`, `~/.aac/tenants/<tenant-id>/publisher.env` | non-secret configuration derived from the manifest | re-rendered on demand; `aac workspace render --force` | No. derived; `aac workspace render --force` recreates them |
|
|
609
|
+
<!-- inventory-table:end -->
|
|
610
|
+
|
|
611
|
+
#### If you lose this machine
|
|
612
|
+
|
|
613
|
+
Back up two things while the machine is healthy: the tenant API key at
|
|
614
|
+
`~/.aac/credentials/<tenant-id>`, and the whole tenant directory
|
|
615
|
+
`~/.aac/tenants/<tenant-id>/` (the admin signing key plus the `root-keys/` and
|
|
616
|
+
`spiffe-bundle/` public inputs the publisher has already published). The workspace
|
|
617
|
+
manifest is worth keeping too, but a workspace can always be replaced. Then, on the new
|
|
618
|
+
machine:
|
|
619
|
+
|
|
620
|
+
1. Install the CLI and `aac profile create <name> --admin-url … --data-plane-url …`.
|
|
621
|
+
Sign in with `aac sso login --idp github --tenant-id <tenant-id> --profile <name>`
|
|
622
|
+
(or `--issuer <url>` for an enterprise connection): the remaining
|
|
623
|
+
steps register a workload and read the tenant's admin-key state, which need a
|
|
624
|
+
tenant-admin session whatever way the tenant was registered (a ceremony bootstrap
|
|
625
|
+
token only covers registration and hosted-domain assignment).
|
|
626
|
+
2. Restore the tenant API key to `~/.aac/credentials/<tenant-id>` (mode `0600`), or issue a
|
|
627
|
+
new one with `aac tenant reissue-api-key` if it was not backed up. Restore
|
|
628
|
+
`~/.aac/tenants/<tenant-id>/` from the backup (directories `0700`, files `0600`).
|
|
629
|
+
3. Run `aac init --profile <name> --workspace <new-name>` with a **new** workspace name.
|
|
630
|
+
Root key ids are fixed per workspace name and the control plane never accepts new key
|
|
631
|
+
material under an old id, so the replacement workspace publishes a new id
|
|
632
|
+
(`<new-name>-root-v1`) and a new development CA anchor.
|
|
633
|
+
4. Start the publisher from the restored tenant directory. Its root-key set now holds the
|
|
634
|
+
old and the new public keys, which is what the control plane requires: a set that
|
|
635
|
+
drops every currently ACTIVE key at once is refused. Retire the old key later by
|
|
636
|
+
removing its public file once nothing signs with it.
|
|
637
|
+
|
|
638
|
+
Reusing the old workspace name on the new machine is refused on purpose: the restored
|
|
639
|
+
tenant directory still holds that name's published root key, and `init` never generates
|
|
640
|
+
different key material under an existing key id. The development certificates and the
|
|
641
|
+
pairing secret are regenerated by step 3; they are never restored.
|
|
642
|
+
|
|
643
|
+
Every private file is created once at mode `0600` under `0700` directories
|
|
644
|
+
and is never overwritten; before generating anything, `init` checks every
|
|
645
|
+
destination and refuses with the full list if one already exists. Rerunning
|
|
646
|
+
`aac init` resumes an interrupted setup (outcome `resumed`), reports a
|
|
647
|
+
complete workspace (outcome `complete`, exit 0), or names the exact conflict
|
|
648
|
+
(exit 3). Every post-registration step is pinned to the workspace's tenant,
|
|
649
|
+
so a profile that has since been pointed at another tenant is refused rather
|
|
650
|
+
than mixed in. A rerun on a complete workspace validates it offline (binding,
|
|
651
|
+
files, permissions, certificate validity, CA fitness) and exits 3 with the
|
|
652
|
+
next command if it is no longer usable. Missing flags for a new tenant are
|
|
653
|
+
usage errors (exit 2).
|
|
654
|
+
|
|
655
|
+
**`aac init` never installs or replaces a tenant-admin authority for an
|
|
656
|
+
existing tenant.** For a new tenant it generates the admin key first and
|
|
657
|
+
registers the public half together with the tenant, which the control plane
|
|
658
|
+
creates in one transaction, so no competing authority can ever be retired by
|
|
659
|
+
setup. For an existing tenant it only checks: the key on this machine must
|
|
660
|
+
already be the tenant's ACTIVE admin key. If the tenant's ACTIVE key is not on
|
|
661
|
+
this machine, `init` stops and tells you to restore that key to
|
|
662
|
+
`~/.aac/tenants/<tenant-id>/tenant-admin.pem` (or pass
|
|
663
|
+
`--tenant-admin-key-file`); if the tenant has no admin key at all, it tells
|
|
664
|
+
you to install one deliberately with `aac tenant rotate-admin-key`. Replacing
|
|
665
|
+
an authority is always that deliberate command, never a side effect of setup. Managed directories under `~/.aac/workspaces/` and
|
|
666
|
+
`~/.aac/tenants/` must be real directories at mode `0700`; a symlink or a
|
|
667
|
+
looser mode is refused before anything is written.
|
|
668
|
+
A second workspace for the same tenant (`--workspace other`) reuses the
|
|
669
|
+
tenant-admin key and gets its own root key id. Each key has an
|
|
670
|
+
`--<role>-key-file` flag to use existing material instead of generating it.
|
|
671
|
+
|
|
672
|
+
**Everything generated is development material.** The CA lives seven days and
|
|
673
|
+
the leaf certificates one day; nothing here qualifies for production
|
|
674
|
+
regardless of the tenant's hosted domain. Moving to production means
|
|
675
|
+
`aac tenant rotate-admin-key` with a key under production custody, a new root
|
|
676
|
+
key id published by your publisher, and certificates from your approved
|
|
677
|
+
issuer.
|
|
678
|
+
|
|
679
|
+
Inspect and maintain a workspace with the `workspace` noun:
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
aac workspace status --workspace starter # what exists, expiry, permissions, next command
|
|
683
|
+
aac workspace status --workspace starter --remote # also: is the public trust material visible?
|
|
684
|
+
aac workspace renew --workspace starter # fresh leaf keys + certificates; old ones archived
|
|
685
|
+
aac workspace render --workspace starter --layout container --force # container path layout
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
`status` is offline by default and exits 3 when material is missing, expired
|
|
689
|
+
or unsafely permissioned. `renew` reissues the one-day certificates with fresh
|
|
690
|
+
keys and reissues the development CA only when it is expired or within a day
|
|
691
|
+
of expiry (or with `--ca`); a new CA is published under the next anchor id and
|
|
692
|
+
needs the publisher restarted. `render` never touches keys and refuses to
|
|
693
|
+
overwrite rendered files unless `--force` is given. Command, flag and path
|
|
694
|
+
names are provisional until the public starter example has consumed them.
|
|
695
|
+
|
|
696
|
+
## Assigned tenant domains (B239)
|
|
697
|
+
|
|
698
|
+
Registration automatically saves the server-assigned `hosted_trust_domain` in
|
|
699
|
+
the selected profile. The CLI displays the full name, explains its purpose in
|
|
700
|
+
SPIFFE identities/certificates/trust configuration, and prints the command for
|
|
701
|
+
finding it again. No manual copy is required. With JSON output, this guidance
|
|
702
|
+
goes to stderr and stdout remains one JSON document; table output includes it
|
|
703
|
+
inline. Completed-registration recovery provides the same saved-name guidance
|
|
704
|
+
without changing credential-reissue requirements.
|
|
705
|
+
|
|
706
|
+
```sh
|
|
707
|
+
aac profile show dev --output table # saved locally, offline
|
|
708
|
+
aac tenant describe --profile dev --output table # assigned name + current binding status
|
|
709
|
+
aac tenant list-trust-domains --profile dev --output table # current ACTIVE bindings
|
|
710
|
+
aac tenant list-trust-domains --profile dev --all --output table # includes revoked history
|
|
711
|
+
aac sso whoami --profile dev --output table # cached session + matching saved name
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
`tenant describe` accepts an optional `--tenant-id`; the usual flag → environment
|
|
715
|
+
→ selected profile precedence applies. Its response comes from AAC. Binding
|
|
716
|
+
table output labels AAC-assigned/custom origin, ACTIVE/REVOKED status and
|
|
717
|
+
inherited scope. Registration, describe, profile show and binding-list JSON
|
|
718
|
+
fields retain their existing shapes. `whoami` adds optional
|
|
719
|
+
`hosted_trust_domain` and `hosted_trust_domain_source: "profile:<name>"` fields
|
|
720
|
+
when that profile's saved tenant matches the inspected session. These fields
|
|
721
|
+
describe locally saved metadata, not current binding eligibility. Tenant
|
|
722
|
+
overrides never display another tenant's saved domain; session exit codes and
|
|
723
|
+
offline operation are unchanged. Profile show says "not saved in this profile"
|
|
724
|
+
when metadata is absent, without asserting that AAC has no allocation.
|
|
725
|
+
|
|
726
|
+
Existing tenant admins use `aac tenant assign-hosted-domain --profile dev`;
|
|
727
|
+
explicit eligible restoration uses `aac tenant reactivate-hosted-domain --profile dev`.
|
|
728
|
+
Neither command registers another tenant or asks for a DNS name.
|
|
729
|
+
See [the hosted-domain guide](../../docs/b239-hosted-trust-domains.md) for
|
|
730
|
+
custom-domain progression, recovery compatibility and lifecycle limits.
|