aac-cli 0.2.6__tar.gz → 0.2.7__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.2.6 → aac_cli-0.2.7}/PKG-INFO +21 -3
- aac_cli-0.2.6/aac_cli.egg-info/PKG-INFO → aac_cli-0.2.7/README.md +14 -23
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/__init__.py +1 -1
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/agent_cli.py +46 -5
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/cli.py +23 -7
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/config.py +13 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/profiles.py +6 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/reference.py +11 -1
- aac_cli-0.2.6/README.md → aac_cli-0.2.7/aac_cli.egg-info/PKG-INFO +41 -1
- {aac_cli-0.2.6 → aac_cli-0.2.7}/pyproject.toml +9 -2
- {aac_cli-0.2.6 → aac_cli-0.2.7}/LICENSE +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/MANIFEST.in +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/NOTICE +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/THIRD_PARTY_NOTICES.md +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/__main__.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/__init__.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/cli.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/data/action-taken-v1.json +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/data/predicates-v1.json +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/data/renderer-source.json +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/from_sidecar.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/inputs.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/model.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/narrative.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/schemas.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/temporal.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/timeline_source.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/_aeg/visualizer.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/admin_key_pem.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/aeg_cli.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/aeg_list.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/agent_config.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/agent_health.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/agent_layout.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/agent_record.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/api_key_rotation_state.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/chain_list.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/config_render.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/dev_material.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/idp_recovery.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/init_cli.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/material_cases.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/registration_state.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/secure_files.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/sso_login.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/supplied_material.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli/trace_query.py +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli.egg-info/SOURCES.txt +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli.egg-info/dependency_links.txt +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli.egg-info/requires.txt +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/aac_cli.egg-info/top_level.txt +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/launchers/aac +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/launchers/aeg +0 -0
- {aac_cli-0.2.6 → aac_cli-0.2.7}/setup.cfg +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aac-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
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
|
|
7
|
-
Project-URL: Documentation, https://cascadeauth.github.io/aac-starter-guide/
|
|
7
|
+
Project-URL: Documentation, https://cascadeauth.github.io/aac-starter-guide/cli/
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
8
13
|
Requires-Python: >=3.11
|
|
9
14
|
Description-Content-Type: text/markdown
|
|
10
15
|
License-File: LICENSE
|
|
@@ -32,6 +37,10 @@ incoming ones against public trust material the tenant publishes.
|
|
|
32
37
|
New to AAC? [What AAC is for](https://cascadeauth.github.io/aac-starter-guide/#what-aac-is-for)
|
|
33
38
|
explains what delegated authority between agents buys you, and what it does not.
|
|
34
39
|
|
|
40
|
+
The [CLI user guide and complete command reference](https://cascadeauth.github.io/aac-starter-guide/cli/)
|
|
41
|
+
cover developer and enterprise onboarding, everyday administration and recovery.
|
|
42
|
+
Select documentation matching `aac --version`.
|
|
43
|
+
|
|
35
44
|
The `aac` command is how a tenant's operator does everything that is not
|
|
36
45
|
done by the sidecar itself: register the tenant, sign in, manage keys,
|
|
37
46
|
workloads and domains, and prepare a runnable local workload. Everything
|
|
@@ -59,7 +68,7 @@ pip install aac-cli
|
|
|
59
68
|
aac --version
|
|
60
69
|
```
|
|
61
70
|
|
|
62
|
-
Python 3.11
|
|
71
|
+
Python 3.11 to 3.14 is supported. Release checks test all four versions.
|
|
63
72
|
|
|
64
73
|
> **Mind the name.** `pip install aac` installs an unrelated project that
|
|
65
74
|
> happens to share the acronym. The AAC package is **`aac-cli`**; the
|
|
@@ -796,6 +805,15 @@ AAC.
|
|
|
796
805
|
|
|
797
806
|
## Output and exit codes
|
|
798
807
|
|
|
808
|
+
For scripts, `aac profile show NAME --field tenant-id` prints the effective
|
|
809
|
+
tenant ID (including `AAC_TENANT_ID` overrides), and
|
|
810
|
+
`aac tenant assign-hosted-domain --field trust-domain` prints the validated
|
|
811
|
+
server-returned domain. Existing agents expose read-only identities through
|
|
812
|
+
`aac agent status --agent NAME --field tenant-id`, `--field hosted-trust-domain`
|
|
813
|
+
or `--field workload-spiffe-id`. A successful scalar is one unquoted line;
|
|
814
|
+
an unavailable value or unhealthy agent fails with empty stdout. `--field`
|
|
815
|
+
cannot be combined with explicit `--output`, or with agent `--remote`.
|
|
816
|
+
|
|
799
817
|
Every command that reports a result prints one JSON document to standard
|
|
800
818
|
output by default, with progress notes and diagnostics on standard error,
|
|
801
819
|
so the JSON stays parseable in scripts; `--output table` prints a readable
|
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: aac-cli
|
|
3
|
-
Version: 0.2.6
|
|
4
|
-
Summary: The aac platform CLI — headless operator interface to the AAC control plane (tenant registration, chain audit).
|
|
5
|
-
Author: Agent Authority Cloud Project
|
|
6
|
-
License-Expression: Apache-2.0
|
|
7
|
-
Project-URL: Documentation, https://cascadeauth.github.io/aac-starter-guide/aeg.html
|
|
8
|
-
Requires-Python: >=3.11
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
License-File: NOTICE
|
|
12
|
-
License-File: THIRD_PARTY_NOTICES.md
|
|
13
|
-
Requires-Dist: httpx>=0.28
|
|
14
|
-
Requires-Dist: cryptography>=42.0
|
|
15
|
-
Requires-Dist: PyYAML>=6.0
|
|
16
|
-
Requires-Dist: pyvis<0.4,>=0.3.2
|
|
17
|
-
Requires-Dist: jsonschema>=4.18
|
|
18
|
-
Provides-Extra: test
|
|
19
|
-
Requires-Dist: pytest>=8.0; extra == "test"
|
|
20
|
-
Requires-Dist: pytest-httpx>=0.30; extra == "test"
|
|
21
|
-
Dynamic: license-file
|
|
22
|
-
|
|
23
1
|
# aac-cli — the `aac` command
|
|
24
2
|
|
|
25
3
|
`aac` is the command-line tool for tenants of Agent Authority Cloud (AAC).
|
|
@@ -32,6 +10,10 @@ incoming ones against public trust material the tenant publishes.
|
|
|
32
10
|
New to AAC? [What AAC is for](https://cascadeauth.github.io/aac-starter-guide/#what-aac-is-for)
|
|
33
11
|
explains what delegated authority between agents buys you, and what it does not.
|
|
34
12
|
|
|
13
|
+
The [CLI user guide and complete command reference](https://cascadeauth.github.io/aac-starter-guide/cli/)
|
|
14
|
+
cover developer and enterprise onboarding, everyday administration and recovery.
|
|
15
|
+
Select documentation matching `aac --version`.
|
|
16
|
+
|
|
35
17
|
The `aac` command is how a tenant's operator does everything that is not
|
|
36
18
|
done by the sidecar itself: register the tenant, sign in, manage keys,
|
|
37
19
|
workloads and domains, and prepare a runnable local workload. Everything
|
|
@@ -59,7 +41,7 @@ pip install aac-cli
|
|
|
59
41
|
aac --version
|
|
60
42
|
```
|
|
61
43
|
|
|
62
|
-
Python 3.11
|
|
44
|
+
Python 3.11 to 3.14 is supported. Release checks test all four versions.
|
|
63
45
|
|
|
64
46
|
> **Mind the name.** `pip install aac` installs an unrelated project that
|
|
65
47
|
> happens to share the acronym. The AAC package is **`aac-cli`**; the
|
|
@@ -796,6 +778,15 @@ AAC.
|
|
|
796
778
|
|
|
797
779
|
## Output and exit codes
|
|
798
780
|
|
|
781
|
+
For scripts, `aac profile show NAME --field tenant-id` prints the effective
|
|
782
|
+
tenant ID (including `AAC_TENANT_ID` overrides), and
|
|
783
|
+
`aac tenant assign-hosted-domain --field trust-domain` prints the validated
|
|
784
|
+
server-returned domain. Existing agents expose read-only identities through
|
|
785
|
+
`aac agent status --agent NAME --field tenant-id`, `--field hosted-trust-domain`
|
|
786
|
+
or `--field workload-spiffe-id`. A successful scalar is one unquoted line;
|
|
787
|
+
an unavailable value or unhealthy agent fails with empty stdout. `--field`
|
|
788
|
+
cannot be combined with explicit `--output`, or with agent `--remote`.
|
|
789
|
+
|
|
799
790
|
Every command that reports a result prints one JSON document to standard
|
|
800
791
|
output by default, with progress notes and diagnostics on standard error,
|
|
801
792
|
so the JSON stays parseable in scripts; `--output table` prints a readable
|
|
@@ -47,7 +47,15 @@ from aac_cli.agent_record import (
|
|
|
47
47
|
read_record,
|
|
48
48
|
write_record,
|
|
49
49
|
)
|
|
50
|
-
from aac_cli.config import
|
|
50
|
+
from aac_cli.config import (
|
|
51
|
+
CANONICAL_TENANT_ID_PATTERN,
|
|
52
|
+
JSON_OUTPUT_DEFAULT,
|
|
53
|
+
CliConfigError,
|
|
54
|
+
CliUsageError,
|
|
55
|
+
cli_home,
|
|
56
|
+
credentials_path,
|
|
57
|
+
validate_hosted_trust_domain,
|
|
58
|
+
)
|
|
51
59
|
from aac_cli.config_render import configuration_summary, outbound_ca_bundle
|
|
52
60
|
from aac_cli.init_cli import (
|
|
53
61
|
SHARED_MATERIAL_FLAGS,
|
|
@@ -88,6 +96,18 @@ def _load(args: argparse.Namespace) -> tuple[AgentPaths, TenantPaths | None, Age
|
|
|
88
96
|
f"[{wanted}]. The `aac agent` commands find the profile through the agent, so omit "
|
|
89
97
|
f"--profile, or name an agent of profile [{wanted}] with --agent."
|
|
90
98
|
)
|
|
99
|
+
if getattr(args, "field", None):
|
|
100
|
+
# Structured status retains its existing diagnostic behavior. Scalar
|
|
101
|
+
# consumers require a complete canonical identity before any stdout.
|
|
102
|
+
if not isinstance(record.tenant_id, str) or not CANONICAL_TENANT_ID_PATTERN.fullmatch(
|
|
103
|
+
record.tenant_id
|
|
104
|
+
):
|
|
105
|
+
raise CliConfigError(f"agent {agent.name!r} has no valid tenant identity")
|
|
106
|
+
if not isinstance(record.hosted_trust_domain, str):
|
|
107
|
+
raise CliConfigError(f"agent {agent.name!r} has no valid hosted trust domain")
|
|
108
|
+
domain = validate_hosted_trust_domain(record.tenant_id, record.hosted_trust_domain)
|
|
109
|
+
if record.workload_spiffe_id != f"spiffe://{domain}/{record.workload_path}":
|
|
110
|
+
raise CliConfigError(f"agent {agent.name!r} has an invalid workload identity")
|
|
91
111
|
tenant = tenant_paths(record.tenant_id) if record.tenant_id else None
|
|
92
112
|
return agent, tenant, record
|
|
93
113
|
|
|
@@ -203,8 +223,19 @@ def _inventory_report(
|
|
|
203
223
|
|
|
204
224
|
|
|
205
225
|
def cmd_agent_status(args: argparse.Namespace) -> int:
|
|
226
|
+
if getattr(args, "field", None) and args.remote:
|
|
227
|
+
raise CliUsageError("--field reports local identity only; omit --remote")
|
|
206
228
|
agent, tenant, record = _load(args)
|
|
207
229
|
health = assess(agent, tenant, record)
|
|
230
|
+
if getattr(args, "field", None):
|
|
231
|
+
value = getattr(record, args.field.replace("-", "_"))
|
|
232
|
+
if not health.healthy:
|
|
233
|
+
raise CliConfigError(
|
|
234
|
+
f"agent {agent.name!r} cannot supply {args.field}: "
|
|
235
|
+
f"{next_step(agent, tenant, record, health) or 'value unavailable'}"
|
|
236
|
+
)
|
|
237
|
+
print(value)
|
|
238
|
+
return 0
|
|
208
239
|
certificates = {
|
|
209
240
|
label: {
|
|
210
241
|
"not_after": report.not_after,
|
|
@@ -603,14 +634,24 @@ def cmd_agent_list(args: argparse.Namespace) -> int:
|
|
|
603
634
|
# --- parser ----------------------------------------------------------------------------
|
|
604
635
|
|
|
605
636
|
|
|
606
|
-
def _agent_flags(parser: argparse.ArgumentParser) -> None:
|
|
637
|
+
def _agent_flags(parser: argparse.ArgumentParser, *, scalar: bool = False) -> None:
|
|
607
638
|
parser.add_argument(
|
|
608
639
|
"--agent",
|
|
609
640
|
required=True,
|
|
610
641
|
help="Target agent name under ~/.aac/agents/.",
|
|
611
642
|
)
|
|
612
|
-
parser.
|
|
613
|
-
|
|
643
|
+
output = parser.add_mutually_exclusive_group() if scalar else parser
|
|
644
|
+
if scalar:
|
|
645
|
+
output.add_argument(
|
|
646
|
+
"--field",
|
|
647
|
+
choices=("tenant-id", "hosted-trust-domain", "workload-spiffe-id"),
|
|
648
|
+
help="Print one local identity value; fail if unavailable or the agent needs attention. Cannot combine with --output or --remote.",
|
|
649
|
+
)
|
|
650
|
+
output.add_argument(
|
|
651
|
+
"--output",
|
|
652
|
+
choices=("json", "table"),
|
|
653
|
+
default=JSON_OUTPUT_DEFAULT if scalar else "json",
|
|
654
|
+
help="Output mode (JSON by default).",
|
|
614
655
|
)
|
|
615
656
|
parser.add_argument(
|
|
616
657
|
"--profile",
|
|
@@ -639,7 +680,7 @@ def add_agent_parser(nouns: argparse._SubParsersAction) -> None:
|
|
|
639
680
|
"status",
|
|
640
681
|
help="Report what exists, certificate expiry, permission problems and the next command.",
|
|
641
682
|
)
|
|
642
|
-
_agent_flags(status)
|
|
683
|
+
_agent_flags(status, scalar=True)
|
|
643
684
|
status.add_argument(
|
|
644
685
|
"--remote",
|
|
645
686
|
action="store_true",
|
|
@@ -97,6 +97,7 @@ from aac_cli.api_key_rotation_state import (
|
|
|
97
97
|
)
|
|
98
98
|
from aac_cli.config import (
|
|
99
99
|
CANONICAL_TENANT_ID_PATTERN,
|
|
100
|
+
JSON_OUTPUT_DEFAULT,
|
|
100
101
|
CliConfigError,
|
|
101
102
|
CliUsageError,
|
|
102
103
|
ResolvedConfig,
|
|
@@ -284,7 +285,7 @@ def _session_headers(config: ResolvedConfig) -> dict[str, str]:
|
|
|
284
285
|
return {"Authorization": f"Bearer {credential.access_token}"}
|
|
285
286
|
|
|
286
287
|
|
|
287
|
-
def _add_common_flags(parser: argparse.ArgumentParser) -> None:
|
|
288
|
+
def _add_common_flags(parser: argparse.ArgumentParser, *, fields: tuple[str, ...] = ()) -> None:
|
|
288
289
|
parser.add_argument(
|
|
289
290
|
"--profile",
|
|
290
291
|
default=None,
|
|
@@ -302,10 +303,17 @@ def _add_common_flags(parser: argparse.ArgumentParser) -> None:
|
|
|
302
303
|
default=None,
|
|
303
304
|
help="Data-plane-surface base URL (overrides profile).",
|
|
304
305
|
)
|
|
305
|
-
parser.
|
|
306
|
+
output = parser.add_mutually_exclusive_group() if fields else parser
|
|
307
|
+
if fields:
|
|
308
|
+
output.add_argument(
|
|
309
|
+
"--field",
|
|
310
|
+
choices=fields,
|
|
311
|
+
help="Print only the selected server-returned value; cannot combine with --output.",
|
|
312
|
+
)
|
|
313
|
+
output.add_argument(
|
|
306
314
|
"--output",
|
|
307
315
|
choices=("json", "table"),
|
|
308
|
-
default="json",
|
|
316
|
+
default=JSON_OUTPUT_DEFAULT if fields else "json",
|
|
309
317
|
help="Output mode: json (the default) or table.",
|
|
310
318
|
)
|
|
311
319
|
|
|
@@ -2350,7 +2358,9 @@ def _cmd_tenant_hosted_domain(args: argparse.Namespace) -> int:
|
|
|
2350
2358
|
file=sys.stderr,
|
|
2351
2359
|
)
|
|
2352
2360
|
return 3
|
|
2353
|
-
if args
|
|
2361
|
+
if getattr(args, "field", None):
|
|
2362
|
+
print(domain)
|
|
2363
|
+
elif args.output == "table":
|
|
2354
2364
|
print(f"hosted_domain : {domain}")
|
|
2355
2365
|
_print_binding_row(payload["binding"])
|
|
2356
2366
|
else:
|
|
@@ -4382,10 +4392,16 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
4382
4392
|
profile_show.add_argument(
|
|
4383
4393
|
"name", nargs="?", default=None, help="Profile name (default: selected)."
|
|
4384
4394
|
)
|
|
4385
|
-
profile_show.
|
|
4395
|
+
profile_output = profile_show.add_mutually_exclusive_group()
|
|
4396
|
+
profile_output.add_argument(
|
|
4397
|
+
"--field",
|
|
4398
|
+
choices=("tenant-id",),
|
|
4399
|
+
help="Print the effective tenant ID (AAC_TENANT_ID overrides stored binding); fail if unavailable. Cannot combine with --output.",
|
|
4400
|
+
)
|
|
4401
|
+
profile_output.add_argument(
|
|
4386
4402
|
"--output",
|
|
4387
4403
|
choices=("json", "table"),
|
|
4388
|
-
default=
|
|
4404
|
+
default=JSON_OUTPUT_DEFAULT,
|
|
4389
4405
|
help="Output mode: json (the default) or table.",
|
|
4390
4406
|
)
|
|
4391
4407
|
profile_show.set_defaults(handler=cmd_profile_show)
|
|
@@ -5047,7 +5063,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
5047
5063
|
" aac tenant bind-trust-domain --profile main --trust-domain example.com\n"
|
|
5048
5064
|
),
|
|
5049
5065
|
)
|
|
5050
|
-
_add_common_flags(hosted)
|
|
5066
|
+
_add_common_flags(hosted, fields=() if reactivation else ("trust-domain",))
|
|
5051
5067
|
hosted.add_argument(
|
|
5052
5068
|
"--tenant-id", default=None, help="Tenant (defaults to the selected profile)."
|
|
5053
5069
|
)
|
|
@@ -64,6 +64,19 @@ from contextlib import contextmanager
|
|
|
64
64
|
from dataclasses import dataclass
|
|
65
65
|
from pathlib import Path
|
|
66
66
|
|
|
67
|
+
|
|
68
|
+
class _OutputDefault(str):
|
|
69
|
+
"""Keep explicit JSON distinguishable from argparse's implicit default.
|
|
70
|
+
|
|
71
|
+
Python 3.11 tracks mutually exclusive actions using identity against the
|
|
72
|
+
default. A plain interned ``"json"`` can therefore bypass the group when
|
|
73
|
+
passed explicitly. A distinct string subtype preserves the public default
|
|
74
|
+
and its generated reference while making normal argv strings explicit.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
JSON_OUTPUT_DEFAULT = _OutputDefault("json")
|
|
79
|
+
|
|
67
80
|
__all__ = [
|
|
68
81
|
"CANONICAL_TENANT_ID_PATTERN",
|
|
69
82
|
"CliConfigError",
|
|
@@ -205,6 +205,12 @@ def cmd_profile_show(args: argparse.Namespace) -> int:
|
|
|
205
205
|
key for key in stored if key not in DEFAULT_SETTINGS and key != "hosted_trust_domain"
|
|
206
206
|
)
|
|
207
207
|
effective = resolve_settings(profile=name)
|
|
208
|
+
if getattr(args, "field", None):
|
|
209
|
+
tenant_id = effective["tenant_id"].value
|
|
210
|
+
if not tenant_id:
|
|
211
|
+
raise CliConfigError(f"profile {name!r} has no effective tenant ID")
|
|
212
|
+
print(tenant_id)
|
|
213
|
+
return 0
|
|
208
214
|
payload = {
|
|
209
215
|
"name": name,
|
|
210
216
|
"selected": name == selected,
|
|
@@ -320,7 +320,7 @@ def _arguments_section(parser: argparse.ArgumentParser) -> list[str]:
|
|
|
320
320
|
def _output_section(parser: argparse.ArgumentParser) -> list[str]:
|
|
321
321
|
if not any("--output" in action.option_strings for action in parser._actions):
|
|
322
322
|
return []
|
|
323
|
-
|
|
323
|
+
lines = [
|
|
324
324
|
"## Output",
|
|
325
325
|
"",
|
|
326
326
|
"`--output json` (the default) prints one JSON document to standard output; "
|
|
@@ -328,6 +328,16 @@ def _output_section(parser: argparse.ArgumentParser) -> list[str]:
|
|
|
328
328
|
"diagnostics go to standard error, so the JSON stays parseable.",
|
|
329
329
|
"",
|
|
330
330
|
]
|
|
331
|
+
if any("--field" in action.option_strings for action in parser._actions):
|
|
332
|
+
lines.extend(
|
|
333
|
+
[
|
|
334
|
+
"`--field` prints one unquoted value followed by a newline instead. "
|
|
335
|
+
"It cannot be combined with an explicit `--output`. A missing or invalid "
|
|
336
|
+
"value fails without scalar output; diagnostics go to standard error.",
|
|
337
|
+
"",
|
|
338
|
+
]
|
|
339
|
+
)
|
|
340
|
+
return lines
|
|
331
341
|
|
|
332
342
|
|
|
333
343
|
def _exit_codes_section() -> list[str]:
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aac-cli
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: The aac platform CLI — headless operator interface to the AAC control plane (tenant registration, chain audit).
|
|
5
|
+
Author: Agent Authority Cloud Project
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Documentation, https://cascadeauth.github.io/aac-starter-guide/cli/
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
License-File: NOTICE
|
|
17
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
18
|
+
Requires-Dist: httpx>=0.28
|
|
19
|
+
Requires-Dist: cryptography>=42.0
|
|
20
|
+
Requires-Dist: PyYAML>=6.0
|
|
21
|
+
Requires-Dist: pyvis<0.4,>=0.3.2
|
|
22
|
+
Requires-Dist: jsonschema>=4.18
|
|
23
|
+
Provides-Extra: test
|
|
24
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
25
|
+
Requires-Dist: pytest-httpx>=0.30; extra == "test"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
1
28
|
# aac-cli — the `aac` command
|
|
2
29
|
|
|
3
30
|
`aac` is the command-line tool for tenants of Agent Authority Cloud (AAC).
|
|
@@ -10,6 +37,10 @@ incoming ones against public trust material the tenant publishes.
|
|
|
10
37
|
New to AAC? [What AAC is for](https://cascadeauth.github.io/aac-starter-guide/#what-aac-is-for)
|
|
11
38
|
explains what delegated authority between agents buys you, and what it does not.
|
|
12
39
|
|
|
40
|
+
The [CLI user guide and complete command reference](https://cascadeauth.github.io/aac-starter-guide/cli/)
|
|
41
|
+
cover developer and enterprise onboarding, everyday administration and recovery.
|
|
42
|
+
Select documentation matching `aac --version`.
|
|
43
|
+
|
|
13
44
|
The `aac` command is how a tenant's operator does everything that is not
|
|
14
45
|
done by the sidecar itself: register the tenant, sign in, manage keys,
|
|
15
46
|
workloads and domains, and prepare a runnable local workload. Everything
|
|
@@ -37,7 +68,7 @@ pip install aac-cli
|
|
|
37
68
|
aac --version
|
|
38
69
|
```
|
|
39
70
|
|
|
40
|
-
Python 3.11
|
|
71
|
+
Python 3.11 to 3.14 is supported. Release checks test all four versions.
|
|
41
72
|
|
|
42
73
|
> **Mind the name.** `pip install aac` installs an unrelated project that
|
|
43
74
|
> happens to share the acronym. The AAC package is **`aac-cli`**; the
|
|
@@ -774,6 +805,15 @@ AAC.
|
|
|
774
805
|
|
|
775
806
|
## Output and exit codes
|
|
776
807
|
|
|
808
|
+
For scripts, `aac profile show NAME --field tenant-id` prints the effective
|
|
809
|
+
tenant ID (including `AAC_TENANT_ID` overrides), and
|
|
810
|
+
`aac tenant assign-hosted-domain --field trust-domain` prints the validated
|
|
811
|
+
server-returned domain. Existing agents expose read-only identities through
|
|
812
|
+
`aac agent status --agent NAME --field tenant-id`, `--field hosted-trust-domain`
|
|
813
|
+
or `--field workload-spiffe-id`. A successful scalar is one unquoted line;
|
|
814
|
+
an unavailable value or unhealthy agent fails with empty stdout. `--field`
|
|
815
|
+
cannot be combined with explicit `--output`, or with agent `--remote`.
|
|
816
|
+
|
|
777
817
|
Every command that reports a result prints one JSON document to standard
|
|
778
818
|
output by default, with progress notes and diagnostics on standard error,
|
|
779
819
|
so the JSON stays parseable in scripts; `--output table` prints a readable
|
|
@@ -32,7 +32,7 @@ build-backend = "setuptools.build_meta"
|
|
|
32
32
|
|
|
33
33
|
[project]
|
|
34
34
|
name = "aac-cli"
|
|
35
|
-
version = "0.2.
|
|
35
|
+
version = "0.2.7"
|
|
36
36
|
description = "The aac platform CLI — headless operator interface to the AAC control plane (tenant registration, chain audit)."
|
|
37
37
|
readme = "README.md"
|
|
38
38
|
requires-python = ">=3.11"
|
|
@@ -42,6 +42,13 @@ license = "Apache-2.0"
|
|
|
42
42
|
# aac_invoke_auth).
|
|
43
43
|
license-files = ["LICENSE", "NOTICE", "THIRD_PARTY_NOTICES.md"]
|
|
44
44
|
authors = [{ name = "Agent Authority Cloud Project" }]
|
|
45
|
+
classifiers = [
|
|
46
|
+
"Programming Language :: Python :: 3",
|
|
47
|
+
"Programming Language :: Python :: 3.11",
|
|
48
|
+
"Programming Language :: Python :: 3.12",
|
|
49
|
+
"Programming Language :: Python :: 3.13",
|
|
50
|
+
"Programming Language :: Python :: 3.14",
|
|
51
|
+
]
|
|
45
52
|
|
|
46
53
|
dependencies = [
|
|
47
54
|
# HTTP client (same floor as the workspace).
|
|
@@ -64,7 +71,7 @@ dependencies = [
|
|
|
64
71
|
]
|
|
65
72
|
|
|
66
73
|
[project.urls]
|
|
67
|
-
Documentation = "https://cascadeauth.github.io/aac-starter-guide/
|
|
74
|
+
Documentation = "https://cascadeauth.github.io/aac-starter-guide/cli/"
|
|
68
75
|
|
|
69
76
|
[project.optional-dependencies]
|
|
70
77
|
test = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|