From 6231ff5c88a040a033365f48483952f9daaaccae Mon Sep 17 00:00:00 2001 From: Remylus Losius Date: Tue, 28 Jul 2026 06:19:36 -0400 Subject: [PATCH] build(deps): adopt Kensa v0.8.0 Unblocked by the remediation outcome vocabulary (#761). Bumping before that landed would have written audit rules to hardened RHEL hosts while reporting "No host change was committed" and refusing rollback, on 2 of 6 reachable dev-fleet hosts. Payload, all corpus-side (the frozen api/ change is additive and already handled): - STIG Ubuntu coverage ~6% -> 84.0% (22.04) and 85.6% (24.04) - CIS Ubuntu 41.8% (22.04) and 38.9% (24.04), campaign in progress - corpus 748 -> 769 unique rule ids - config_value gains opt-in dropin_dir: the pwquality family read only the base file and false-FAILED a host hardened via pwquality.conf.d/, which is where CIS/STIG remediation writes - exact audit-rule matching: -F path=/usr/bin/su no longer substring-matches a loaded /usr/bin/sudo, which was a false-PASS on the su control - audit_rule_set stages reboot-deferred on immutable-audit hosts instead of failing, which is the change #761 exists to handle - golang.org/x/text v0.38.0 -> v0.39.0 (GO-2026-5970) The AC-11 guard was checked against the real module rather than assumed: every TransactionStatus v0.8.0 can produce is mapped by remediation.OutcomeOf, so nothing falls through to the fail-closed branch. EXPECT SCORE MOVEMENT ON FIRST SCAN. The verdict corrections are strictly more correct but they do change shipped RHEL cis/stig results: the drop-in reads, maxrepeat/maxsequence now failing an explicit =0 (previously a false-PASS), and framework-divergent thresholds defaulting to the stricter requirement (e.g. pwquality difok, CIS >= 2 vs STIG >= 8, ships 8). A CIS-only operator loosens via --var. Hosts will flip state and drift alerts will fire; that is the corpus becoming honest, not a regression. Doc counts follow the BACKLOG DOC-2 rule that a bare number is the bug: every count now names its scope and its Kensa version ("769 rules in the corpus, Kensa v0.8.0"), and the guides state explicitly that a single host is measured against the subset applying to its OS, not all 769. That ambiguity is what put three different rule counts into circulation (508, 539, 748). kensa-rules needs no manual bump: build-kensa-rules.sh derives its version from the module via stage-kensa-rules.sh, verified resolving to 0.8.0 / 769 rules. Spec: system-kensa-executor 2.7.0 -> 2.8.0 (AC-10 version pin). Verified: gofmt, go vet, go build, full go test ./internal/..., 116 specs 116 passing. --- README.md | 2 +- docs/guides/COMPLIANCE_CONTROLS.md | 4 ++-- docs/guides/INSTALLATION.md | 2 +- docs/guides/LINUX_DISTRIBUTION_SUPPORT.md | 14 +++++++------- docs/guides/SCANNING_AND_COMPLIANCE.md | 2 +- go.mod | 2 +- go.sum | 4 ++-- internal/kensa/types.go | 2 +- specs/system/kensa-executor.spec.yaml | 6 +++--- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bf54568a..2445e005 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ OpenWatch is the compliance operating system for teams managing Linux infrastruc > React 19 + TanStack frontend (`frontend/`), PostgreSQL-only. The current > version is `0.6.0`, on the general-availability line that opened with `0.2.0`. -![OpenWatch Host Management: a fleet of RHEL and Ubuntu hosts with per-host compliance scores against 748 Kensa rules](docs/images/host-management.png) +![OpenWatch Host Management: a fleet of RHEL and Ubuntu hosts with per-host compliance scores against the 769-rule Kensa corpus](docs/images/host-management.png) ## The Problem with Point-in-Time Compliance diff --git a/docs/guides/COMPLIANCE_CONTROLS.md b/docs/guides/COMPLIANCE_CONTROLS.md index 32d000cc..f2da3339 100644 --- a/docs/guides/COMPLIANCE_CONTROLS.md +++ b/docs/guides/COMPLIANCE_CONTROLS.md @@ -41,7 +41,7 @@ This document maps OpenWatch's security controls to industry frameworks, providi | Control | Title | OpenWatch Implementation | Evidence | |---------|-------|-------------------------|----------| -| CM-2 | Baseline Configuration | Kensa YAML rules define expected configurations | Kensa rules (748 rules, Kensa v0.7.6); scan results | +| CM-2 | Baseline Configuration | Kensa YAML rules define expected configurations | Kensa rules (769 rules in the corpus, Kensa v0.8.0); scan results | | CM-3 | Configuration Change Control | Database migration tracking, version control | Migration version reported by `openwatch migrate` | | CM-6 | Configuration Settings | Configuration validation at startup | Output of `openwatch check-config` | | CM-8 | System Component Inventory | Host management with discovery and metadata | Host list and collected system info from the API | @@ -89,7 +89,7 @@ This document maps OpenWatch's security controls to industry frameworks, providi | 1.1 | Enterprise Asset Inventory | Host management with system info collection | | 2.1 | Software Inventory | Server intelligence (package collection) | | 3.3 | Data Encryption | AES-256-GCM at rest, TLS 1.2+ in transit | -| 4.1 | Secure Configuration | Kensa compliance scanning (748 rules, Kensa v0.7.6) | +| 4.1 | Secure Configuration | Kensa compliance scanning (769 rules in the corpus, Kensa v0.8.0) | | 4.2 | Baseline Network Configuration | Network discovery and topology mapping | | 5.2 | Unique Passwords | Argon2id hashing, 8-char minimum (15 for admin), breached-password screening | | 5.4 | MFA | TOTP-based MFA (no backup/recovery codes) | diff --git a/docs/guides/INSTALLATION.md b/docs/guides/INSTALLATION.md index e0242a73..518cfb92 100644 --- a/docs/guides/INSTALLATION.md +++ b/docs/guides/INSTALLATION.md @@ -110,7 +110,7 @@ Install **both** files in one transaction. `openwatch` declares a hard dependency on `kensa-rules`—the rule corpus the scan engine loads from `/usr/share/kensa/rules`. Installing `openwatch` alone fails the dependency check (by design: a corpus-less node cannot scan). `kensa-rules` is `noarch` -and versioned on the Kensa content line (for example `0.7.6`), independent of the +and versioned on the Kensa content line (for example `0.8.0`), independent of the platform version, so the rules can update without re-releasing OpenWatch. Use the filenames you downloaded (`aarch64` for the arm64 openwatch RPM; the diff --git a/docs/guides/LINUX_DISTRIBUTION_SUPPORT.md b/docs/guides/LINUX_DISTRIBUTION_SUPPORT.md index 06af1e62..d5d4b5e1 100644 --- a/docs/guides/LINUX_DISTRIBUTION_SUPPORT.md +++ b/docs/guides/LINUX_DISTRIBUTION_SUPPORT.md @@ -1,7 +1,7 @@ # Linux distribution support matrix > **Scope.** OpenWatch targets Linux, but **not every Linux distribution is -> supported to the same degree**. As of Kensa v0.7.6, compliance *scanning* is +> supported to the same degree**. As of Kensa v0.8.0, compliance *scanning* is > supported on the **RHEL family and on Ubuntu**, because those are the > platforms the bundled Kensa rule corpus covers. This page states, with > evidence, which distributions work for (1) running the OpenWatch server and @@ -9,9 +9,9 @@ **Last updated:** 2026-07-14 · **Applies to:** OpenWatch v0.5.0 (Go single-binary) -**Last verified:** 2026-07-13 against Kensa rule corpus **v0.7.6** (748 rules). +**Last verified:** 2026-07-28 against Kensa rule corpus **v0.8.0** (769 rules in the corpus). Per-OS counts below are read from each rule's `platforms:` declarations in the -v0.7.6 corpus, not from a live scan. +v0.8.0 corpus, not from a live scan. --- @@ -19,7 +19,7 @@ v0.7.6 corpus, not from a live scan. - **Compliance scanning works on RHEL 8 / 9 / 10** and its binary-compatible rebuilds (Rocky, AlmaLinux, CentOS Stream, Oracle Linux), **and on Ubuntu - 22.04 / 24.04 LTS.** Kensa v0.7.6 ships 748 rules across these platforms. + 22.04 / 24.04 LTS.** Kensa v0.8.0 ships 769 rules across these platforms. A single host is measured against the subset that applies to its operating system, not all 769. - **Each rule declares the platforms it applies to**, so a host is only evaluated against rules that match its detected OS. Ubuntu hosts are scanned against the Ubuntu rule set; RHEL hosts against the RHEL rule set. @@ -65,7 +65,7 @@ sensitivity: ### Per-OS rule applicability -Rule applicability is read from the currently bundled Kensa v0.7.6 corpus +Rule applicability is read from the currently bundled Kensa v0.8.0 corpus (each rule's `platforms:` block). These are the counts of rules that apply per OS family: @@ -75,7 +75,7 @@ OS family: | Ubuntu (22.04, 24.04) | 117 | A rule can apply to several platforms, so these counts overlap; the Kensa -v0.7.6 corpus total is 748 distinct rules. +v0.8.0 corpus total is 769 distinct rules. ### Support matrix @@ -183,7 +183,7 @@ a compliance score. partial-success semantics. - Kensa filters its corpus by the host's detected platform at scan time. - Rule corpus applicability (read from the corpus platform declarations): the - currently bundled corpus is Kensa v0.7.6, **748 rules** spanning RHEL + currently bundled corpus is Kensa v0.8.0, **769 rules** spanning RHEL 8/9/10 and Ubuntu 22.04/24.04—668 applicable to the RHEL family, 117 to Ubuntu (rules can apply to more than one platform, so these overlap). - Framework mappings: CIS RHEL 9 v2.0.0, STIG RHEL 9 V2R7, plus CIS/STIG Ubuntu. diff --git a/docs/guides/SCANNING_AND_COMPLIANCE.md b/docs/guides/SCANNING_AND_COMPLIANCE.md index 7dd81f1e..85c170be 100644 --- a/docs/guides/SCANNING_AND_COMPLIANCE.md +++ b/docs/guides/SCANNING_AND_COMPLIANCE.md @@ -27,7 +27,7 @@ Kensa retrieves SSH credentials from OpenWatch's encrypted store SSH connection to target host | v -748 rules evaluated (Kensa v0.7.6; check commands, config values, file permissions) +769 rules in the corpus (Kensa v0.8.0; check commands, config values, file permissions). The number evaluated on a given host is lower: rules resolve per operating system | v Each rule returns: pass/fail, severity, detail, evidence diff --git a/go.mod b/go.mod index ab2c1e38..f422eb7a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.26.5 require ( github.com/BurntSushi/toml v1.6.0 - github.com/Hanalyx/kensa v0.7.6 + github.com/Hanalyx/kensa v0.8.0 github.com/gliderlabs/ssh v0.3.8 github.com/go-chi/chi/v5 v5.3.0 github.com/go-pdf/fpdf v0.9.0 diff --git a/go.sum b/go.sum index c1f2d505..17d6837e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Hanalyx/kensa v0.7.6 h1:SDSvP2Blg92tCEY2l6iLoHsOjSnTwVx4DR6qYue8OWM= -github.com/Hanalyx/kensa v0.7.6/go.mod h1:DPuksmA1bOQXyQT+3OwLrZs0yJw9nlOIhG1CEsvX2oI= +github.com/Hanalyx/kensa v0.8.0 h1:H0KOY7F9vDA54fgz9jm3gd7/X/cW8tuXqJ9L7KT3ZtA= +github.com/Hanalyx/kensa v0.8.0/go.mod h1:RuBtdJNBlr5cCT6O8LjQqwx9gRyR+owlAiwIQrB4TRk= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= diff --git a/internal/kensa/types.go b/internal/kensa/types.go index 9a61defa..ab77ae4a 100644 --- a/internal/kensa/types.go +++ b/internal/kensa/types.go @@ -10,7 +10,7 @@ import ( // KensaModuleVersion is the version pin recorded in the spec's context // block. AC-10 source-inspects to verify this matches the corresponding // entry in app/go.mod. -const KensaModuleVersion = "v0.7.6" +const KensaModuleVersion = "v0.8.0" // Sentinel errors returned by Executor.Run. Tests use errors.Is for // classification; the audit emission path maps each to a typed diff --git a/specs/system/kensa-executor.spec.yaml b/specs/system/kensa-executor.spec.yaml index 59f6f6c2..7ad57df0 100644 --- a/specs/system/kensa-executor.spec.yaml +++ b/specs/system/kensa-executor.spec.yaml @@ -1,7 +1,7 @@ spec: id: system-kensa-executor title: Kensa executor wrapper - version: "2.7.0" + version: "2.8.0" status: approved tier: 1 @@ -10,7 +10,7 @@ spec: feature: Kensa scan execution bridge description: > The executor invokes Kensa (Go module github.com/Hanalyx/kensa - pinned to v0.7.6) to run a scan against a single host using the + pinned to v0.8.0) to run a scan against a single host using the FULL rule corpus applicable to the host's detected OS capabilities. The Kensa API (`Kensa.Scan(ctx, host, rules, opts...)` per kensa-go/api/kensa.go:228) takes a `[]*api.Rule` @@ -131,7 +131,7 @@ spec: type: technical enforcement: error - id: C-13 - description: The production scanFunc MUST compose the scan-only Kensa via api.New with pkg/kensa.NewScanner (kensa v0.7.6 — stateless, concurrency-safe shared) and this package's TransportFactory; no engine, store, or signer is constructed for the scan path. The worker subcommand binds it via WithScanFunc(NewProductionScanFunc(...)). unwiredScanFunc may remain ONLY as the test fallback NewExecutor defaults to before binding, annotated as such + description: The production scanFunc MUST compose the scan-only Kensa via api.New with pkg/kensa.NewScanner (kensa v0.8.0 — stateless, concurrency-safe shared) and this package's TransportFactory; no engine, store, or signer is constructed for the scan path. The worker subcommand binds it via WithScanFunc(NewProductionScanFunc(...)). unwiredScanFunc may remain ONLY as the test fallback NewExecutor defaults to before binding, annotated as such type: technical enforcement: error - id: C-14