diff --git a/README.md b/README.md index 38ce2fa..349ac35 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ This is how to run kensa today, pre-1.0. Requires Go 1.26+ and make. git clone git@github.com:Hanalyx/kensa.git cd kensa make build # builds all five binaries into bin/ -./bin/kensa --version # → kensa 0.3.2 (kensa) +./bin/kensa --version # → kensa 0.4.1 (kensa) ``` The five binaries: @@ -110,7 +110,7 @@ ldd bin/kensa # "not a dynamic executable" ## Status -`v0.3.2`. The 0.x line is the development phase. +`v0.4.1`. The 0.x line is the development phase. The `api/` Go package is held to a stricter contract — frozen under v1 semver for OpenWatch's consumption. Behavior on the rest of the surface @@ -130,7 +130,15 @@ surface on `pkg/kensa` — `LoadRules` / `BuiltInVars` / `RuleVariables` — so api consumers load the corpus and inject operator-configured variables without copying files or importing `internal/` (v0.3.1), and public scanner construction with a caller-supplied `TransportFactory` — -`NewScanner` / `DefaultWithTransportFactory` (v0.3.2). +`NewScanner` / `DefaultWithTransportFactory` (v0.3.2). Most recently: +structured per-check evidence (`RuleOutcome.Evidence []CheckEvidence` — +the exact command, output, and expected value behind each verdict), +exported as a Kensa-native document (`-o evidence:`) and an OSCAL 1.0.6 +Assessment Results document (`-o oscal:`), conformance-gated against the +vendored NIST schema and live-validated on the test fleet (v0.4.0), and +public OSCAL export on `pkg/kensa` — `ExportOSCALScan` / +`WriteOSCALScan` / `ExportOSCAL` / `WriteOSCAL` — so api consumers turn a +scan into OSCAL without the CLI (v0.4.1). All 29 handlers carry passing spec-driven tests. Open ship items before v1.0: RHEL 8 `$kernelopts` capture in the boot diff --git a/docs/guide/01-install.md b/docs/guide/01-install.md index 7e26c91..45d9f05 100644 --- a/docs/guide/01-install.md +++ b/docs/guide/01-install.md @@ -3,7 +3,7 @@ ## What you'll have when you're done `kensa` and `kensa-rules` installed from signed packages, the verification -keys imported, and `kensa --version` printing `kensa 0.3.2`. From there, +keys imported, and `kensa --version` printing `kensa 0.4.1`. From there, [02-quickstart](02-quickstart.md) is the next step. Target hosts (the machines you'll scan) need no kensa installation — @@ -55,27 +55,27 @@ sudo apt install kensa kensa-rules ### Air-gapped On a connected host, download the bundled tarball from -[the v0.3.2 release](https://github.com/Hanalyx/kensa/releases/tag/v0.3.2): +[the v0.4.1 release](https://github.com/Hanalyx/kensa/releases/tag/v0.4.1): ``` -kensa_0.3.2_linux__with-rules.tar.gz # binaries + rules + LICENSE + KEYS -kensa_0.3.2_checksums.sha256 # sha256 of every artifact -kensa_0.3.2_checksums.sha256.sig # cosign signature of the checksums +kensa_0.4.1_linux__with-rules.tar.gz # binaries + rules + LICENSE + KEYS +kensa_0.4.1_checksums.sha256 # sha256 of every artifact +kensa_0.4.1_checksums.sha256.sig # cosign signature of the checksums ``` Verify before transferring: ```bash -sha256sum -c kensa_0.3.2_checksums.sha256 # one OK line per artifact you downloaded +sha256sum -c kensa_0.4.1_checksums.sha256 # one OK line per artifact you downloaded cosign verify-blob --key cosign.pub \ - --signature kensa_0.3.2_checksums.sha256.sig \ - kensa_0.3.2_checksums.sha256 + --signature kensa_0.4.1_checksums.sha256.sig \ + kensa_0.4.1_checksums.sha256 ``` Then copy the tarball to the air-gapped host and: ```bash -tar xzf kensa_0.3.2_linux_amd64_with-rules.tar.gz +tar xzf kensa_0.4.1_linux_amd64_with-rules.tar.gz sudo install -m 0755 kensa kensa-validate kensa-keygen /usr/local/bin/ sudo install -m 0755 kensa-systemd-helper /usr/libexec/ sudo mkdir -p /usr/share/kensa && sudo cp -r rules /usr/share/kensa/ @@ -150,7 +150,7 @@ tarball). The rules corpus lives at `rules/` in the repo; copy it to kensa --version ``` -You're done when this prints `kensa 0.3.2 (kensa)`. If it doesn't, +You're done when this prints `kensa 0.4.1 (kensa)`. If it doesn't, the binary isn't on your `$PATH` — go back to **Step 2**. ## Next diff --git a/docs/guide/04-scan-and-remediate.md b/docs/guide/04-scan-and-remediate.md index 3ecb2d4..b58d069 100644 --- a/docs/guide/04-scan-and-remediate.md +++ b/docs/guide/04-scan-and-remediate.md @@ -79,8 +79,10 @@ still go to stderr). The exit code and every `-o FORMAT[:PATH]` output are produced from the canonical result struct, not reconstructed from the rendered rows. Read -the result document (or `-o json`/`oscal`/etc.) for the record of what -changed; the rows are the same data rendered for a human as it arrives. +the result document (`-o json`, `-o evidence` for the Kensa-native +evidence document, `-o oscal` for OSCAL 1.0.6, etc.) for the record of +what changed; the rows are the same data rendered for a human as it +arrives. ### Inventory (multi-host) diff --git a/docs/guide/07-integration.md b/docs/guide/07-integration.md index 6309f53..27f3f5d 100644 --- a/docs/guide/07-integration.md +++ b/docs/guide/07-integration.md @@ -15,7 +15,14 @@ One pointer that IS current: programs importing the `api` Go package from `ScanResult.Outcomes` (since v0.3.0) — one `RuleOutcome` per rule with a `ComplianceStatus` of `pass` / `fail` / `skipped` / `error`, the rule's severity, a human-readable detail, and the rule's normalised -compliance-framework references (`FrameworkRefs`). The check-only +compliance-framework references (`FrameworkRefs`). Since v0.4.0 each +`RuleOutcome` also carries `Evidence []CheckEvidence` — one entry per +command the check ran, with the exact `Command`, captured +`Stdout`/`Stderr`, `ExitCode`, and `Expected` value: the reproducible +proof behind a verdict, so a consumer can show or re-verify the finding +without re-running the scan. `ScanResult` additionally exposes the +`Capabilities` and `Platform` the scan evaluated against, so the host +context a verdict was computed under is self-describing. The check-only `ScanResult.Transactions` entries remain for backward compatibility, but their `committed`/`rolled_back` statuses are a legacy encoding of compliant/non-compliant — prefer `Outcomes` for an unambiguous verdict. @@ -56,6 +63,26 @@ supply their own `api.TransportFactory`: - Full service (remediate, history, transaction log): `kensa.DefaultWithTransportFactory(ctx, storePath, yours, engineOpts...)`. +Exporting a scan as a standards artifact is public surface too (package +`github.com/Hanalyx/kensa/pkg/kensa`, since v0.4.1). A scan's verdicts +and their embedded check evidence convert to an OSCAL 1.0.6 Assessment +Results document with no shelling out to the CLI: + +- `kensa.ExportOSCALScan(result, hostname)` → `[]byte` of OSCAL 1.0.6 AR + JSON (`kensa.WriteOSCALScan(w, result, hostname)` streams to an + `io.Writer`). One finding + observation per rule, the `CheckEvidence` + embedded as relevant-evidence, framework refs as control-ids. The scan + document is **unsigned** by design — it is derived from the read-only + `ScanResult`. +- `kensa.ExportOSCAL(envelope)` / `kensa.WriteOSCAL(w, envelope)` — the + remediation counterpart, rendering a signed `api.EvidenceEnvelope` + (the audit-truth-of-record a transaction produces) as OSCAL. This path + is anchored on the envelope's Ed25519 signature. + +The byte production lives in `internal/` and is conformance-gated against +the vendored NIST OSCAL 1.0.6 schema; these are the importable entry +points to it. + End-to-end, the whole consumer chain is public: `kensa.LoadRules(…, operatorVars)` → construct (either form above) → -`Scan` → `ScanResult.Outcomes`. +`Scan` → `ScanResult.Outcomes` → `kensa.ExportOSCALScan(…)`.