Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/scripts/collect-ubuntu-backport-evidence.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Only read the exact consumer and immutable bundle; execute its guard on the runner.
set -euo pipefail
test "$#" -eq 3
image=$1
sbom=$2
evidence=$3
bundle_image='ghcr.io/pasturestack/ubuntu-security-backports:v0.1.0@sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a'
bundle_digest=${bundle_image##*@}
[[ "$bundle_digest" =~ ^sha256:[0-9a-f]{64}$ ]]
test -s "$sbom"
mkdir -p "$evidence"
scratch=$(mktemp -d)
consumer=
bundle=
cleanup() {
if [[ -n "$consumer" ]]; then docker rm "$consumer" >/dev/null 2>&1 || true; fi
if [[ -n "$bundle" ]]; then docker rm "$bundle" >/dev/null 2>&1 || true; fi
rm -rf -- "$scratch"
}
trap cleanup EXIT
consumer=$(docker create --entrypoint /bin/true "$image")
docker cp "$consumer:/usr/share/pasturestack/security/ubuntu-backports/." "$evidence/"
docker rm "$consumer" >/dev/null
consumer=
bundle=$(docker create "$bundle_image" /artifact-export-only)
docker cp "$bundle:/out/verify-consumer-evidence.py" "$scratch/verify-consumer-evidence.py"
docker cp "$bundle:/out/SHA256SUMS" "$scratch/bundle-SHA256SUMS"
docker rm "$bundle" >/dev/null
bundle=
python3 -B "$scratch/verify-consumer-evidence.py" \
--evidence-dir "$evidence" --sbom "$sbom" \
--expected-bundle-digest "$bundle_digest" \
--bundle-checksums "$scratch/bundle-SHA256SUMS"
29 changes: 21 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,34 @@ jobs:
-v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image --scanners vuln,secret \
--exit-code 0 \
--format json --output /evidence/runtime-security-raw.json "$image"
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD/evidence:/evidence" \
-v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image --format cyclonedx \
--output /evidence/runtime.cdx.json "$image"
backports="$RUNNER_TEMP/pod-pause-image-ubuntu-backports"
bash .github/scripts/collect-ubuntu-backport-evidence.sh \
"$image" "evidence/runtime.cdx.json" "$backports" \
> "evidence/ubuntu-backports-verification.json"
tar -C "$backports" -czf "evidence/ubuntu-backports.tar.gz" .
docker run --rm -v "$backports:/backports:ro" \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD/evidence:/evidence" \
-v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image --vex /backports/openvex.json --skip-db-update --scanners vuln,secret \
--exit-code 0 \
--format json --output /evidence/runtime-security.json "$image"
jq -e '[.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL" or .Severity == "HIGH")] | length == 0' \
evidence/runtime-security.json >/dev/null
jq -e '[.Results[]?.Secrets[]?] | length == 0' evidence/runtime-security.json >/dev/null
python3 .github/scripts/enforce-runtime-vulnerabilities.py \
--phase release \
--repository "$GITHUB_REPOSITORY"
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "$PWD/evidence:/evidence" \
-v "$RUNNER_TEMP/trivy-cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image --format cyclonedx \
--output /evidence/runtime.cdx.json "$image"
jq -e '.bomFormat == "CycloneDX" and (.components | length > 0)' \
evidence/runtime.cdx.json >/dev/null
sha256sum evidence/runtime-security.json evidence/runtime.cdx.json \
sha256sum evidence/runtime-security-raw.json evidence/ubuntu-backports-verification.json evidence/ubuntu-backports.tar.gz evidence/runtime-security.json evidence/runtime.cdx.json \
> evidence/SHA256SUMS

- name: Publish immutable runtime image
Expand Down Expand Up @@ -131,7 +143,8 @@ jobs:
gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --verify-tag \
--title "Pod Pause Image $GITHUB_REF_NAME" \
--notes 'Pure numeric PastureStack pod-infrastructure image release with signal smoke tests, vulnerability scan, SBOM, checksums, and provenance.' \
evidence/runtime-security.json evidence/runtime.cdx.json evidence/SHA256SUMS
evidence/runtime-security-raw.json evidence/runtime-security.json evidence/runtime.cdx.json \
evidence/ubuntu-backports-verification.json evidence/ubuntu-backports.tar.gz evidence/SHA256SUMS

- name: Clean run-owned resources
if: always()
Expand Down
18 changes: 16 additions & 2 deletions .github/workflows/security-release-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,28 @@ jobs:
--volume "$PWD/evidence:/evidence" \
--volume "$trivy_cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image \
--format cyclonedx \
--output /evidence/image.cdx.json \
--scanners vuln \
--format json \
--output /evidence/image-vulnerabilities-raw.json \
"$CANDIDATE_IMAGE"
docker run --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$PWD/evidence:/evidence" \
--volume "$trivy_cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image \
--format cyclonedx \
--output /evidence/image.cdx.json \
"$CANDIDATE_IMAGE"
backports="$RUNNER_TEMP/pod-pause-image-ubuntu-backports"
bash .github/scripts/collect-ubuntu-backport-evidence.sh \
"$CANDIDATE_IMAGE" "evidence/image.cdx.json" "$backports" \
> "evidence/ubuntu-backports-verification.json"
tar -C "$backports" -czf "evidence/ubuntu-backports.tar.gz" .
docker run --rm -v "$backports:/backports:ro" \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$PWD/evidence:/evidence" \
--volume "$trivy_cache:/root/.cache/trivy" \
"$TRIVY_IMAGE" image --vex /backports/openvex.json --skip-db-update \
--scanners vuln \
--format json \
--output /evidence/image-vulnerabilities.json \
Expand Down
27 changes: 26 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# syntax=docker/dockerfile:1.7
ARG UBUNTU_IMAGE=ubuntu:26.04@sha256:2260313b31c8c011cd2eebe728008efac1b3982be73eb71348ea2648d2c0e09b

ARG UBUNTU_SECURITY_BACKPORTS_IMAGE=ghcr.io/pasturestack/ubuntu-security-backports:v0.1.0@sha256:2742a3d429e4e14bc587f6dedc51ded4246cf90bbaedcd86c67d0885e32a6f2a

FROM ${UBUNTU_IMAGE} AS snapshot-ca-bootstrap

ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd \
Expand Down Expand Up @@ -84,9 +87,12 @@ RUN gcc -O2 -Wall -Wextra -Werror -D_FORTIFY_SOURCE=3 -fstack-protector-strong -
-Wl,-z,relro -Wl,-z,now -Wl,--build-id=none -o /out-pause pause.c \
&& strip /out-pause

FROM ${UBUNTU_SECURITY_BACKPORTS_IMAGE} AS ubuntu_security_backports

FROM ${UBUNTU_IMAGE}
ARG UBUNTU_SECURITY_BACKPORTS_IMAGE

ARG IMAGE_VERSION=v3.0.5
ARG IMAGE_VERSION=v3.0.6
ARG SOURCE_REVISION=unknown
ARG UBUNTU_IMAGE

Expand Down Expand Up @@ -120,5 +126,24 @@ COPY --from=build /out-pause /pause
COPY --from=build /usr/share/pasturestack/manifests/ /usr/share/pasturestack/manifests/
COPY LICENSE /usr/share/licenses/pod-pause-image/LICENSE

# Keep the build-only installer and package archives outside the final image.
RUN --mount=type=bind,from=ubuntu_security_backports,source=/out,target=/opt/pasturestack/ubuntu-security-backports,readonly \
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 file in manifest.json qualification.json source-inputs.lock.json openvex.json; do \
cp "/opt/pasturestack/ubuntu-security-backports/$file" "$evidence/$file"; \
done; \
printf '%s\n' "$UBUNTU_SECURITY_BACKPORTS_IMAGE" > "$evidence/bundle-image.txt"; \
(cd "$evidence" && sha256sum manifest.json qualification.json source-inputs.lock.json openvex.json install.json verify.json bundle-image.txt > SHA256SUMS); \
{ \
printf 'record\tname\tarchitecture\tversion\n'; \
printf 'metadata\tschema\t-\tpasturestack.dpkg-manifest/v1\n'; \
printf 'metadata\tbase_image\t-\t%s\n' "$UBUNTU_IMAGE"; \
dpkg-query -W -f='package\t${binary:Package}\t${Architecture}\t${Version}\n' | LC_ALL=C sort; \
} > /usr/share/pasturestack/manifests/runtime-ubuntu-packages.tsv

USER 65532:65532
ENTRYPOINT ["/pause"]
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# PastureStack Pod Pause Image

Linux runtime **`v3.0.6`** consumes verified Ubuntu security backports without adding packages or changing the existing coreutils provider.

The runtime recipe applies the qualified Ubuntu 26.04 backport bundle only to already-installed packages and preserves the selected coreutils provider. The immutable bundle digest and final-image checks are pending. Bundle manifests, qualification, exact-version OpenVEX, source inputs and install/verify receipts are retained under `/usr/share/pasturestack/security/ubuntu-backports/`; raw scan evidence and the existing full-severity release policy remain required.

A small pod-infrastructure image that keeps a container alive, reaps orphaned child processes, and exits cleanly when it receives `SIGTERM` or `SIGINT`.

PastureStack is an independent community effort to preserve, audit, and modernize the Rancher 1.6 ecosystem. It is not affiliated with or endorsed by Rancher Labs or SUSE.
Expand All @@ -8,10 +12,10 @@ PastureStack is an independent community effort to preserve, audit, and moderniz

## Maintained image

The reviewed `linux/amd64` runtime uses the pure numeric coordinate:
After publication, the candidate `linux/amd64` runtime uses the pure numeric coordinate:

```text
ghcr.io/pasturestack/pod-pause-image:v3.0.5
ghcr.io/pasturestack/pod-pause-image:v3.0.6
```

Product identity and provenance are carried by the package name, OCI labels,
Expand All @@ -21,7 +25,7 @@ numeric successor after its release and integration gates pass.

## Build

Version 3.0.5 installs the SHA256-pinned official Ubuntu CA security update in
The recipe installs the SHA256-pinned official Ubuntu CA security update in
the build stage after the locked snapshot. Both stages apply the existing-package
security micro-updates in `ubuntu-security-packages.lock` from the signed
2026-10-23 Ubuntu 26.04 snapshot, without adding or removing packages. This
Expand All @@ -33,9 +37,9 @@ signal-handling, privilege or pod-sandbox behavior.

```sh
docker build --pull \
--build-arg IMAGE_VERSION=v3.0.5 \
--build-arg IMAGE_VERSION=v3.0.6 \
--build-arg SOURCE_REVISION="$(git rev-parse HEAD)" \
-t local/pasturestack/pod-pause-image:v3.0.5 .
-t local/pasturestack/pod-pause-image:v3.0.6 .
```

The runtime base is pinned to the reviewed Ubuntu 26.04 `linux/amd64` manifest. The build stage uses the HTTPS Ubuntu snapshot and exact direct-package versions recorded in [`ubuntu-apt.lock`](ubuntu-apt.lock). The final image carries the resolved builder toolchain, builder package, and runtime package manifests under `/usr/share/pasturestack/manifests/`; CI also records builder and runtime image inspections, CycloneDX SBOMs, vulnerability reports, and signal-handling smoke tests as a 30-day review artifact.
Expand All @@ -45,7 +49,7 @@ The release gate checks the complete runtime vulnerability report. Any available
## Smoke test

```sh
docker run -d --name pod-pause-poc local/pasturestack/pod-pause-image:v3.0.5
docker run -d --name pod-pause-poc local/pasturestack/pod-pause-image:v3.0.6
docker inspect --format '{{.State.Running}} {{.Config.User}}' pod-pause-poc
docker stop --time 5 pod-pause-poc
docker inspect --format '{{.State.ExitCode}}' pod-pause-poc
Expand Down
2 changes: 1 addition & 1 deletion scripts/validate
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ grep -F 'builder-ubuntu-packages.tsv' Dockerfile >/dev/null
grep -F 'builder-toolchain.tsv' Dockerfile >/dev/null
grep -F 'runtime-ubuntu-packages.tsv' Dockerfile >/dev/null
grep -F 'rm -f /usr/bin/pebble' Dockerfile >/dev/null
grep -F 'ARG IMAGE_VERSION=v3.0.5' Dockerfile >/dev/null
grep -F 'ARG IMAGE_VERSION=v3.0.6' Dockerfile >/dev/null
grep -F 'ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd' Dockerfile >/dev/null
grep -F 'https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb' Dockerfile >/dev/null
test "$(grep -Fc 'dpkg -i /tmp/ca-certificates.deb;' Dockerfile)" -eq 1
Expand Down
Loading