Add JSON output format (--output json) for list, status, and show - #888
Add JSON output format (--output json) for list, status, and show#888Muhammaduazir69 wants to merge 1 commit into
Conversation
Introduces a global --output/-o flag (table|json, default table) so the read-only commands can emit machine-readable JSON for automation, CI, and SIEM ingestion. - New cmd/stratus/cmd/output.go defines stable JSON view models, decoupled from stratus.AttackTechnique (whose Detonate/Revert closures and embedded Terraform code are not serializable). - Global persistent flag validated via PersistentPreRunE. - main() now exits non-zero when a command fails, so the CLI is usable in scripts (previously the Execute() error was ignored). - First unit tests under cmd/ covering the JSON mapping and flag validation. - Documents the new flag on the list/status/show command pages. Closes DataDog#241 Signed-off-by: Muhammad Uzair <muhammaduzairr69@gmail.com>
|
Hi @Muhammaduazir69, thanks for the contribution! Since we're at it and we noticed you made the |
|
Thanks @christophetd! Agreed — logs and structured output are different things, and turning the log stream itself into JSON (one object per log line) would just be noise; someone consuming Here's how I'd make the global
[
{ "id": "aws.defense-evasion.cloudtrail-stop", "state": "DETONATED", "success": true, "error": null },
{ "id": "aws.persistence.iam-backdoor-user", "state": "WARM", "success": false, "error": "..." }
]That gives automation what it actually needs (per-technique result + resulting state, alongside the existing non-zero exit code) while keeping stdout valid JSON — the same split as Two notes from the current code:
On scope — happy either way:
I lean toward (1) to keep it reviewable, but glad to do (2) here if you'd prefer. And if you'd rather not expose |
What this does
Adds a global
--output/-oflag (table|json, defaulttable) so the read-only commands can emit machine-readable JSON:stratus list -o json— the full technique catalog (id, name, platform, isSlow, isIdempotent, mitreAttackTactics)stratus status -o json— per-technique state (id, name, state)stratus show <id> -o json— full technique detail (description, detection, MITRE tactics, framework mappings)Closes #241.
Why
The only way to consume Stratus' technique inventory or state today is by scraping the rendered tables. JSON output makes Stratus scriptable for automation, CI pipelines, and SIEM/detection-engineering ingestion (the use case raised in #241).
Example
Implementation notes
v2/cmd/stratus/cmd/output.godefines stable JSON view models decoupled fromstratus.AttackTechnique— that struct carriesDetonate/Revertclosures and embedded Terraform[]byte, which must not (and cannot) be serialized. This keeps the JSON contract stable even if the internal struct changes.PersistentPreRunE, so every command inherits it and unknown formats are rejected early.-o json, the existing colored tables render exactly as before.main()now exits non-zero when a command (or flag validation) fails. Previously the error fromRootCmd.Execute()was discarded, so even invalid input exited0— which would make the new-ovalidation (and any other error) undetectable in scripts.Tests
cmd/(output_test.go): JSON mapping for list/show, framework-mapping serialization, empty-slice vsnullstability, no HTML-escaping, and--outputvalidation.go test ./...,go vet,gofmt, andstaticcheck ./cmd/...all pass locally.Scope
Scoped to the read-only commands (
list,status,show) that have structured output.detonate/warmup/revert/cleanupstream progress logs and are intentionally left as-is; structured result output for those can be a follow-up.