Skip to content

Commit c5909d7

Browse files
authored
Merge pull request #31 from neuvector/cosign-image-manifests
ci: ensure all the images we built are signed with cosign
2 parents 564b616 + de5b905 commit c5909d7

1 file changed

Lines changed: 71 additions & 2 deletions

File tree

.github/workflows/container-build.yml

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ jobs:
2222
permissions:
2323
contents: read
2424
packages: write # Pushing images to ghcr.io
25+
id-token: write # Signing images with cosign
2526
runs-on: ${{ matrix.runner }}
2627
steps:
2728
- name: Checkout code
2829
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
30+
- name: Install cosign
31+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
2932
- name: Set up Docker Buildx
3033
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
3134
- name: Login to GitHub Container Registry
@@ -53,6 +56,28 @@ jobs:
5356
tags: ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}
5457
outputs: |
5558
type=image,push=true,push-by-digest=true,name-canonical=true
59+
60+
# We need to disable the new bundle format enabled by default since
61+
# cosign v3.x.x because some verification tools (e.g. slsactl, hauler and old
62+
# cosign) are not able to properly verify the signatures using this
63+
# new format
64+
- name: Sign container image with cosign v2 signature format
65+
run: |
66+
cosign sign --yes --new-bundle-format=false --use-signing-config=false \
67+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${{ steps.build-image.outputs.digest }}
68+
69+
- name: Sign container image with cosign v3 signature format
70+
run: |
71+
cosign sign --yes --new-bundle-format=true --use-signing-config=true \
72+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${{ steps.build-image.outputs.digest }}
73+
74+
- name: Verify container image signature
75+
run: |
76+
cosign verify \
77+
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
78+
--certificate-identity="https://github.com/${{github.repository_owner}}/runtime-enforcer/.github/workflows/container-build.yml@${{ github.ref }}" \
79+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${{ steps.build-image.outputs.digest }}
80+
5681
- name: Export digest
5782
run: |
5883
mkdir -p ${{ runner.temp }}/digests
@@ -70,6 +95,7 @@ jobs:
7095
needs: [build]
7196
permissions:
7297
packages: write # Pushing multi-arch manifest to ghcr.io
98+
id-token: write # Signing images with cosign
7399
strategy:
74100
matrix:
75101
component: [operator, daemon]
@@ -80,7 +106,8 @@ jobs:
80106
path: ${{ runner.temp }}/digests
81107
pattern: digest-${{ matrix.component }}-*
82108
merge-multiple: true
83-
109+
- name: Install cosign
110+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
84111
- name: Login to GHCR
85112
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
86113
with:
@@ -105,13 +132,55 @@ jobs:
105132
id: create-manifest
106133
working-directory: ${{ runner.temp }}/digests
107134
run: |
135+
set -e
108136
amd64_digest=$(cat ${{ matrix.component }}-amd64.txt)
109137
138+
# Create the manifest locally
139+
docker buildx imagetools create \
140+
-t ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}:${{ env.TAG_NAME }} \
141+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${amd64_digest} \
142+
--dry-run > expected-multi-arch-manifest.json
143+
144+
# Create the manifest and push it
110145
docker buildx imagetools create \
111146
-t ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}:${{ env.TAG_NAME }} \
112147
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${amd64_digest} \
113148
114-
docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}:${{ env.TAG_NAME }}
149+
# The previous command is NOT printing the digest of the multi-arch manifest, we have to obtain it by
150+
# fetching it from the OCI registry and **verify** its contents before signing it
151+
152+
# Fetch the multi arch manifest
153+
docker buildx imagetools inspect ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}:${{ env.TAG_NAME }} \
154+
--raw > multi-arch-manifest.json
155+
multi_arch_manifest_digest="sha256:$(sha256sum multi-arch-manifest.json | awk '{print $1}')"
156+
157+
# Compare the contents of the manifest we previously computed and the actual one.
158+
# Use jq to sort the contents and build a compact output (removing useless whitespaces),
159+
# this is done to ensure the JSON documents have the same structure.
160+
expected_digest="sha256:$(jq -S -c . expected-multi-arch-manifest.json | sha256sum | awk '{print $1}')"
161+
actual_digest="sha256:$(jq -S -c . multi-arch-manifest.json | sha256sum | awk '{print $1}')"
162+
163+
if [ "$expected_digest" != "$actual_digest" ]; then
164+
echo "Error: digests do not match!"
165+
exit 1
166+
fi
167+
168+
# Sign the multi-arch image manifest using cosign v2 format
169+
cosign sign --yes --new-bundle-format=false --use-signing-config=false \
170+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${multi_arch_manifest_digest}
171+
172+
# Sign the multi-arch image manifest using cosign v3 format
173+
cosign sign --yes --new-bundle-format=true --use-signing-config=true \
174+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${multi_arch_manifest_digest}
175+
176+
echo "MULTI_ARCH_MANIFEST_DIGEST=$multi_arch_manifest_digest" >> $GITHUB_ENV
177+
178+
- name: Verify multi-arch manifest signature
179+
run: |
180+
cosign verify \
181+
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
182+
--certificate-identity="https://github.com/${{github.repository_owner}}/runtime-enforcer/.github/workflows/container-build.yml@${{ github.ref }}" \
183+
ghcr.io/${{ github.repository_owner }}/runtime-enforcer/${{ matrix.component }}@${{ env.MULTI_ARCH_MANIFEST_DIGEST}}
115184
116185
attest:
117186
needs: [merge]

0 commit comments

Comments
 (0)