From 68ae58d886621540208b98378ed517b3525244e0 Mon Sep 17 00:00:00 2001 From: "Cheng-Chen, Chen" Date: Thu, 22 Oct 2026 12:19:54 +0800 Subject: [PATCH] Bind Linux supervisor to the scoped-audit Host API producer --- .github/workflows/codeql-verification.yml | 8 ++--- .github/workflows/security-release-gate.yml | 32 +++++++++---------- .github/workflows/validate.yml | 16 +++++----- COMPATIBILITY.md | 14 ++++++++ README.md | 8 ++--- scripts/version | 2 +- service/hostapilauncher/process_linux_test.go | 2 +- service/hostapilauncher/supervisor.go | 2 +- service/hostapilauncher/supervisor_test.go | 4 +-- 9 files changed, 51 insertions(+), 37 deletions(-) diff --git a/.github/workflows/codeql-verification.yml b/.github/workflows/codeql-verification.yml index a020918e..3cfa89ed 100644 --- a/.github/workflows/codeql-verification.yml +++ b/.github/workflows/codeql-verification.yml @@ -37,11 +37,11 @@ jobs: run: | set -euo pipefail test -z "$(git status --porcelain)" - git merge-base --is-ancestor c8663d12dd253ef13258750dca056d4b1219fc10 HEAD - grep -Fq 'VERSION_OVERRIDE: v0.13.30' .github/workflows/validate.yml + git merge-base --is-ancestor 73e3a7c5f438dbda42c4078885a66e6f156aa731 HEAD + grep -Fq 'VERSION_OVERRIDE: v0.13.31' .github/workflows/validate.yml grep -Fq 'SHA256SUMS' scripts/package grep -Fq 'bash scripts/verify-package "$linux_asset"' .github/workflows/validate.yml - grep -Fq 'bash scripts/verify-package dist/artifacts/node-agent-0.13.30.tar.gz' .github/workflows/security-release-gate.yml + grep -Fq 'bash scripts/verify-package dist/artifacts/node-agent-0.13.31.tar.gz' .github/workflows/security-release-gate.yml - name: Install the release Go toolchain uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 @@ -68,7 +68,7 @@ jobs: export GOFLAGS=-mod=vendor mkdir -p "$GITHUB_WORKSPACE/bin" CGO_ENABLED=0 go build -trimpath -tags 'netgo osusergo' \ - -ldflags='-w -s -X main.VERSION=v0.13.30' \ + -ldflags='-w -s -X main.VERSION=v0.13.31' \ -o "$GITHUB_WORKSPACE/bin/node-agent" ./ - name: Analyze without publishing temporary alerts diff --git a/.github/workflows/security-release-gate.yml b/.github/workflows/security-release-gate.yml index 5baa23bc..0eba9a70 100644 --- a/.github/workflows/security-release-gate.yml +++ b/.github/workflows/security-release-gate.yml @@ -19,9 +19,9 @@ jobs: timeout-minutes: 120 env: DAPPER_IMAGE: pasturestack/node-agent-dapper:${{ github.sha }} - RUNTIME_IMAGE: pasturestack/node-agent:v0.13.30 + RUNTIME_IMAGE: pasturestack/node-agent:v0.13.31 TRIVY_IMAGE: aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969 - VERSION_OVERRIDE: v0.13.30 + VERSION_OVERRIDE: v0.13.31 steps: - name: Check out candidate uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -34,7 +34,7 @@ jobs: run: | set -euo pipefail test -z "$(git status --porcelain)" - git merge-base --is-ancestor c8663d12dd253ef13258750dca056d4b1219fc10 HEAD + git merge-base --is-ancestor 73e3a7c5f438dbda42c4078885a66e6f156aa731 HEAD mkdir -p evidence git rev-parse HEAD > evidence/source-revision.txt sha256sum Dockerfile.dapper package/Dockerfile tests/requirements.lock \ @@ -50,25 +50,25 @@ jobs: set -euo pipefail CROSS=1 VERSION_OVERRIDE="$VERSION_OVERRIDE" make DAPPER_IMAGE="$DAPPER_IMAGE" ci make DAPPER_IMAGE="$DAPPER_IMAGE" IMAGE_NAME=pasturestack/node-agent \ - TAG=v0.13.30 VERSION_OVERRIDE="$VERSION_OVERRIDE" package-image - test -s dist/artifacts/node-agent-0.13.30.tar.gz - test -s dist/artifacts/node-agent-0.13.30-windows-amd64.zip + TAG=v0.13.31 VERSION_OVERRIDE="$VERSION_OVERRIDE" package-image + test -s dist/artifacts/node-agent-0.13.31.tar.gz + test -s dist/artifacts/node-agent-0.13.31-windows-amd64.zip test "$(cat dist/image)" = "$RUNTIME_IMAGE" - gzip -t dist/artifacts/node-agent-0.13.30.tar.gz - bash scripts/verify-package dist/artifacts/node-agent-0.13.30.tar.gz - unzip -t dist/artifacts/node-agent-0.13.30-windows-amd64.zip + gzip -t dist/artifacts/node-agent-0.13.31.tar.gz + bash scripts/verify-package dist/artifacts/node-agent-0.13.31.tar.gz + unzip -t dist/artifacts/node-agent-0.13.31-windows-amd64.zip ( cd dist/artifacts - sha256sum node-agent-0.13.30.tar.gz node-agent-0.13.30-windows-amd64.zip > SHA256SUMS + sha256sum node-agent-0.13.31.tar.gz node-agent-0.13.31-windows-amd64.zip > SHA256SUMS sha256sum -c SHA256SUMS ) - sha256sum dist/artifacts/node-agent-0.13.30.tar.gz \ - dist/artifacts/node-agent-0.13.30-windows-amd64.zip \ + sha256sum dist/artifacts/node-agent-0.13.31.tar.gz \ + dist/artifacts/node-agent-0.13.31-windows-amd64.zip \ bin/node-agent bin/windows/amd64/node-agent.exe > evidence/product-artifacts.sha256 docker image inspect "$RUNTIME_IMAGE" > evidence/runtime-image-inspect.json docker run --rm --entrypoint /usr/bin/node-agent "$RUNTIME_IMAGE" --version \ > evidence/runtime-version.txt - grep -Fxq 'node-agent version v0.13.30' evidence/runtime-version.txt + grep -Fxq 'node-agent version v0.13.31' evidence/runtime-version.txt - name: Verify reproducible Linux binary shell: bash @@ -246,10 +246,10 @@ jobs: - name: Retain exact scanned release packages uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: node-agent-scanned-0.13.30 + name: node-agent-scanned-0.13.31 path: | - dist/artifacts/node-agent-0.13.30.tar.gz - dist/artifacts/node-agent-0.13.30-windows-amd64.zip + dist/artifacts/node-agent-0.13.31.tar.gz + dist/artifacts/node-agent-0.13.31-windows-amd64.zip dist/artifacts/SHA256SUMS if-no-files-found: error retention-days: 30 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 7cac977c..06fd276f 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -52,7 +52,7 @@ jobs: id: package env: CROSS: "1" - VERSION_OVERRIDE: v0.13.30 + VERSION_OVERRIDE: v0.13.31 VALIDATION_SCOPE: ${{ inputs.validation_scope || 'full' }} run: | set -euo pipefail @@ -75,8 +75,8 @@ jobs: exit 1 ;; esac - linux_asset="dist/artifacts/node-agent-0.13.30.tar.gz" - windows_asset="dist/artifacts/node-agent-0.13.30-windows-amd64.zip" + linux_asset="dist/artifacts/node-agent-0.13.31.tar.gz" + windows_asset="dist/artifacts/node-agent-0.13.31-windows-amd64.zip" test -s "$linux_asset" test -s "$windows_asset" gzip -t "$linux_asset" @@ -92,8 +92,8 @@ jobs: ( cd dist/artifacts sha256sum \ - node-agent-0.13.30.tar.gz \ - node-agent-0.13.30-windows-amd64.zip >SHA256SUMS + node-agent-0.13.31.tar.gz \ + node-agent-0.13.31-windows-amd64.zip >SHA256SUMS sha256sum -c SHA256SUMS ) printf 'NODE_AGENT_VALIDATION_OK source=%s version=%s scope=%s artifacts=linux,windows\n' \ @@ -102,10 +102,10 @@ jobs: - name: Retain reviewed release candidate uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: node-agent-0.13.30 + name: node-agent-0.13.31 path: | - dist/artifacts/node-agent-0.13.30.tar.gz - dist/artifacts/node-agent-0.13.30-windows-amd64.zip + dist/artifacts/node-agent-0.13.31.tar.gz + dist/artifacts/node-agent-0.13.31-windows-amd64.zip dist/artifacts/SHA256SUMS if-no-files-found: error retention-days: 30 diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index bfb9297e..0be4465a 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -2,6 +2,20 @@ The node agent preserves established event names, reply payloads, generated client schemas, Docker labels, state fields, registration-script inputs, and storage-driver identifiers consumed by existing deployments. +## Linux Host API producer in 0.13.31 + +The source package version is `0.13.31`. Its Linux supervisor requires exactly +Host API `0.38.7`, installed first through the existing authenticated configcontent +package sequence. Version mismatch still closes Host API admission without a +legacy fallback. Fixed producer paths, agent identity forwarding, executable +ownership checks, parent-bound lifetime, package layout, and both SHA-1 and +SHA-256 verification contracts are unchanged. Node does not implement stream +authorization or terminal-cause arbitration. + +Linux and Windows cross-packaging share this source version. Windows retains its +existing embedded compatibility path; cross-builds are not Windows runtime or +delegated-stream acceptance. Source versions are not publication evidence. + ## Linux Host disk reporting in 0.13.29 Filesystem enumeration and usage measurement use the same process mount view. diff --git a/README.md b/README.md index 6ed94ce7..5434caf5 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@ From a Docker-capable Linux host: make test make build make package -make package-image IMAGE_NAME=pasturestack/node-agent TAG=v0.13.30 +make package-image IMAGE_NAME=pasturestack/node-agent TAG=v0.13.31 ``` Packaging is local only and does not push an image. See [COMPATIBILITY.md](COMPATIBILITY.md), [SECURITY.md](SECURITY.md), and [ORIGIN.md](ORIGIN.md). -The current recipe packages version `0.13.30`. Source changes alone are not +The current recipe packages version `0.13.31`. Source changes alone are not publication proof: use the [official releases](https://github.com/PastureStack/node-agent/releases) and their SHA-256 checksums to verify published packages. Published tags and assets remain immutable; later documentation commits do not change their producer identity. @@ -39,9 +39,9 @@ client 0.5, gopsutil v4.26, mapstructure v2.5, netlink v1.3, and netns v0.0.5. The retired AWS SDK v1, Aliyungo, root Docker module, GOPATH/Godeps, and Trash dependency paths are not part of the build. -`VERSION_OVERRIDE=v0.13.30 make package` produces the deterministic Linux asset `node-agent-0.13.30.tar.gz`. The archive carries the legacy SHA-1 and current SHA-256 manifests required by the authenticated configcontent installer. The producer release is published by this repository; Server can embed that verified archive and distribute it through the existing configuration channel. Component publication and matching Server acceptance are separate evidence boundaries. +`VERSION_OVERRIDE=v0.13.31 make package` produces the deterministic Linux asset `node-agent-0.13.31.tar.gz`. The archive carries the legacy SHA-1 and current SHA-256 manifests required by the authenticated configcontent installer. The producer release is published by this repository; Server can embed that verified archive and distribute it through the existing configuration channel. Component publication and matching Server acceptance are separate evidence boundaries. -On Linux, Node supervises the separately maintained `host-api` producer at `${PASTURESTACK_HOME:-${CATTLE_HOME:-/var/lib/pasturestack}}/bin/host-api`. Host API `0.38.6` must be installed before the Node package by the existing `pyagent` package sequence. Node verifies its exact version, forwards the current agent/host identity only through process environment, restarts an exited child, and binds its lifetime to Node. Missing or incompatible producers never fall back to the embedded legacy Host API. Stream authorization, target binding, and private durable terminal evidence remain owned by the Host API producer. +On Linux, Node supervises the separately maintained `host-api` producer at `${PASTURESTACK_HOME:-${CATTLE_HOME:-/var/lib/pasturestack}}/bin/host-api`. Host API `0.38.7` must be installed before the Node package by the existing `pyagent` package sequence. Node verifies its exact version, forwards the current agent/host identity only through process environment, restarts an exited child, and binds its lifetime to Node. Missing or incompatible producers never fall back to the embedded legacy Host API. Stream authorization, target binding, and private durable terminal evidence remain owned by the Host API producer. Windows retains the existing embedded compatibility path; this release does not provide Windows stream delegation or durable terminal evidence support. A replacement Windows bootstrap image and upgrade/rollback tests are still required before Windows hosts are supported. The Server recipe independently pins its Windows artifact; a Linux package publication and CI cross-builds do not establish new Windows runtime acceptance. diff --git a/scripts/version b/scripts/version index eedc3d0c..bc4a1e5b 100755 --- a/scripts/version +++ b/scripts/version @@ -5,4 +5,4 @@ if [ -n "$VERSION_OVERRIDE" ]; then return 0 fi -VERSION=v0.13.30 +VERSION=v0.13.31 diff --git a/service/hostapilauncher/process_linux_test.go b/service/hostapilauncher/process_linux_test.go index 5ce936fc..2da65b30 100644 --- a/service/hostapilauncher/process_linux_test.go +++ b/service/hostapilauncher/process_linux_test.go @@ -19,7 +19,7 @@ func TestProducerIsBoundToLinuxParentDeathAndRejectsUnsafeExecutable(t *testing. } directory := t.TempDir() file := filepath.Join(directory, "host-api") - if err := os.WriteFile(file, []byte("#!/bin/sh\nprintf '0.38.6\\n'\n"), 0755); err != nil { + if err := os.WriteFile(file, []byte("#!/bin/sh\nprintf '0.38.7\\n'\n"), 0755); err != nil { t.Fatal(err) } if err := validateProducer(context.Background(), file, os.Environ()); err != nil { diff --git a/service/hostapilauncher/supervisor.go b/service/hostapilauncher/supervisor.go index 5404b6bd..a11beb3f 100644 --- a/service/hostapilauncher/supervisor.go +++ b/service/hostapilauncher/supervisor.go @@ -17,7 +17,7 @@ import ( "github.com/rancher/log" ) -const RequiredVersion = "0.38.6" +const RequiredVersion = "0.38.7" type Settings struct { Binary string diff --git a/service/hostapilauncher/supervisor_test.go b/service/hostapilauncher/supervisor_test.go index 3c201207..b86ef5cb 100644 --- a/service/hostapilauncher/supervisor_test.go +++ b/service/hostapilauncher/supervisor_test.go @@ -9,12 +9,12 @@ import ( ) func TestProducerVersionIsExactAndBounded(t *testing.T) { - for _, version := range []string{"0.38.6", "0.38.6\n"} { + for _, version := range []string{"0.38.7", "0.38.7\n"} { if !validVersion(version) { t.Fatal("current producer rejected") } } - for _, version := range []string{"0.38.4", "0.38.5", "0.38.6-dirty", "0.38.6\nextra", ""} { + for _, version := range []string{"0.38.4", "0.38.5", "0.38.6", "0.38.8", "0.39.0", "0.038.7", "v0.38.7", "0.38.7-dirty", "0.38.7\r\n", "0.38.7\nextra", "0.38.7\n0.38.7", ""} { if validVersion(version) { t.Fatal("incompatible producer accepted") }