chore(deps): Update testing-tools #1735
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| # KMS-backed bundle signing and verification e2e tests against MiniStack | |
| # (https://ministack.org), a token-free AWS emulator. Provisions an ephemeral | |
| # ECDSA P-256 asymmetric KMS key, builds the aicr binary, then runs the chainsaw | |
| # suite gated by --selector 'requires=ministack'. No real AWS credentials are | |
| # needed: MiniStack accepts any values for AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. | |
| # | |
| # MiniStack replaces LocalStack here because LocalStack's latest/stable images | |
| # now refuse to boot without a paid license token (exit code 55), which would | |
| # turn any image bump into a CI outage. The MiniStack image is pinned in | |
| # .settings.yaml (testing_tools.ministack_image) and resolved via load-versions, | |
| # so it is never floated to :latest. The emulator runs as a plain `docker run` | |
| # step (not a services: container) because a service container starts before any | |
| # step and therefore cannot reference the load-versions step output. | |
| name: KMS MiniStack E2E | |
| on: | |
| workflow_dispatch: {} | |
| push: | |
| branches: | |
| - main | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| # Validate on PRs that touch the test, its workflow/tooling, or the signing | |
| # code under test. Gated to same-repo in the job `if` below: fork PRs lack the | |
| # OIDC token needed to attest the binary, so they skip rather than fail. | |
| pull_request: | |
| branches: | |
| - main | |
| paths: | |
| - 'tests/chainsaw/signing/bundle-attestation-kms-ministack/**' | |
| - '.github/workflows/kms-ministack-e2e.yaml' | |
| - '.github/actions/load-versions/**' | |
| - '.github/actions/generate-slsa-predicate/**' | |
| - '.github/actions/setup-build-tools/**' | |
| - '.settings.yaml' | |
| - '.goreleaser.yaml' | |
| - 'pkg/bundler/**' | |
| # The keyless/trust-root verification path imports pkg/trust directly. | |
| - 'pkg/trust/**' | |
| # The `bundle --signing-key`, `verify --key`, and identity-regexp plumbing | |
| # under test lives in pkg/cli; cmd/aicr is the thin entrypoint. go.mod/sum | |
| # cover dependency bumps (e.g. sigstore) that change the signing path. | |
| - 'pkg/cli/**' | |
| - 'cmd/aicr/**' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - 'vendor/**' | |
| # Least privilege at the workflow level; id-token is granted only to the job | |
| # that needs it (below). | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| AWS_ACCESS_KEY_ID: test | |
| AWS_SECRET_ACCESS_KEY: test | |
| AWS_DEFAULT_REGION: us-east-1 | |
| # HTTPS: sigstore's awskms client hardcodes https://, so MiniStack runs with | |
| # USE_SSL=1 and a mkcert cert the Go AWS SDK trusts (AWS_CA_BUNDLE for the CLI). | |
| MINISTACK_ENDPOINT: https://localhost:4566 | |
| MINISTACK_CERT_DIR: /tmp/ministack-tls | |
| jobs: | |
| kms-ministack-e2e: | |
| name: KMS MiniStack E2E | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| # id-token: write mints the GitHub OIDC token for Sigstore keyless signing. | |
| # The "Build aicr binary" step runs goreleaser, whose cosign attest-blob hook | |
| # uses that identity to produce the binary's SLSA provenance (fed by | |
| # "Generate SLSA predicate" and checked by --min-trust-level verified). | |
| permissions: | |
| contents: read | |
| id-token: write | |
| # Skip on fork PRs: they get a read-only token, so `cosign attest-blob` | |
| # (binary attestation) cannot run. push/workflow_dispatch always run. | |
| if: >- | |
| github.event_name != 'pull_request' || | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Load versions | |
| id: versions | |
| uses: ./.github/actions/load-versions | |
| - name: Setup Go | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: ${{ steps.versions.outputs.go }} | |
| cache: true | |
| - name: Install GoReleaser | |
| uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 | |
| with: | |
| version: ${{ steps.versions.outputs.goreleaser }} | |
| install-only: true | |
| - name: Install Chainsaw | |
| uses: ./.github/actions/setup-build-tools | |
| with: | |
| install_chainsaw: 'true' | |
| chainsaw_version: ${{ steps.versions.outputs.chainsaw }} | |
| chainsaw_sha256: ${{ steps.versions.outputs.chainsaw_sha256_linux_amd64 }} | |
| - name: Install Cosign | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| with: | |
| # Pin from .settings.yaml (>= v3.1.0) so cosign logs DSSE attestations | |
| # to Rekor v2 as hashedrekord/PAE. The installer default (v3.0.6) writes | |
| # the legacy dsse entry type, which sigstore-go cannot verify. See #1650. | |
| cosign-release: ${{ steps.versions.outputs.cosign }} | |
| - name: Generate SLSA predicate | |
| uses: ./.github/actions/generate-slsa-predicate | |
| with: | |
| workflow_file: kms-ministack-e2e.yaml | |
| - name: Install AWS CLI | |
| run: | | |
| set -euo pipefail | |
| python3 -m pip install --quiet "awscli==${{ steps.versions.outputs.awscli }}" | |
| - name: Install mkcert and provision TLS cert | |
| env: | |
| MKCERT_VERSION: ${{ steps.versions.outputs.mkcert }} | |
| MKCERT_SHA256: ${{ steps.versions.outputs.mkcert_sha256_linux_amd64 }} | |
| run: | | |
| set -euo pipefail | |
| # Pinned mkcert binary (GitHub release), checksum-verified before install. | |
| tmp="$(mktemp)" | |
| curl -fsSL -o "$tmp" \ | |
| "https://github.com/FiloSottile/mkcert/releases/download/${MKCERT_VERSION}/mkcert-${MKCERT_VERSION}-linux-amd64" | |
| echo "${MKCERT_SHA256} ${tmp}" | sha256sum -c - | |
| sudo install -m 0755 "$tmp" /usr/local/bin/mkcert | |
| rm -f "$tmp" | |
| # Install the mkcert CA into the runner trust store so the Go AWS SDK | |
| # trusts MiniStack's TLS. Ephemeral runner, so this is safe. | |
| mkcert -install | |
| mkdir -p "${MINISTACK_CERT_DIR}" | |
| mkcert -cert-file "${MINISTACK_CERT_DIR}/cert.pem" \ | |
| -key-file "${MINISTACK_CERT_DIR}/key.pem" \ | |
| localhost 127.0.0.1 ::1 | |
| chmod 644 "${MINISTACK_CERT_DIR}"/*.pem | |
| # The Python aws CLI uses its own bundle; point it at the mkcert root CA. | |
| echo "AWS_CA_BUNDLE=$(mkcert -CAROOT)/rootCA.pem" >> "$GITHUB_ENV" | |
| - name: Start MiniStack | |
| env: | |
| MINISTACK_IMAGE: ${{ steps.versions.outputs.ministack_image }} | |
| run: | | |
| set -euo pipefail | |
| # Token-free AWS emulator; image is pinned in .settings.yaml. USE_SSL=1 | |
| # serves TLS with the mounted mkcert cert (sigstore awskms needs https). | |
| docker run -d --name ministack -p 4566:4566 \ | |
| -e USE_SSL=1 \ | |
| -e MINISTACK_SSL_CERT=/certs/cert.pem \ | |
| -e MINISTACK_SSL_KEY=/certs/key.pem \ | |
| -v "${MINISTACK_CERT_DIR}:/certs:ro" \ | |
| "${MINISTACK_IMAGE}" >/dev/null | |
| # Wait for KMS to serve. AWS_MAX_ATTEMPTS=1 + short CLI timeouts keep each | |
| # probe fast while the endpoint is still coming up. | |
| for _ in $(seq 1 45); do | |
| if [ "$(docker inspect -f '{{.State.Running}}' ministack 2>/dev/null)" != "true" ]; then | |
| docker logs ministack 2>&1 | tail -20 | |
| echo "::error::MiniStack container exited unexpectedly" | |
| exit 1 | |
| fi | |
| if AWS_MAX_ATTEMPTS=1 aws kms list-keys \ | |
| --endpoint-url "${MINISTACK_ENDPOINT}" \ | |
| --cli-connect-timeout 3 --cli-read-timeout 5 \ | |
| --output text >/dev/null 2>&1; then | |
| echo "MiniStack KMS is ready" | |
| exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| docker logs ministack 2>&1 | tail -20 | |
| echo "::error::MiniStack did not become ready in time" | |
| exit 1 | |
| - name: Build aicr binary | |
| env: | |
| GOFLAGS: -mod=vendor | |
| run: | | |
| set -euo pipefail | |
| goreleaser build --clean --single-target --snapshot --timeout 10m | |
| - name: Locate binary and detect attestation | |
| run: | | |
| set -euo pipefail | |
| AICR_BIN="" | |
| for pattern in dist/aicr_linux_amd64_v1/aicr dist/aicr_linux_amd64/aicr; do | |
| if [ -x "$pattern" ]; then | |
| AICR_BIN="$(pwd)/$pattern" | |
| break | |
| fi | |
| done | |
| if [ -z "$AICR_BIN" ]; then | |
| echo "::error::Built binary not found in dist/" | |
| exit 1 | |
| fi | |
| echo "AICR_BIN=${AICR_BIN}" >> "$GITHUB_ENV" | |
| echo "Binary: ${AICR_BIN}" | |
| ATTEST_FILE="$(dirname "$AICR_BIN")/aicr-attestation.sigstore.json" | |
| if [ -f "$ATTEST_FILE" ]; then | |
| echo "AICR_ATTESTED=true" >> "$GITHUB_ENV" | |
| echo "AICR_IDENTITY_REGEXP=https://github.com/${{ github.repository }}/.github/workflows/kms-ministack-e2e\\.yaml@.*" >> "$GITHUB_ENV" | |
| echo "Binary attestation found: $ATTEST_FILE" | |
| else | |
| echo "AICR_ATTESTED=false" >> "$GITHUB_ENV" | |
| echo "::warning::No binary attestation found; verify-min-trust-verified step will be skipped" | |
| fi | |
| - name: Provision KMS key in MiniStack | |
| run: | | |
| set -euo pipefail | |
| # Create an ECDSA P-256 asymmetric signing key | |
| KMS_KEY_ARN=$(aws kms create-key \ | |
| --endpoint-url "${MINISTACK_ENDPOINT}" \ | |
| --key-spec ECC_NIST_P256 \ | |
| --key-usage SIGN_VERIFY \ | |
| --description "aicr-e2e-signing-key" \ | |
| --query 'KeyMetadata.Arn' \ | |
| --output text) | |
| echo "Provisioned KMS key ARN: ${KMS_KEY_ARN}" | |
| echo "KMS_KEY_ARN=${KMS_KEY_ARN}" >> "$GITHUB_ENV" | |
| # Derive the URI with the MiniStack endpoint embedded in the host portion. | |
| # Format: awskms://<host:port>/<arn> | |
| HOST="${MINISTACK_ENDPOINT#http://}" | |
| HOST="${HOST#https://}" | |
| HOST="${HOST%/}" | |
| KMS_URI="awskms://${HOST}/${KMS_KEY_ARN}" | |
| echo "KMS_URI=${KMS_URI}" >> "$GITHUB_ENV" | |
| echo "KMS URI: ${KMS_URI}" | |
| - name: Export public key to PEM | |
| run: | | |
| set -euo pipefail | |
| mkdir -p /tmp/kms-e2e | |
| aws kms get-public-key \ | |
| --endpoint-url "${MINISTACK_ENDPOINT}" \ | |
| --key-id "${KMS_KEY_ARN}" \ | |
| --query 'PublicKey' \ | |
| --output text | base64 -d | \ | |
| openssl pkey -pubin -inform DER -outform PEM \ | |
| -out /tmp/kms-e2e/signing-key.pem | |
| echo "KMS_PEM_FILE=/tmp/kms-e2e/signing-key.pem" >> "$GITHUB_ENV" | |
| echo "Public key exported to /tmp/kms-e2e/signing-key.pem" | |
| - name: Run KMS MiniStack chainsaw tests | |
| env: | |
| AICR_ATTESTED: ${{ env.AICR_ATTESTED }} | |
| AICR_IDENTITY_REGEXP: ${{ env.AICR_IDENTITY_REGEXP }} | |
| run: | | |
| set -euo pipefail | |
| chainsaw test \ | |
| --no-cluster \ | |
| --config tests/chainsaw/chainsaw-config.yaml \ | |
| --test-dir tests/chainsaw/signing/bundle-attestation-kms-ministack/ \ | |
| --selector 'requires=ministack' | |
| - name: Stop MiniStack | |
| if: always() | |
| run: docker rm -f ministack >/dev/null 2>&1 || true |