From 146002c029d3aa3c4d09bb0ada346abc40b04811 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Sun, 25 Oct 2026 06:43:32 +0800 Subject: [PATCH 1/2] Pin shared Ubuntu security backports for v0.14.41 Integrate only existing runtime packages and preserve raw scans, native OpenVEX, producer checksum verification and strict vulnerability policy. Shared OCI producer: 59f4ec1f31e510361c4635023c08fcf2a2b2133c. OCI completion and final-image gates remain pending; this source commit does not publish a release. --- .../enforce-runtime-vulnerabilities.py | 4 +- .github/workflows/codeql-verification.yml | 2 +- .github/workflows/release.yml | 80 +++++--- .github/workflows/security-release-gate.yml | 38 +++- README.md | 183 +++--------------- package/Dockerfile | 21 ++ 6 files changed, 131 insertions(+), 197 deletions(-) diff --git a/.github/scripts/enforce-runtime-vulnerabilities.py b/.github/scripts/enforce-runtime-vulnerabilities.py index db676ee..ee38273 100644 --- a/.github/scripts/enforce-runtime-vulnerabilities.py +++ b/.github/scripts/enforce-runtime-vulnerabilities.py @@ -51,9 +51,9 @@ def violations(report, ledger, repository): reports = { "source": "evidence/source-security.json", "product": "evidence/product-security.json", - "runtime": "evidence/runtime-security.json", + "runtime": "evidence/runtime-security.effective.json", "dapper": "evidence/dapper-nonheader-security.json", - "release-runtime": "dist/release/runtime-security.json", + "release-runtime": "dist/release/runtime-security.effective.json", } parser.add_argument("scope", choices=tuple(reports)) parser.add_argument("--repository", required=True) diff --git a/.github/workflows/codeql-verification.yml b/.github/workflows/codeql-verification.yml index 80e1432..2dab840 100644 --- a/.github/workflows/codeql-verification.yml +++ b/.github/workflows/codeql-verification.yml @@ -53,7 +53,7 @@ jobs: cd "$GITHUB_WORKSPACE" go test -run '^$' ./... go test -run '^$' -tags=integration ./store - VERSION_OVERRIDE=0.14.40 ./scripts/build + VERSION_OVERRIDE=0.14.41 ./scripts/build - name: Analyze without publishing temporary alerts uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a1d0db..cc6432e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ name: Release IPsec overlay -# A release is dispatched from main only after an annotated v0.14.40 tag and +# A release is dispatched from main only after an annotated v0.14.41 tag and # successful, same-commit Security release gate and CodeQL verification runs. # GHCR, registry attestations, and GitHub Releases are not an atomic transaction. # All source/product/runtime gates precede the image push. A later failure may @@ -9,11 +9,11 @@ on: workflow_dispatch: inputs: release_tag: - description: Existing annotated, numeric v0.14.40 tag at main HEAD + description: Existing annotated, numeric v0.14.41 tag at main HEAD required: true type: choice options: - - v0.14.40 + - v0.14.41 security_run_id: description: Successful same-SHA Security release gate run ID required: true @@ -35,7 +35,7 @@ permissions: attestations: write concurrency: - group: ipsec-vxlan-overlay-release-v0.14.40 + group: ipsec-vxlan-overlay-release-v0.14.41 cancel-in-progress: false jobs: @@ -48,8 +48,8 @@ jobs: CODEQL_RUN_ID: ${{ inputs.codeql_run_id }} RESUME_DIGEST: ${{ inputs.resume_digest }} GH_TOKEN: ${{ github.token }} - SERVICE_IMAGE: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.40 - LOCAL_IMAGE: local/pasturestack/ipsec-vxlan-overlay-network:0.14.40 + SERVICE_IMAGE: ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.41 + LOCAL_IMAGE: local/pasturestack/ipsec-vxlan-overlay-network:0.14.41 TRIVY_IMAGE: aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969 GOFLAGS: -mod=vendor GOWORK: off @@ -67,7 +67,7 @@ jobs: run: | set -euo pipefail test "$GITHUB_REF" = refs/heads/main - test "$RELEASE_TAG" = v0.14.40 + test "$RELEASE_TAG" = v0.14.41 [[ "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] [[ "$SECURITY_RUN_ID" =~ ^[0-9]+$ ]] [[ "$CODEQL_RUN_ID" =~ ^[0-9]+$ ]] @@ -115,7 +115,7 @@ jobs: --name "ipsec-vxlan-overlay-network-security-$SOURCE_SHA" --dir evidence for file in SHA256SUMS source-tree.txt source-locks.sha256 product.sha256 \ security-summary.txt source-security.json product-security.json \ - runtime-security.json source-sbom.cdx.json dapper-security.json \ + runtime-security.json runtime-security.effective.json source-sbom.cdx.json dapper-security.json \ dapper-nonheader-security.json; do test -s "evidence/$file" done @@ -134,6 +134,7 @@ jobs: done for scope in source product runtime; do report="evidence/${scope}-security.json" + if [ "$scope" = runtime ]; then report=evidence/runtime-security.effective.json; fi python3 .github/scripts/enforce-runtime-vulnerabilities.py \ "$scope" --repository "$GITHUB_REPOSITORY" for field in secrets critical high; do @@ -162,15 +163,15 @@ jobs: shell: bash run: | set -euo pipefail - VERSION_OVERRIDE=0.14.40 ./scripts/build + VERSION_OVERRIDE=0.14.41 ./scripts/build sha256sum --check evidence/product.sha256 if [ -z "$RESUME_DIGEST" ]; then - VERSION_OVERRIDE=0.14.40 TAG=0.14.40 REPO=local/pasturestack \ + VERSION_OVERRIDE=0.14.41 TAG=0.14.41 REPO=local/pasturestack \ IMAGE_REVISION="$SOURCE_SHA" ./scripts/package test "$(wc -l < dist/images)" -eq 1 grep -Fx "$LOCAL_IMAGE" dist/images test "$(docker image inspect "$LOCAL_IMAGE" \ - --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" = 0.14.40 + --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" = 0.14.41 test "$(docker image inspect "$LOCAL_IMAGE" \ --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" = "$SOURCE_SHA" docker tag "$LOCAL_IMAGE" "$SERVICE_IMAGE" @@ -188,7 +189,7 @@ jobs: docker pull "$SERVICE_IMAGE@$RESUME_DIGEST" docker tag "$SERVICE_IMAGE@$RESUME_DIGEST" "$SERVICE_IMAGE" test "$(docker image inspect "$SERVICE_IMAGE" \ - --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" = 0.14.40 + --format '{{index .Config.Labels "org.opencontainers.image.version"}}')" = 0.14.41 test "$(docker image inspect "$SERVICE_IMAGE" \ --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" = "$SOURCE_SHA" verification_container="$(docker create "$SERVICE_IMAGE")" @@ -209,6 +210,12 @@ jobs: docker rm "$verification_container" >/dev/null trap - EXIT fi + release_container=$(docker create "$SERVICE_IMAGE") + trap 'docker rm "$release_container" >/dev/null' EXIT + docker cp "$release_container:/usr/share/pasturestack/security/ubuntu-backports" "$release_dir/ubuntu-backports" + docker rm "$release_container" >/dev/null + trap - EXIT + (cd "$release_dir/ubuntu-backports" && sha256sum --check SHA256SUMS) docker pull "$TRIVY_IMAGE" cache="$RUNNER_TEMP/ipsec-release-trivy-cache" mkdir -p "$cache" @@ -220,13 +227,6 @@ jobs: --scanners vuln,secret --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL --format json \ --output /release/runtime-security.json "$SERVICE_IMAGE" test -s "$release_dir/runtime-security.json" - python3 .github/scripts/test_runtime_vulnerability_policy.py - python3 .github/scripts/enforce-runtime-vulnerabilities.py \ - release-runtime --repository "$GITHUB_REPOSITORY" - test "$(jq '[.Results[]?.Secrets[]?] | length' "$release_dir/runtime-security.json")" -eq 0 - test "$(jq '[.Results[]?.Vulnerabilities[]? | - select(.Severity == "CRITICAL" or .Severity == "HIGH")] | length' \ - "$release_dir/runtime-security.json")" -eq 0 docker run --rm --network none -v /var/run/docker.sock:/var/run/docker.sock \ -v "$cache:/root/.cache/trivy" -v "$release_dir:/release" "$TRIVY_IMAGE" \ image --cache-dir /root/.cache/trivy --skip-db-update --offline-scan \ @@ -234,6 +234,29 @@ jobs: test -s "$release_dir/image-sbom.cdx.json" jq -e '.serialNumber and ((.components // []) | length > 0)' \ "$release_dir/image-sbom.cdx.json" >/dev/null + # The same immutable OCI supplied this checksum-checked runner guard + # during the candidate gate; downloaded evidence is SHA-bound above. + (cd evidence/bundle-tools && \ + test "$(grep -Ec '^[0-9a-f]{64} verify-consumer-evidence\.py$' SHA256SUMS)" -eq 1 && \ + grep -E '^[0-9a-f]{64} verify-consumer-evidence\.py$' SHA256SUMS | sha256sum --check -) + python3 evidence/bundle-tools/verify-consumer-evidence.py \ + --evidence-dir "$release_dir/ubuntu-backports" --sbom "$release_dir/image-sbom.cdx.json" \ + --bundle-checksums evidence/bundle-tools/SHA256SUMS \ + --expected-bundle-digest 'sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a' > "$release_dir/ubuntu-backports-validation.json" + docker run --rm --network none -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$cache:/root/.cache/trivy" -v "$release_dir:/release" "$TRIVY_IMAGE" \ + image --cache-dir /root/.cache/trivy --skip-db-update --offline-scan \ + --scanners vuln,secret --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL \ + --vex /release/ubuntu-backports/openvex.json --format json \ + --output /release/runtime-security.effective.json "$SERVICE_IMAGE" + python3 .github/scripts/test_runtime_vulnerability_policy.py + python3 .github/scripts/enforce-runtime-vulnerabilities.py \ + release-runtime --repository "$GITHUB_REPOSITORY" + test "$(jq '[.Results[]?.Secrets[]?] | length' "$release_dir/runtime-security.effective.json")" -eq 0 + test "$(jq '[.Results[]?.Vulnerabilities[]? | + select(.Severity == "CRITICAL" or .Severity == "HIGH")] | length' \ + "$release_dir/runtime-security.effective.json")" -eq 0 + tar -cf "$release_dir/ubuntu-backports-evidence.tar" -C "$release_dir" ubuntu-backports ubuntu-backports-validation.json cp evidence/source-sbom.cdx.json "$release_dir/source-sbom.cdx.json" cp evidence/product.sha256 "$release_dir/product.sha256" cp evidence/security-summary.txt "$release_dir/gate-security-summary.txt" @@ -328,7 +351,7 @@ jobs: run: | set -euo pipefail release_dir="dist/release" - product_dir="$release_dir/ipsec-vxlan-overlay-network-0.14.40-linux-amd64" + product_dir="$release_dir/ipsec-vxlan-overlay-network-0.14.41-linux-amd64" mkdir -p "$product_dir" cp bin/ipsec-vxlan-overlay-network bin/ipsec-vxlan-overlay-topology bin/pasture-cni-resolver \ LICENSE ORIGIN.md SECURITY.md THIRD_PARTY_NOTICES.md "$product_dir/" @@ -340,13 +363,14 @@ jobs: find "$product_dir" -exec touch -h -d "@$source_epoch" {} + tar --sort=name --mtime="@$source_epoch" --owner=0 --group=0 \ --numeric-owner -C "$release_dir" \ - -cJf "$release_dir/ipsec-vxlan-overlay-network-0.14.40-linux-amd64.tar.xz" \ - ipsec-vxlan-overlay-network-0.14.40-linux-amd64 + -cJf "$release_dir/ipsec-vxlan-overlay-network-0.14.41-linux-amd64.tar.xz" \ + ipsec-vxlan-overlay-network-0.14.41-linux-amd64 ( cd "$release_dir" - sha256sum ipsec-vxlan-overlay-network-0.14.40-linux-amd64.tar.xz \ + sha256sum ipsec-vxlan-overlay-network-0.14.41-linux-amd64.tar.xz \ source-sbom.cdx.json image-sbom.cdx.json product.sha256 \ - runtime-security.json gate-security-summary.txt image-digest.txt \ + runtime-security.json runtime-security.effective.json ubuntu-backports-evidence.tar \ + gate-security-summary.txt image-digest.txt \ release-identity.txt > SHA256SUMS sha256sum --check SHA256SUMS ) @@ -368,13 +392,15 @@ jobs: run: | set -euo pipefail gh release create "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --verify-tag \ - --title 'IPsec Overlay v0.14.40' \ + --title 'IPsec Overlay v0.14.41' \ --notes "Source ${SOURCE_SHA}; Security gate run ${SECURITY_RUN_ID}; CodeQL run ${CODEQL_RUN_ID}. GHCR image ${SERVICE_IMAGE}@$(cat dist/release/image-digest.txt | sed 's/^.*@//')." \ - dist/release/ipsec-vxlan-overlay-network-0.14.40-linux-amd64.tar.xz \ + dist/release/ipsec-vxlan-overlay-network-0.14.41-linux-amd64.tar.xz \ dist/release/source-sbom.cdx.json \ dist/release/image-sbom.cdx.json \ dist/release/product.sha256 \ dist/release/runtime-security.json \ + dist/release/runtime-security.effective.json \ + dist/release/ubuntu-backports-evidence.tar \ dist/release/gate-security-summary.txt \ dist/release/image-digest.txt \ dist/release/release-identity.txt \ @@ -382,7 +408,7 @@ jobs: gh api "repos/$GITHUB_REPOSITORY/releases/tags/$RELEASE_TAG" | jq -e --arg tag "$RELEASE_TAG" \ '.tag_name == $tag and .draft == false and .prerelease == false and - (.assets | length) == 9' >/dev/null + (.assets | length) == 11' >/dev/null - name: Preserve image digest for a safe retry after partial publication if: always() diff --git a/.github/workflows/security-release-gate.yml b/.github/workflows/security-release-gate.yml index 8cd1df0..02187f9 100644 --- a/.github/workflows/security-release-gate.yml +++ b/.github/workflows/security-release-gate.yml @@ -20,12 +20,12 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 120 env: - CANDIDATE_VERSION: 0.14.40 - VERSION_OVERRIDE: 0.14.40 - TAG: 0.14.40 + CANDIDATE_VERSION: 0.14.41 + VERSION_OVERRIDE: 0.14.41 + TAG: 0.14.41 IMAGE_REVISION: ${{ github.sha }} REPO: local/pasturestack - IMAGE: local/pasturestack/ipsec-vxlan-overlay-network:0.14.40 + IMAGE: local/pasturestack/ipsec-vxlan-overlay-network:0.14.41 GO_VERSION: 1.27.3 GO_LINUX_AMD64_SHA256: 65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40 TRIVY_IMAGE: aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969 @@ -115,6 +115,8 @@ jobs: test "$(docker image inspect "$IMAGE" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" = "$GITHUB_SHA" candidate_container="$(docker create "$IMAGE")" docker cp "$candidate_container:/opt/cni/bin/pasture-bridge" evidence/pasture-bridge.image + docker cp "$candidate_container:/usr/share/pasturestack/security/ubuntu-backports" evidence/ubuntu-backports + (cd evidence/ubuntu-backports && sha256sum --check SHA256SUMS) docker rm "$candidate_container" >/dev/null cmp bin/pasture-cni-resolver evidence/pasture-bridge.image # All five published companion binaries ship in the runtime image. @@ -224,6 +226,26 @@ jobs: "$TRIVY_IMAGE" image --cache-dir /root/.cache/trivy \ --skip-db-update --offline-scan --format cyclonedx \ --output /work/evidence/runtime-sbom.cdx.json "$IMAGE" + bundle_image='ghcr.io/pasturestack/ubuntu-security-backports:v0.1.0@sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a' + mkdir -p evidence/bundle-tools + bundle_container=$(docker create "$bundle_image" unused) + trap 'docker rm "$bundle_container" >/dev/null' EXIT + docker cp "$bundle_container:/out/verify-consumer-evidence.py" evidence/bundle-tools/verify-consumer-evidence.py + docker cp "$bundle_container:/out/SHA256SUMS" evidence/bundle-tools/SHA256SUMS + docker rm "$bundle_container" >/dev/null + trap - EXIT + (cd evidence/bundle-tools && \ + test "$(grep -Ec '^[0-9a-f]{64} verify-consumer-evidence\.py$' SHA256SUMS)" -eq 1 && \ + grep -E '^[0-9a-f]{64} verify-consumer-evidence\.py$' SHA256SUMS | sha256sum --check -) + python3 evidence/bundle-tools/verify-consumer-evidence.py \ + --evidence-dir evidence/ubuntu-backports --sbom evidence/runtime-sbom.cdx.json \ + --bundle-checksums evidence/bundle-tools/SHA256SUMS \ + --expected-bundle-digest 'sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a' > evidence/ubuntu-backports-validation.json + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$TRIVY_CACHE:/root/.cache/trivy" -v "$PWD:/work" -w /work "$TRIVY_IMAGE" \ + image --cache-dir /root/.cache/trivy --skip-db-update --offline-scan --scanners vuln,secret \ + --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL --vex /work/evidence/ubuntu-backports/openvex.json \ + --format json --output /work/evidence/runtime-security.effective.json "$IMAGE" dapper_rootfs=$(mktemp -d "$RUNNER_TEMP/ipsec-overlay-dapper.XXXXXX") dapper_container=$(docker create "$DAPPER_IMAGE") docker export "$dapper_container" | tar --no-same-owner --no-same-permissions -x -C "$dapper_rootfs" @@ -304,7 +326,7 @@ jobs: impact_statement:$impact }] | { "@context":"https://openvex.dev/ns/v0.2.0", - "@id":"https://github.com/PastureStack/ipsec-vxlan-overlay-network/security/openvex/dapper/0.14.40", + "@id":"https://github.com/PastureStack/ipsec-vxlan-overlay-network/security/openvex/dapper/0.14.41", author:"PastureStack Security", timestamp:$timestamp, version:1, @@ -320,10 +342,14 @@ jobs: run: | set -euo pipefail cd "$GITHUB_WORKSPACE" - : > evidence/security-summary.txt + printf 'runtime_policy_input=runtime-security.effective.json\n' > evidence/security-summary.txt + jq '{critical: [.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length, + high: [.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH")] | length}' \ + evidence/runtime-security.json > evidence/runtime-raw-severity-counts.json python3 .github/scripts/test_runtime_vulnerability_policy.py for scope in source product runtime; do report="evidence/${scope}-security.json" + if [ "$scope" = runtime ]; then report=evidence/runtime-security.effective.json; fi secrets=$(jq '[.Results[]?.Secrets[]?] | length' "$report") critical=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length' "$report") high=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH")] | length' "$report") diff --git a/README.md b/README.md index 0b6ad05..308b687 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # PastureStack IPsec/VXLAN Overlay Network -Current source builds use Go 1.27.3 while the Go language minimum remains 1.26.0. The selected `golang.org/x/net` version is v0.60.0; its required `golang.org/x/sys` version is v0.48.0. Ubuntu 26.04 images install the checksum-pinned `ca-certificates` 20260816ubuntu0.26.04.1 package with only officially fixed, already-installed packages advanced by the reviewed security overlay. These source inputs take effect in newly built artifacts; existing published release coordinates below describe their original artifacts. +Linux candidate **`v0.14.41`** integrates shared Ubuntu 26.04 security backports for already-installed packages while preserving the selected coreutils provider. It is unpublished; the last published Linux release is [v0.14.40](https://github.com/PastureStack/ipsec-vxlan-overlay-network/releases/tag/v0.14.40). + +Build and image examples below target the candidate. Publication requires completed bundle provenance and the normal final-image release gates. The image retains bundle manifests, source inputs and install/verify receipts under `/usr/share/pasturestack/security/ubuntu-backports/`. This repository provides the privileged network data plane used by PastureStack. It contains IPsec and VXLAN overlay processes, connectivity checks, CNI runtime assets, and an audit-only topology planner. @@ -8,161 +10,21 @@ PastureStack is an independent community effort to preserve, audit, and moderniz ## Release status -Published [v0.14.40](https://github.com/PastureStack/ipsec-vxlan-overlay-network/releases/tag/v0.14.40) refreshes the compiler, effective Go dependencies, -official Ubuntu security packages, and checksum-pinned companion binaries. -The companions are metadata CNI IPAM `v0.2.8`, host-local CNI IPAM `v0.1.6`, -flat CNI IPAM `v0.1.6`, mount propagation `v1.0.12`, and per-host subnet -`v0.2.5`. The last is an official Go 1.27.3 rebuild whose Go implementation -and tests are byte-identical to the historical `v0.2.8` prerelease companion; -the numeric tag difference does not remove a runtime feature. The security -APT overlay uses private index/cache paths and verifies that the original -strongSwan source index remains readable. Networking, CLI/API, CNI, and -firewall ownership contracts are unchanged. The published image records producer -`4711833178a05e5d225e364cce856bd108bdc707` and manifest digest -`sha256:1d39becf00ea540355cb60b430d5d379d38451c1b633ce0d704ef046f44f2c07`. -See the [official publication](https://github.com/PastureStack/ipsec-vxlan-overlay-network/actions/runs/39971594096) -for same-source checks and scan evidence. Managed-service upgrade acceptance -remains separate from publication. - -The immutable `v0.14.39` release is retained but is not recommended for new -deployments: its historical HIGH/CRITICAL-only scan missed officially fixed -MEDIUM findings in strongSwan and systemd-sysusers. `v0.14.40` pins Ubuntu's -strongSwan `6.0.4-1ubuntu3.2` and systemd-sysusers `259.5-0ubuntu3.4`, carries -the matching checksum-bound strongSwan source, and scans all severities. -Any finding with an official fixed version blocks publication, including -LOW/MEDIUM; HIGH, CRITICAL, UNKNOWN, secrets, and unregistered findings also -block. Only exact repository/package/version/PURL LOW/MEDIUM entries backed -by the official Ubuntu no-fix ledger can pass. The disposable builder's -kernel-header scope stays separate and never exempts shipped runtime code. - -The prior `v0.14.27` source and image were published with manifest digest -`sha256:917c4369ee22808c100dd890d17296fe341e0dda4b2ad2923050f4fca5c22386` -and release SBOM/provenance attestations. On an isolated Ubuntu 26.04.1 / Docker 29.8 VM, that -published image selected native nftables without modifying host rules, rejected -an explicit legacy mismatch, and passed a two-container XFRM/encrypted-packet -integration test. That test is not a two-physical-host upgrade or reboot gate. -Publishing the image alone does not change deployments. - -`v0.14.28` tightened host firewall detection. Published `v0.14.29` keeps that -validation but leaves host NAT, forwarding, and host ports solely to Network -Plugin Manager. The official image manifest is -`sha256:e65921d3ea7ec3a3582400b0bc2ca3297484375bad42dd61bbf74b1201c18ad1` -from source commit `276f8fee8ceb64a216a2907fdb0c60394296a208`; the same-commit -security and CodeQL gates and the release rebuild passed. Upgrade the manager -and verify it is healthy before upgrading this router; publishing an image and -updating Catalog are separate gates. Check the Catalog version lock for the -current deployment coordinate. - -The published `v0.14.30` image (manifest -`sha256:326cec5fa786dbb18df68d10653b3cef1af4785cbb0897aecb616ffcec7914ca`, -source `8b9e40b88c027c0c3c76720f8077a5a82aa63473`) addresses a -rolling-upgrade handoff observed on two -managed hosts: both router generations briefly shared host network port 8111, -but the old startup guard inspected the holder namespace instead of the host -namespace where the router actually listens. The new guard checks the target -namespace before launching the router, waits at most 90 seconds for the prior -listener to leave, and fails clearly if that cannot be verified. It does not -change firewall ownership, Docker backend selection, or XFRM policy. Catalog -Templates `v0.3.4` publishes this image in IPsec Overlay template version `5`; -that publication is distinct from a completed live rolling-upgrade gate. - -The image is intended to be launched by the PastureStack infrastructure catalog. The IPsec router requires host PID access, `NET_ADMIN`-equivalent privileged access, and the network namespace contract documented in [COMPATIBILITY.md](COMPATIBILITY.md). It is not a standalone control plane or an unprivileged application container. - -The published `v0.14.31` image (manifest -`sha256:4d8a51e04bdd27fea3cb2949158103d43e0d2470907c328f76f7a0c6ccec8608`, -source `22f486cbcbcf92bda91fce555268226eddd723ba`) keeps charon running -when one peer is temporarily unavailable (for example, during a host reboot). -The existing 30-second IPsec health reconciliation retries that missing -CHILD_SA; a stale local peer identity still uses its separate explicit charon -restart path. This does not change firewall ownership or the selected Docker -firewall backend. Catalog pinning and live peer-restart verification remain -separate gates. - -The `v0.14.32` change was scoped to IPsec peer lifecycle. Each managed IKE -connection requests strongSwan's per-peer `unique=replace` policy, including -older custom templates that omit the option; an explicit template policy is -preserved. The health reconciler force-removes only a `DELETING` IKE_SA for -which the same managed peer already has an established replacement with an -installed CHILD_SA. It never terminates by connection name or changes host -firewall rules. The isolated two-node regression test now forces concurrent -initiation and a one-sided peer restart, and requires exactly one working SA -on each side within a bounded convergence window while encrypted traffic -continues. This source change is not proof that a Catalog or live host has -already been upgraded. A subsequent live rolling upgrade on two hosts showed -that `unique=replace` and cleanup of `DELETING` SAs alone did not converge: -both peers retained two established SAs, with only one carrying traffic. - -`v0.14.33` keeps the 30-second health reconciler as the owner of missing-SA -recovery and changes the default CHILD `close_action` to `none`, avoiding a -second automatic initiation path after peer close. Explicit custom CHILD -templates remain unchanged. After four health cycles, the reconciler may -terminate only an idle established duplicate for the same managed peer when -exactly one other installed association has carried traffic. Ambiguous or -recent pairs, unrelated peers, and other connections are left untouched. The -live two-host upgrade and traffic gates remain separate from this source fix. - -Published `v0.14.34` adds a bounded CNI entrypoint adapter for the official -per-host-subnet template. Only `bridgeSubnet`, `ipam.subnet`, and optional IP -range fields containing an explicit `__host_label__:` reference are resolved -from the local host Metadata API. Literal flat-network CNI documents are -forwarded byte-for-byte to the preserved bridge binary. Missing required -labels, malformed IPv4 values, mismatched bridge/IPAM subnets, or metadata -errors fail before changing the bridge. This does not select or alter the host -firewall backend; Network Plugin Manager continues to own NAT and host ports. -Catalog Templates `v0.3.8` pins this image in IPsec Overlay template version -`9`, and Server `v1.6.436` embeds that Catalog. The official release image -passed the isolated native-nftables, iptables-nft, and iptables-legacy gates; -the two-host Catalog upgrade on the managed test environment converged with -`v0.14.34` running for the router, connectivity check, and CNI driver. Both -managed hosts were then rebooted one at a time: after agent/CNI startup, -cross-host TCP, local Metadata/DNS, and HTTPS egress passed in both workload -namespaces. Startup is asynchronous, so a service-level healthy status alone -must not be used as proof that a restarted workload has acquired its IP. - -`v0.14.35` addressed a separate rolling-upgrade handoff: a -replacement connectivity-check can briefly share the prior generation's -network namespace while the old sidecar still owns TCP 80. It waits at most -90 seconds for that listener to leave, retrying only `EADDRINUSE`; an unrelated -bind error or exhausted deadline still fails clearly. This stays inside the -connectivity-check module and does not alter host firewall rules, Docker -backend selection, or the router's port 8111 ownership. Source tests hold and -release the port and verify the bounded failure path. Image publication, -Catalog pinning, and live upgrade acceptance are separate gates for each release. - -Published `v0.14.36` updates the packaged preserved bridge compatibility -binary to `v0.7.2`. In the Layer 2 Flat template it honors -`skipBridgeConfigureIP`, so the CNI driver does not add another address to an -operator-owned bridge. It packages `flat-cni-ipam v0.1.4` and does not change -firewall ownership. Catalog Templates `v0.3.11` pins this image in Layer 2 Flat -template version `5`; Server `v1.6.439` embeds that Catalog. - -Published `v0.14.37` updates only the packaged flat-network IPAM companion to -`flat-cni-ipam v0.1.5`. When a template expresses `bridgeSubnet` with the -network address, the IPAM now selects the same first usable gateway derived by -the bridge plugin if that address is present. This makes restart reconciliation -deterministic when an operator-owned flat bridge also carries a separate host -address. Explicit host addresses still win, and an unresolved multi-address -bridge still fails closed instead of guessing. Firewall ownership and backend -selection remain unchanged. Publication, Catalog pinning, and live reboot -acceptance are separate gates. - -Candidate `v0.14.38` repairs IPsec connection caching when the local Metadata -Agent IP changes. Its fingerprint includes that IP and the complete effective -IKE configuration. A discovered connection name is not a verified fingerprint; -only a successful `load-conn` updates the cache. Proposals, explicit identities, -custom CHILD settings, firewall ownership, and backend selection are unchanged. - -After the new connection, policies, and host routes load successfully, cleanup -may terminate only an exact IKE ID for the same managed peer and an old local -endpoint anchored in this process's previous successful load. This includes a -CONNECTING association without a CHILD. Foreign children, identities, peers, -ambiguous IDs, and unknown imported configurations do not authorize cleanup. -Load failure never updates the cache or triggers this cleanup; no daemon restart -is added. Unit tests and a Linux cross-build are source-only evidence, not proof -of publication or live recovery. The release digest, Catalog pinning, and managed -two-host endpoint-change acceptance remain separate gates. -Normal PR merges still require successful Security and CodeQL gates on the exact -final source SHA before release. +After publication, select `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.41` through the infrastructure +Catalog. Security and CodeQL checks, the release scan and immutable publication +must pass first. Image publication, Catalog selection and managed-host +acceptance are separate. + +The image is launched by the infrastructure Catalog. The IPsec router requires +host PID access, privileged networking, and the namespace contract in +[COMPATIBILITY.md](COMPATIBILITY.md). Network Plugin Manager owns host NAT, +forwarding and host ports; this update preserves that ownership and the +selected GNU/uutils provider. + +The checksum-pinned companions remain metadata CNI IPAM `v0.2.8`, host-local +CNI IPAM `v0.1.6`, flat CNI IPAM `v0.1.6`, mount propagation `v1.0.12`, per-host +subnet `v0.2.5`, and the preserved bridge compatibility binary `v0.7.2`. +The original strongSwan source and package locks remain independently retained. The release gate retains every severity and rejects fixed findings, unreviewed findings, Critical/High/Unknown findings, and secrets in the source, @@ -190,11 +52,11 @@ The build is containerized and requires Docker on a Linux AMD64 host: ```sh make test make validate -VERSION_OVERRIDE=0.14.40 make build -TAG=0.14.40 make package +VERSION_OVERRIDE=0.14.41 make build +TAG=0.14.41 make package ``` -The package build downloads dependencies anonymously, verifies every standalone binary with SHA-256, pins the Ubuntu base image by digest, resolves packages from Canonical snapshot `20260808T000000Z` with the exact versions in `ubuntu-apt.lock`, and includes the corresponding strongSwan source archives in the image. The sole package overlay is the checksum-pinned OpenSSL triplet (`openssl`, `libssl3t64`, `openssl-provider-legacy`) at `3.5.5-1ubuntu3.6` from snapshot `20260930T000000Z`, fixing CVE-2026-84782 in both Dapper and runtime without changing other package locks or the kernel-header review boundary. Go dependencies are declared in `go.mod`, checksum-bound by `go.sum`, and committed in the standard module-aware `vendor` tree for offline builds. +The package build downloads dependencies anonymously, verifies every standalone binary with SHA-256, pins the Ubuntu base image by digest, resolves packages from Canonical snapshot `20260808T000000Z` with the exact versions in `ubuntu-apt.lock`, and includes the corresponding strongSwan source archives in the image. The build also retains the checksum-pinned OpenSSL triplet (`openssl`, `libssl3t64`, `openssl-provider-legacy`) at `3.5.5-1ubuntu3.6` from snapshot `20260930T000000Z`, fixing CVE-2026-84782 in both Dapper and runtime without changing other package locks or the kernel-header review boundary. Go dependencies are declared in `go.mod`, checksum-bound by `go.sum`, and committed in the standard module-aware `vendor` tree for offline builds. The release gate also runs `scripts/integration-optional-cni-isolated` against the image it just packaged. Inside a disposable, network-isolated container it @@ -212,8 +74,7 @@ The health reconciler canonicalizes strongSwan VICI CHILD_SA runtime names befor ## Host firewall backends -The Catalog IPsec `overlay-router` runs in the host network namespace. With -`v0.14.29`, `PASTURESTACK_FIREWALL_BACKEND=auto` reads Docker's actual +The Catalog IPsec `overlay-router` runs in the host network namespace. `PASTURESTACK_FIREWALL_BACKEND=auto` reads Docker's actual firewall driver from the mounted Docker socket and verifies that exactly one matching Docker-owned firewall backend has live hooks. An explicit selection is verified the same way; stale, mixed or mismatched Docker rules, reachable diff --git a/package/Dockerfile b/package/Dockerfile index 33549af..043b9ac 100644 --- a/package/Dockerfile +++ b/package/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1.7 +FROM ghcr.io/pasturestack/ubuntu-security-backports:v0.1.0@sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a AS ubuntu_security_backports FROM ubuntu:26.04@sha256:2260313b31c8c011cd2eebe728008efac1b3982be73eb71348ea2648d2c0e09b COPY ubuntu-apt.lock /licenses/ubuntu-apt.lock @@ -155,5 +157,24 @@ LABEL org.opencontainers.image.source="https://github.com/PastureStack/ipsec-vxl org.opencontainers.image.revision="${IMAGE_REVISION}" \ org.pasturestack.third-party-licenses="See /licenses/pasturestack/THIRD_PARTY_NOTICES.md" +# Install only qualified packages already present after the final Ubuntu update. +# This read-only build mount leaves no installer, archive or extra runtime tool. +RUN --mount=from=ubuntu_security_backports,source=/out,target=/opt/pasturestack/ubuntu-security-backports,ro \ + set -eux; \ + evidence=/usr/share/pasturestack/security/ubuntu-backports; \ + mkdir -p "${evidence}"; \ + /opt/pasturestack/ubuntu-security-backports/install-existing-backports --install-in-docker-build > "${evidence}/install.json"; \ + /opt/pasturestack/ubuntu-security-backports/install-existing-backports --verify-installed > "${evidence}/verify.json"; \ + for document in manifest.json qualification.json openvex.json source-inputs.lock.json; do \ + cp "/opt/pasturestack/ubuntu-security-backports/${document}" "${evidence}/${document}"; \ + done; \ + printf '%s\n' 'ghcr.io/pasturestack/ubuntu-security-backports:v0.1.0@sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a' > "${evidence}/bundle-image.txt"; \ + (cd "${evidence}" && sha256sum manifest.json qualification.json openvex.json source-inputs.lock.json install.json verify.json bundle-image.txt > SHA256SUMS); \ + dpkg-query -W -f='${binary:Package}\t${Version}\n' | LC_ALL=C sort > /usr/share/pasturestack/ubuntu-security-packages.tsv; \ + . /licenses/ubuntu-apt.lock; \ + { printf 'snapshot\t%s\n' "${UBUNTU_APT_SNAPSHOT}"; dpkg-query -W -f='${binary:Package}\t${Version}\n' | LC_ALL=C sort; } \ + > /licenses/IPSEC-VXLAN-OVERLAY-RUNTIME-UBUNTU-APT-PACKAGES.tsv; \ + rm -f /var/cache/ldconfig/aux-cache + ENTRYPOINT ["/pasturestack-entrypoint.sh"] CMD ["start.sh"] From 0c8ab954730c0e8c40b37621fbaee9ffaf780996 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Sun, 25 Oct 2026 06:57:05 +0800 Subject: [PATCH 2/2] Align runtime README for v0.14.41 README only. Preserve runtime and verification source exactly from 146002c029d3aa3c4d09bb0ada346abc40b04811. Describe the release version without obsolete candidate or previous-release notes. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 308b687..b5fd8a3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # PastureStack IPsec/VXLAN Overlay Network -Linux candidate **`v0.14.41`** integrates shared Ubuntu 26.04 security backports for already-installed packages while preserving the selected coreutils provider. It is unpublished; the last published Linux release is [v0.14.40](https://github.com/PastureStack/ipsec-vxlan-overlay-network/releases/tag/v0.14.40). +Linux runtime **`v0.14.41`** integrates shared Ubuntu 26.04 security backports for already-installed packages while preserving the selected coreutils provider. -Build and image examples below target the candidate. Publication requires completed bundle provenance and the normal final-image release gates. The image retains bundle manifests, source inputs and install/verify receipts under `/usr/share/pasturestack/security/ubuntu-backports/`. +The image retains bundle manifests, source inputs and installation receipts under `/usr/share/pasturestack/security/ubuntu-backports/`. This repository provides the privileged network data plane used by PastureStack. It contains IPsec and VXLAN overlay processes, connectivity checks, CNI runtime assets, and an audit-only topology planner. @@ -10,7 +10,7 @@ PastureStack is an independent community effort to preserve, audit, and moderniz ## Release status -After publication, select `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.41` through the infrastructure +Select `ghcr.io/pasturestack/ipsec-vxlan-overlay-network:v0.14.41` through the infrastructure Catalog. Security and CodeQL checks, the release scan and immutable publication must pass first. Image publication, Catalog selection and managed-host acceptance are separate.