From 7c2d558a35e5a2ed4a3761e7286e2262af149813 Mon Sep 17 00:00:00 2001 From: Mathias Beaulieu-Duncan Date: Mon, 2 Feb 2026 10:29:27 -0500 Subject: [PATCH] Replace cosign with docker buildx for SBOM and provenance attestations Cosign keyless mode requires OIDC browser auth which is not viable in CI. Switch all three pipelines to use apko build + docker buildx with --sbom=true and --provenance=mode=max for automatic attestation. Co-Authored-By: Claude Opus 4.5 --- .gitea/workflows/publish.yaml | 83 +++++++-------------------- .gitea/workflows/rebuild.yaml | 90 +++++++----------------------- .gitea/workflows/update-check.yaml | 82 +++++++-------------------- 3 files changed, 63 insertions(+), 192 deletions(-) diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml index 905d800..b603561 100644 --- a/.gitea/workflows/publish.yaml +++ b/.gitea/workflows/publish.yaml @@ -52,13 +52,8 @@ jobs: tar xzf /tmp/apko.tar.gz --strip-components=1 -C /usr/local/bin rm /tmp/apko.tar.gz - - name: Install cosign - run: | - COSIGN_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') - COSIGN_VERSION=$(curl -fsSL "https://api.github.com/repos/sigstore/cosign/releases/latest" | jq -r '.tag_name') - curl -fsSL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-${COSIGN_ARCH}" \ - -o /usr/local/bin/cosign - chmod +x /usr/local/bin/cosign + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Login to Docker Registry uses: docker/login-action@v3 @@ -95,7 +90,6 @@ jobs: echo "upstream=${UPSTREAM}" >> "$GITHUB_OUTPUT" echo "Upstream version for ${VARIANT}: ${UPSTREAM}" - # Query DockerHub for existing tags to determine build increment REPO_NAME="${{ env.IMAGE_NAME }}" REGISTRY_URL="${{ secrets.REGISTRY_URL }}" NAMESPACE=$(echo "$REGISTRY_URL" | sed 's|.*://||; s|.*\.io/||; s|/$||') @@ -116,60 +110,25 @@ jobs: echo "version_tag=${VERSION_TAG}" >> "$GITHUB_OUTPUT" echo "Next version tag: ${VERSION_TAG}" - - name: Build and push image - id: publish + - name: Build apko image tarball run: | - IMAGE_LATEST=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-${{ steps.tag.outputs.suffix }} - IMAGE_VERSIONED=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - mkdir -p /tmp/sbom - apko publish ${{ matrix.config }} \ - --sbom-path /tmp/sbom \ - --image-refs /tmp/image-refs.txt \ - "${IMAGE_LATEST}" \ - "${IMAGE_VERSIONED}" - echo "image_ref=${IMAGE_LATEST}" >> "$GITHUB_OUTPUT" - echo "image_versioned=${IMAGE_VERSIONED}" >> "$GITHUB_OUTPUT" - DIGEST=$(head -1 /tmp/image-refs.txt | sed 's/.*@//') - echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" + apko build ${{ matrix.config }} \ + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-${{ steps.tag.outputs.suffix }} \ + /tmp/image.tar + echo 'FROM scratch' > /tmp/Dockerfile + echo 'ADD image.tar /' >> /tmp/Dockerfile - - name: Attach SBOM attestation - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - SBOM_FILE=$(ls /tmp/sbom/*.spdx.json 2>/dev/null | head -1) - if [ -n "$SBOM_FILE" ]; then - cosign attach sbom --sbom "${SBOM_FILE}" "${IMAGE_DIGEST}" - echo "SBOM attached successfully" - else - echo "No SBOM file found, skipping" - fi - - - name: Generate and attach provenance - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - jq -n \ - --arg builder "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --arg buildType "https://apko.dev/build/v1" \ - --arg uri "${{ github.server_url }}/${{ github.repository }}" \ - --arg sha1 "${{ github.sha }}" \ - --arg entry "${{ matrix.config }}" \ - --arg runId "${{ github.run_id }}" \ - '{ - "builder": {"id": $builder}, - "buildType": $buildType, - "invocation": { - "configSource": {"uri": $uri, "digest": {"sha1": $sha1}, "entryPoint": $entry} - }, - "metadata": { - "buildInvocationID": $runId, - "completeness": {"parameters": true, "environment": true, "materials": true} - } - }' > /tmp/provenance.json - cosign attest --predicate /tmp/provenance.json --type slsaprovenance "${IMAGE_DIGEST}" - echo "Provenance attestation attached successfully" + - name: Build and push with buildx (SBOM + provenance) + uses: docker/build-push-action@v5 + with: + context: /tmp + file: /tmp/Dockerfile + push: true + sbom: true + provenance: mode=max + tags: | + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-${{ steps.tag.outputs.suffix }} + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - name: Install Docker Scout run: | @@ -178,5 +137,5 @@ jobs: - name: Docker Scout CVE Scan run: | - docker pull ${{ steps.publish.outputs.image_ref }} - docker scout cves ${{ steps.publish.outputs.image_ref }} --only-severity critical,high + docker pull ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-${{ steps.tag.outputs.suffix }} + docker scout cves ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-${{ steps.tag.outputs.suffix }} --only-severity critical,high diff --git a/.gitea/workflows/rebuild.yaml b/.gitea/workflows/rebuild.yaml index f22cf36..dc7852c 100644 --- a/.gitea/workflows/rebuild.yaml +++ b/.gitea/workflows/rebuild.yaml @@ -44,13 +44,8 @@ jobs: tar xzf /tmp/apko.tar.gz --strip-components=1 -C /usr/local/bin rm /tmp/apko.tar.gz - - name: Install cosign - run: | - COSIGN_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') - COSIGN_VERSION=$(curl -fsSL "https://api.github.com/repos/sigstore/cosign/releases/latest" | jq -r '.tag_name') - curl -fsSL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-${COSIGN_ARCH}" \ - -o /usr/local/bin/cosign - chmod +x /usr/local/bin/cosign + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Login to Docker Registry uses: docker/login-action@v3 @@ -65,24 +60,20 @@ jobs: case "$VARIANT" in base|build) - # Use Wolfi glibc version as base version UPSTREAM=$(apko resolve ${{ matrix.config }} 2>&1 | grep -oP 'glibc-\K[0-9]+\.[0-9]+' | head -1 || echo "0.0") if [ "$UPSTREAM" = "" ] || [ "$UPSTREAM" = "0.0" ]; then UPSTREAM=$(apko resolve ${{ matrix.config }} 2>&1 | grep -oP 'glibc \(\K[0-9]+\.[0-9]+' | head -1 || echo "2.42") fi ;; dotnet-runtime) - # Use latest .NET runtime version UPSTREAM=$(curl -fsSL "https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json" \ | jq -r '[."releases-index"[] | select(."support-phase" == "active" or ."support-phase" == "go-live") | ."latest-runtime"] | sort_by(. | split(".") | map(tonumber)) | last') ;; dotnet-sdk) - # Use latest .NET SDK version UPSTREAM=$(curl -fsSL "https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json" \ | jq -r '[."releases-index"[] | select(."support-phase" == "active" or ."support-phase" == "go-live") | ."latest-sdk"] | sort_by(. | split(".") | map(tonumber)) | last') ;; flutter-sdk) - # Use latest Flutter stable version UPSTREAM=$(curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" \ | jq -r '.current_release.stable as $hash | .releases[] | select(.hash == $hash and .channel == "stable") | .version') ;; @@ -91,17 +82,13 @@ jobs: echo "upstream=${UPSTREAM}" >> "$GITHUB_OUTPUT" echo "Upstream version for ${VARIANT}: ${UPSTREAM}" - # Query DockerHub for existing tags to determine build increment REPO_NAME="${{ env.IMAGE_NAME }}" REGISTRY_URL="${{ secrets.REGISTRY_URL }}" - # Extract namespace/repo from registry URL (e.g. docker.io/svrnty -> svrnty) NAMESPACE=$(echo "$REGISTRY_URL" | sed 's|.*://||; s|.*\.io/||; s|/$||') - # Query DockerHub API for tags matching this variant and version EXISTING_TAGS=$(curl -s "https://hub.docker.com/v2/repositories/${NAMESPACE}/${REPO_NAME}/tags?page_size=100&name=${VARIANT}-${UPSTREAM}." \ | jq -r '.results[]?.name // empty' 2>/dev/null || echo "") - # Find highest build number MAX_BUILD=0 for tag in $EXISTING_TAGS; do BUILD_NUM=$(echo "$tag" | grep -oP "\.\K[0-9]+$" || echo "0") @@ -115,60 +102,25 @@ jobs: echo "version_tag=${VERSION_TAG}" >> "$GITHUB_OUTPUT" echo "Next version tag: ${VERSION_TAG}" - - name: Rebuild and push with latest Wolfi packages - id: publish + - name: Build apko image tarball run: | - IMAGE_LATEST=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest - IMAGE_VERSIONED=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - mkdir -p /tmp/sbom - apko publish ${{ matrix.config }} \ - --sbom-path /tmp/sbom \ - --image-refs /tmp/image-refs.txt \ - "${IMAGE_LATEST}" \ - "${IMAGE_VERSIONED}" - echo "image_ref=${IMAGE_LATEST}" >> "$GITHUB_OUTPUT" - echo "image_versioned=${IMAGE_VERSIONED}" >> "$GITHUB_OUTPUT" - DIGEST=$(head -1 /tmp/image-refs.txt | sed 's/.*@//') - echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" + apko build ${{ matrix.config }} \ + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest \ + /tmp/image.tar + echo 'FROM scratch' > /tmp/Dockerfile + echo 'ADD image.tar /' >> /tmp/Dockerfile - - name: Attach SBOM attestation - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - SBOM_FILE=$(ls /tmp/sbom/*.spdx.json 2>/dev/null | head -1) - if [ -n "$SBOM_FILE" ]; then - cosign attach sbom --sbom "${SBOM_FILE}" "${IMAGE_DIGEST}" - echo "SBOM attached successfully" - else - echo "No SBOM file found, skipping" - fi - - - name: Generate and attach provenance - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - jq -n \ - --arg builder "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --arg buildType "https://apko.dev/build/v1" \ - --arg uri "${{ github.server_url }}/${{ github.repository }}" \ - --arg sha1 "${{ github.sha }}" \ - --arg entry "${{ matrix.config }}" \ - --arg runId "${{ github.run_id }}" \ - '{ - "builder": {"id": $builder}, - "buildType": $buildType, - "invocation": { - "configSource": {"uri": $uri, "digest": {"sha1": $sha1}, "entryPoint": $entry} - }, - "metadata": { - "buildInvocationID": $runId, - "completeness": {"parameters": true, "environment": true, "materials": true} - } - }' > /tmp/provenance.json - cosign attest --predicate /tmp/provenance.json --type slsaprovenance "${IMAGE_DIGEST}" - echo "Provenance attestation attached successfully" + - name: Build and push with buildx (SBOM + provenance) + uses: docker/build-push-action@v5 + with: + context: /tmp + file: /tmp/Dockerfile + push: true + sbom: true + provenance: mode=max + tags: | + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - name: Install Docker Scout run: | @@ -177,5 +129,5 @@ jobs: - name: Docker Scout CVE Scan run: | - docker pull ${{ steps.publish.outputs.image_ref }} - docker scout cves ${{ steps.publish.outputs.image_ref }} --only-severity critical,high + docker pull ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest + docker scout cves ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest --only-severity critical,high diff --git a/.gitea/workflows/update-check.yaml b/.gitea/workflows/update-check.yaml index be0105f..1d13d78 100644 --- a/.gitea/workflows/update-check.yaml +++ b/.gitea/workflows/update-check.yaml @@ -134,13 +134,8 @@ jobs: tar xzf /tmp/apko.tar.gz --strip-components=1 -C /usr/local/bin rm /tmp/apko.tar.gz - - name: Install cosign - run: | - COSIGN_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') - COSIGN_VERSION=$(curl -fsSL "https://api.github.com/repos/sigstore/cosign/releases/latest" | jq -r '.tag_name') - curl -fsSL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-${COSIGN_ARCH}" \ - -o /usr/local/bin/cosign - chmod +x /usr/local/bin/cosign + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Login to Docker Registry uses: docker/login-action@v3 @@ -197,60 +192,25 @@ jobs: echo "version_tag=${VERSION_TAG}" >> "$GITHUB_OUTPUT" echo "Next version tag: ${VERSION_TAG}" - - name: Build and push image - id: publish + - name: Build apko image tarball run: | - IMAGE_LATEST=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest - IMAGE_VERSIONED=${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - mkdir -p /tmp/sbom - apko publish ${{ matrix.config }} \ - --sbom-path /tmp/sbom \ - --image-refs /tmp/image-refs.txt \ - "${IMAGE_LATEST}" \ - "${IMAGE_VERSIONED}" - echo "image_ref=${IMAGE_LATEST}" >> "$GITHUB_OUTPUT" - echo "image_versioned=${IMAGE_VERSIONED}" >> "$GITHUB_OUTPUT" - DIGEST=$(head -1 /tmp/image-refs.txt | sed 's/.*@//') - echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT" + apko build ${{ matrix.config }} \ + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest \ + /tmp/image.tar + echo 'FROM scratch' > /tmp/Dockerfile + echo 'ADD image.tar /' >> /tmp/Dockerfile - - name: Attach SBOM attestation - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - SBOM_FILE=$(ls /tmp/sbom/*.spdx.json 2>/dev/null | head -1) - if [ -n "$SBOM_FILE" ]; then - cosign attach sbom --sbom "${SBOM_FILE}" "${IMAGE_DIGEST}" - echo "SBOM attached successfully" - else - echo "No SBOM file found, skipping" - fi - - - name: Generate and attach provenance - env: - COSIGN_YES: "true" - run: | - IMAGE_DIGEST="${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}@${{ steps.publish.outputs.digest }}" - jq -n \ - --arg builder "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --arg buildType "https://apko.dev/build/v1" \ - --arg uri "${{ github.server_url }}/${{ github.repository }}" \ - --arg sha1 "${{ github.sha }}" \ - --arg entry "${{ matrix.config }}" \ - --arg runId "${{ github.run_id }}" \ - '{ - "builder": {"id": $builder}, - "buildType": $buildType, - "invocation": { - "configSource": {"uri": $uri, "digest": {"sha1": $sha1}, "entryPoint": $entry} - }, - "metadata": { - "buildInvocationID": $runId, - "completeness": {"parameters": true, "environment": true, "materials": true} - } - }' > /tmp/provenance.json - cosign attest --predicate /tmp/provenance.json --type slsaprovenance "${IMAGE_DIGEST}" - echo "Provenance attestation attached successfully" + - name: Build and push with buildx (SBOM + provenance) + uses: docker/build-push-action@v5 + with: + context: /tmp + file: /tmp/Dockerfile + push: true + sbom: true + provenance: mode=max + tags: | + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest + ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }} - name: Install Docker Scout run: | @@ -259,8 +219,8 @@ jobs: - name: Docker Scout CVE Scan run: | - docker pull ${{ steps.publish.outputs.image_ref }} - docker scout cves ${{ steps.publish.outputs.image_ref }} --only-severity critical,high + docker pull ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest + docker scout cves ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest --only-severity critical,high notify-flutter: name: Create release for new Flutter version