diff --git a/.github/workflows/publish-kyverno-migration-runtime.yaml b/.github/workflows/publish-kyverno-migration-runtime.yaml index 183bab655d..c3de89ea7d 100644 --- a/.github/workflows/publish-kyverno-migration-runtime.yaml +++ b/.github/workflows/publish-kyverno-migration-runtime.yaml @@ -65,6 +65,12 @@ jobs: git diff --check git add -- cmd/platform-migrate/main.go cmd/platform-migrate/main_test.go go.mod go.sum test "$(git write-tree)" = "${PATCHED_SOURCE_TREE}" + # Go stamps the main module version from a tag on a clean HEAD. Keep the source commit's date. + source_date="$(git log -1 --format=%cI)" + GIT_AUTHOR_DATE="${source_date}" GIT_COMMITTER_DATE="${source_date}" \ + git -c user.name=platform -c user.email=platform@devantler.tech commit --quiet --no-gpg-sign \ + --message "Apply reviewed migration runtime patch" + git tag v1.19.2 - name: Set up Buildx container driver uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0 @@ -129,6 +135,12 @@ jobs: git diff --check git add -- cmd/platform-migrate/main.go cmd/platform-migrate/main_test.go go.mod go.sum test "$(git write-tree)" = "${PATCHED_SOURCE_TREE}" + # Go stamps the main module version from a tag on a clean HEAD. Keep the source commit's date. + source_date="$(git log -1 --format=%cI)" + GIT_AUTHOR_DATE="${source_date}" GIT_COMMITTER_DATE="${source_date}" \ + git -c user.name=platform -c user.email=platform@devantler.tech commit --quiet --no-gpg-sign \ + --message "Apply reviewed migration runtime patch" + git tag v1.19.2 - name: Set up Buildx container driver uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0 diff --git a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile index 99489d772a..ec169fc6db 100644 --- a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile +++ b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile @@ -13,17 +13,32 @@ RUN GOBIN=/usr/local/bin go install github.com/golangci/golangci-lint/v2/cmd/gol && timeout 300s golangci-lint run --timeout=4m ./cmd/platform-migrate ./cmd/cli/kubectl-kyverno/commands/migrate ARG VERSION=development RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=readonly -trimpath \ - -ldflags="-s -w -X main.buildVersion=${VERSION}" \ + -ldflags="-X main.buildVersion=${VERSION}" \ -o /out/kubectl-kyverno ./cmd/platform-migrate \ && test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10" \ + && go version -m /out/kubectl-kyverno > /tmp/build-info \ + && grep -Eq '^[[:space:]]+mod[[:space:]]+github\.com/kyverno/kyverno[[:space:]]+v1\.19\.2[[:space:]]' /tmp/build-info \ + && grep -Eq '^[[:space:]]+build[[:space:]]+vcs\.modified=false$' /tmp/build-info \ + && go tool nm /out/kubectl-kyverno > /tmp/symbols \ + && grep -Eq '[[:space:]]T main\.main$' /tmp/symbols \ && test "$(/out/kubectl-kyverno --version)" = "kubectl-kyverno version ${VERSION}" \ && /out/kubectl-kyverno migrate --help \ && if /out/kubectl-kyverno apply --help > /tmp/unsupported-command 2>&1; then \ echo 'Unsupported CLI command exposed by migration runtime'; exit 1; \ else test "$?" -eq 1 && grep -F 'unknown command "apply"' /tmp/unsupported-command; fi +# Only these exact whole-module records for Kyverno v1.19.2 are accepted, with the same +# adjudication and removal as scripts/tests/tenant-webapp-admission/.govulncheck-allow.txt +# (platform#5154). The list must match exactly: another advisory fails the build, and so does +# an empty list, because that means the report was not read or the record needs removing here. RUN GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.8.0 \ && timeout 300s govulncheck ./cmd/platform-migrate \ - && timeout 120s govulncheck -mode=binary /out/kubectl-kyverno + && timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json \ + && grep -Eq '"scan_level": *"symbol"' /tmp/binary-scan.json \ + && timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json \ + && grep -Eq '"pkgSymbols": *\[[^]]+\]' /tmp/binary-extract.json \ + && grep -Eo '"osv": *"[^"]+"' /tmp/binary-scan.json | grep -Eo 'GO-[0-9]+-[0-9]+' | sort -u > /tmp/binary-findings \ + && cat /tmp/binary-findings \ + && test "$(tr '\n' ' ' < /tmp/binary-findings)" = 'GO-2025-3615 GO-2026-5337 GO-2026-5594 ' FROM reg.kyverno.io/kyverno/kyverno-cli:v1.19.2@sha256:322ec5044d600930cb3af0e56dc33154a2d1d1fba58f4cadad3f47be7e78b11c COPY --from=builder --chmod=0755 /out/kubectl-kyverno /ko-app/kubectl-kyverno diff --git a/scripts/tests/test-kyverno-migration-runtime.sh b/scripts/tests/test-kyverno-migration-runtime.sh index 1349ab46f0..69e9a24aba 100755 --- a/scripts/tests/test-kyverno-migration-runtime.sh +++ b/scripts/tests/test-kyverno-migration-runtime.sh @@ -31,6 +31,13 @@ for job in verify publish; do | map(select(. == "test \"$(git write-tree)\" = \"${PATCHED_SOURCE_TREE}\"")) | length) == 1)] | length == 1 ' "$workflow" >/dev/null || fail "exact source tree proof missing in $job" + # shellcheck disable=SC2016 + JOB="$job" yq -e ' + [.jobs[strenv(JOB)].steps[] | select(."working-directory" == "upstream") + | select((.run // "" | split("\n") + | map(select(. == "git tag v1.19.2")) + | length) == 1)] | length == 1 + ' "$workflow" >/dev/null || fail "release tag binding missing in $job" JOB="$job" yq -e '[.jobs[strenv(JOB)].steps[] | select(.with.repository == "kyverno/kyverno" and .with.ref == "e63308f1e16c05cd009ac4864be6ec25c66b49be" and .with."persist-credentials" == false)] | length == 1' "$workflow" >/dev/null || fail 'upstream checkout not exact' JOB="$job" yq -e '[.jobs[strenv(JOB)].steps[] | select(.with.file == "./k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile" and .with.provenance == "mode=max" and .with.sbom == true)] | length == 1' "$workflow" >/dev/null || fail 'tested build provenance missing' done @@ -48,12 +55,21 @@ grep -Fq "github.com/kyverno/kyverno/pkg/engine/|golang.org/x/crypto/openpgp|git grep -Fxq 'RUN timeout 300s go test -mod=readonly -race ./cmd/platform-migrate ./cmd/cli/kubectl-kyverno/commands/migrate' "$dockerfile" || fail 'released migration and actual TLS API regressions missing' grep -Fq 'go install golang.org/x/vuln/cmd/govulncheck@v1.8.0' "$dockerfile" || fail 'reviewed scanner missing' grep -Fq 'timeout 300s govulncheck ./cmd/platform-migrate' "$dockerfile" || fail 'source scan missing' -grep -Fq 'timeout 120s govulncheck -mode=binary /out/kubectl-kyverno' "$dockerfile" || fail 'compiled binary scan missing' +grep -Fq 'timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json' "$dockerfile" || fail 'compiled binary scan missing' +grep -Fq "grep -Eq '\"scan_level\": *\"symbol\"' /tmp/binary-scan.json" "$dockerfile" || fail 'symbol-level scan proof missing' +grep -Fq 'timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json' "$dockerfile" || fail 'symbol extraction proof missing' +grep -Fq "grep -Eq '\"pkgSymbols\": *\\[[^]]+\\]' /tmp/binary-extract.json" "$dockerfile" || fail 'non-empty symbol proof missing' +# shellcheck disable=SC2016 +grep -Fq "test \"\$(tr '\\n' ' ' < /tmp/binary-findings)\" = 'GO-2025-3615 GO-2026-5337 GO-2026-5594 '" "$dockerfile" || fail 'accepted advisories changed' # shellcheck disable=SC2016 grep -Fq 'test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10"' "$dockerfile" || fail 'actual compiler proof missing' # shellcheck disable=SC2016 grep -Fq 'test "$(/out/kubectl-kyverno --version)" = "kubectl-kyverno version ${VERSION}"' "$dockerfile" || fail 'actual immutable executable identity missing' grep -Fq 'unknown command "apply"' "$dockerfile" || fail 'unsupported-command refusal missing' +if grep -Eq -- '-ldflags="[^"]*-[sw][ "]' "$dockerfile"; then fail 'stripped symbols defeat the binary scan'; fi +grep -Fq 'github\.com/kyverno/kyverno[[:space:]]+v1\.19\.2[[:space:]]' "$dockerfile" || fail 'executable release identity proof missing' +grep -Fq 'vcs\.modified=false$' "$dockerfile" || fail 'clean source proof missing' +grep -Fq 'T main\.main$' "$dockerfile" || fail 'retained symbol proof missing' grep -Fxq 'FROM reg.kyverno.io/kyverno/kyverno-cli:v1.19.2@sha256:322ec5044d600930cb3af0e56dc33154a2d1d1fba58f4cadad3f47be7e78b11c' "$dockerfile" || fail 'runtime release pin changed' grep -Fxq 'USER 65534:65534' "$dockerfile" || fail 'migration Job execution identity changed' grep -Fxq 'RUN ["/ko-app/kubectl-kyverno", "migrate", "--help"]' "$dockerfile" || fail 'real non-root runtime check missing'