Skip to content

Commit c521e03

Browse files
committed
feat: SLSA 3
Updates the CI to make policy server SLSA 3 complaint by providing the SBOM and provenance files. Signed-off-by: José Guilherme Vanz <jguilhermevanz@suse.com>
1 parent e7ca8f9 commit c521e03

10 files changed

+316
-224
lines changed

.github/workflows/attestation.yml

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: Sign attestation files
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
image-digest:
7+
type: string
8+
required: true
9+
10+
jobs:
11+
sbom:
12+
name: Fetch, sign and verify SBOM and provenance files
13+
strategy:
14+
matrix:
15+
arch: [amd64, arm64]
16+
17+
permissions:
18+
packages: write
19+
id-token: write
20+
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Install cosign
24+
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
25+
26+
- name: Install the crane command
27+
uses: kubewarden/github-actions/crane-installer@d94509d260ee11a92b4f65bc0acd297feec24d7f # v3.3.5
28+
29+
- name: Login to GitHub Container Registry
30+
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
31+
with:
32+
registry: ghcr.io
33+
username: ${{ github.repository_owner }}
34+
password: ${{ secrets.GITHUB_TOKEN }}
35+
36+
- name: Verify container image signature
37+
run: |
38+
cosign verify \
39+
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
40+
--certificate-identity="https://github.com/${{github.repository_owner}}/policy-server/.github/workflows/container-image.yml@${{ github.ref }}" \
41+
ghcr.io/${{ github.repository_owner }}/policy-server@${{ inputs.image-digest }}
42+
43+
- name: Find platform digest
44+
shell: bash
45+
run: |
46+
set -e
47+
DIGEST=$(crane digest \
48+
--platform "linux/${{ matrix.arch }}" \
49+
ghcr.io/${{ github.repository_owner }}/policy-server@${{ inputs.image-digest }})
50+
echo "PLATFORM_DIGEST=${DIGEST}" >> "$GITHUB_ENV"
51+
52+
- name: Find attestation digest
53+
run: |
54+
set -e
55+
DIGEST=$(crane manifest ghcr.io/${{github.repository_owner}}/policy-server@${{ inputs.image-digest }} \
56+
| jq '.manifests[] | select(.annotations["vnd.docker.reference.type"]=="attestation-manifest") | select(.annotations["vnd.docker.reference.digest"]=="${{ env.PLATFORM_DIGEST }}") | .digest'
57+
)
58+
echo "ATTESTATION_MANIFEST_DIGEST=${DIGEST}" >> "$GITHUB_ENV"
59+
60+
- name: Find provenance manifest digest
61+
run: |
62+
set -e
63+
DIGEST=$(crane manifest ghcr.io/${{github.repository_owner}}/policy-server@${{ env.ATTESTATION_MANIFEST_DIGEST}} | \
64+
jq '.layers[] | select(.annotations["in-toto.io/predicate-type"] == "https://slsa.dev/provenance/v0.2") | .digest')
65+
echo "PROVENANCE_DIGEST=${DIGEST}" >> "$GITHUB_ENV"
66+
67+
- name: Find SBOM manifest layers digest
68+
run: |
69+
set -e
70+
DIGEST=$(crane manifest ghcr.io/${{github.repository_owner}}/policy-server@${{ env.ATTESTATION_MANIFEST_DIGEST}} | \
71+
jq '.layers | map(select(.annotations["in-toto.io/predicate-type"] == "https://spdx.dev/Document")) | map(.digest) | join(" ")')
72+
echo "SBOM_DIGEST=${DIGEST}" >> "$GITHUB_ENV"
73+
74+
- name: Download provenance and SBOM files
75+
run: |
76+
set -e
77+
crane blob ghcr.io/${{github.repository_owner}}/policy-server@${{ env.PROVENANCE_DIGEST}} > policy-server-attestation-${{ matrix.arch }}-provenance.json
78+
sha256sum policy-server-attestation-${{ matrix.arch }}-provenance.json >> policy-server-attestation-${{ matrix.arch }}-checksum.txt
79+
80+
81+
for sbom_digest in "${{ env.SBOM_DIGEST }}"; do
82+
crane blob ghcr.io/${{github.repository_owner}}/policy-server@$sbom_digest > policy-server-attestation-${{ matrix.arch }}-sbom-${sbom_digest#"sha256:"}.json
83+
sha256sum policy-server-attestation-${{ matrix.arch }}-sbom-${sbom_digest#"sha256:"}.json >> policy-server-attestation-${{ matrix.arch }}-checksum.txt
84+
done
85+
86+
- name: Sign checksum file
87+
run: |
88+
cosign sign-blob --yes \
89+
--bundle policy-server-attestation-${{ matrix.arch }}-checksum-cosign.bundle \
90+
policy-server-attestation-${{ matrix.arch }}-checksum.txt
91+
92+
cosign verify-blob \
93+
--bundle policy-server-attestation-${{ matrix.arch }}-checksum-cosign.bundle \
94+
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
95+
--certificate-identity="https://github.com/${{github.repository_owner}}/policy-server/.github/workflows/attestation.yml@${{ github.ref }}" \
96+
policy-server-attestation-${{ matrix.arch }}-checksum.txt
97+
98+
- name: Upload SBOMs as artifacts
99+
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
100+
with:
101+
name: attestation-${{ matrix.arch }}
102+
path: policy-server-attestation-${{ matrix.arch }}*

.github/workflows/container-build.yml

+3-10
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,12 @@ jobs:
2020
uses: ./.github/workflows/container-image.yml
2121
permissions:
2222
packages: write
23-
24-
sign:
25-
needs: build
26-
uses: ./.github/workflows/sign-image.yml
27-
permissions:
28-
packages: write
2923
id-token: write
30-
with:
31-
image-digest: ${{ needs.build.outputs.digest }}
3224

3325
sbom:
34-
needs: build
35-
uses: ./.github/workflows/sbom.yml
26+
needs:
27+
- build
28+
uses: ./.github/workflows/attestation.yml
3629
permissions:
3730
packages: write
3831
id-token: write

.github/workflows/container-image.yml

+23-53
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,11 @@ on:
88
value: ${{ jobs.build.outputs.digest }}
99

1010
jobs:
11-
cross-build:
12-
name: Cross compile policy-server binary
13-
runs-on: ubuntu-latest
14-
15-
strategy:
16-
matrix:
17-
targetarch:
18-
- aarch64
19-
- x86_64
20-
21-
steps:
22-
- name: Checkout code
23-
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
24-
25-
- name: Setup rust toolchain
26-
uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # v1.0.7
27-
with:
28-
toolchain: stable
29-
target: ${{matrix.targetarch}}-unknown-linux-musl
30-
override: true
31-
32-
- uses: actions-rs/cargo@844f36862e911db73fe0815f00a4a2602c279505 # v1.0.3
33-
with:
34-
use-cross: true
35-
command: build
36-
args: --release --target ${{matrix.targetarch}}-unknown-linux-musl
37-
38-
- name: Upload policy-server binary
39-
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
40-
with:
41-
name: policy-server-${{ matrix.targetarch }}
42-
path: |
43-
target/${{ matrix.targetarch }}-unknown-linux-musl/release/policy-server
44-
4511
build:
4612
name: Build container image
4713
permissions:
4814
packages: write
49-
needs:
50-
- cross-build
15+
id-token: write
5116
runs-on: ubuntu-latest
5217
outputs:
5318
repository: ${{ steps.setoutput.outputs.repository }}
@@ -57,55 +22,60 @@ jobs:
5722
steps:
5823
- name: Checkout code
5924
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
25+
26+
- name: Install cosign
27+
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
28+
6029
- name: Set up QEMU
6130
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
31+
6232
- name: Set up Docker Buildx
6333
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
34+
6435
- name: Login to GitHub Container Registry
6536
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
6637
with:
6738
registry: ghcr.io
6839
username: ${{ github.repository_owner }}
6940
password: ${{ secrets.GITHUB_TOKEN }}
7041

71-
# Download the policy-server artifacts we've built inside of the previous job
72-
- name: Download policy-server-x86_64 artifact
73-
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
74-
with:
75-
name: policy-server-x86_64
76-
path: artifacts-x86_64
77-
- name: Download policy-server-aarch64 artifact
78-
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
79-
with:
80-
name: policy-server-aarch64
81-
path: artifacts-aarch64
82-
- name: Move binaries to project root
83-
run: |
84-
mv artifacts-x86_64/policy-server policy-server-x86_64
85-
mv artifacts-aarch64/policy-server policy-server-aarch64
86-
8742
- name: Retrieve tag name (main branch)
8843
if: ${{ startsWith(github.ref, 'refs/heads/main') }}
8944
run: |
9045
echo TAG_NAME=latest >> $GITHUB_ENV
46+
9147
- name: Retrieve tag name (feat branch)
9248
if: ${{ startsWith(github.ref, 'refs/heads/feat') }}
9349
run: |
9450
echo "TAG_NAME=latest-$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
51+
9552
- name: Retrieve tag name (tag)
9653
if: ${{ startsWith(github.ref, 'refs/tags/') }}
9754
run: |
9855
echo TAG_NAME=$(echo $GITHUB_REF | sed -e "s|refs/tags/||") >> $GITHUB_ENV
56+
9957
- name: Push and push container image
10058
id: build-image
10159
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
10260
with:
10361
context: .
104-
file: ./Dockerfile.github
62+
file: ./Dockerfile
10563
platforms: linux/amd64, linux/arm64
10664
push: true
65+
sbom: true
66+
provenance: mode=max
10767
tags: |
10868
ghcr.io/${{github.repository_owner}}/policy-server:${{ env.TAG_NAME }}
69+
70+
- name: Sign container image
71+
run: |
72+
cosign sign --yes ghcr.io/${{github.repository_owner}}/policy-server@${{ steps.build-image.outputs.digest }}
73+
74+
cosign verify \
75+
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
76+
--certificate-identity-regexp="https://github.com/${{github.repository_owner}}/policy-server/.github/workflows/container-image.yml@${{ github.ref }}" \
77+
ghcr.io/${{github.repository_owner}}/policy-server@${{ steps.build-image.outputs.digest }}
78+
10979
- id: setoutput
11080
name: Set output parameters
11181
run: |

.github/workflows/release.yml

+10-8
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,22 @@ jobs:
7474
- name: Checkout code for kubewarden-dashboard.json
7575
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
7676

77-
- name: Download SBOM artifact
77+
- name: Download attestation artifact
7878
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
7979
with:
80-
pattern: sbom-*
80+
pattern: attestation-*
8181
path: ./
8282
merge-multiple: true
8383

8484
- name: Display structure of downloaded files
8585
run: ls -R
8686

87+
- name: Create tarball for the attestation files
88+
run: |
89+
for arch in "amd64" "arm64"; do
90+
tar -czf attestation-$arch.tar.gz $(ls policy-server-attestation-$arch-*)
91+
done
92+
8793
- name: Upload release assets
8894
id: upload_release_assets
8995
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
@@ -93,12 +99,8 @@ jobs:
9399
let path = require('path');
94100
95101
let files = [
96-
'policy-server-sbom-amd64.spdx',
97-
'policy-server-sbom-amd64.spdx.cert',
98-
'policy-server-sbom-amd64.spdx.sig',
99-
'policy-server-sbom-arm64.spdx',
100-
'policy-server-sbom-arm64.spdx.cert',
101-
'policy-server-sbom-arm64.spdx.sig',
102+
'attestation-amd64.tar.gz',
103+
'attestation-arm64.tar.gz',
102104
'kubewarden-dashboard.json']
103105
const {RELEASE_ID} = process.env
104106

.github/workflows/sbom.yml

-87
This file was deleted.

0 commit comments

Comments
 (0)