Skip to content

Commit 2d71c3f

Browse files
authored
Merge pull request #1 from testifysec/test-witness-build
Add Witness build workflow with Sigstore signing
2 parents 8000f0a + 3ecdcc4 commit 2d71c3f

File tree

1 file changed

+146
-24
lines changed

1 file changed

+146
-24
lines changed

.github/workflows/build-and-attest.yml

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ env:
1010
REGISTRY: ghcr.io
1111
IMAGE_NAME: ${{ github.repository }}
1212

13+
permissions:
14+
contents: read
15+
packages: write
16+
id-token: write # Required for Sigstore signing
17+
1318
jobs:
1419
build-and-push:
1520
runs-on: ubuntu-latest
16-
permissions:
17-
contents: read
18-
packages: write
19-
id-token: write # Required for Sigstore signing
2021

2122
steps:
2223
- name: Checkout repository
@@ -44,31 +45,152 @@ jobs:
4445
type=raw,value=latest,enable={{is_default_branch}}
4546
4647
- name: Build and push Docker image with Witness
47-
uses: testifysec/witness-run-action@v0.1.7
48+
uses: testifysec/witness-run-action@v0.3.0
4849
with:
4950
step: docker-build
50-
command: |
51-
docker buildx build \
52-
--push \
53-
--platform linux/amd64,linux/arm64 \
54-
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
55-
--tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
56-
--metadata-file docker-metadata.json \
57-
--provenance=true \
58-
--sbom=true \
59-
--cache-from type=gha \
60-
--cache-to type=gha,mode=max \
61-
.
51+
command: docker buildx build --push --platform linux/amd64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest --metadata-file docker-metadata.json --provenance=true --sbom=true --cache-from type=gha --cache-to type=gha,mode=max .
52+
attestations: docker slsa git github secretscan
53+
attestor-slsa-export: true
6254
enable-sigstore: true
6355
enable-archivista: true
6456

65-
- name: Generate attestation summary
57+
- name: Display attestation metadata
58+
id: attestation
59+
run: |
60+
echo "## Attestation Metadata" >> $GITHUB_STEP_SUMMARY
61+
echo "" >> $GITHUB_STEP_SUMMARY
62+
63+
# Parse docker metadata
64+
if [ -f docker-metadata.json ]; then
65+
echo "### 📦 Docker Build Output" >> $GITHUB_STEP_SUMMARY
66+
echo '```json' >> $GITHUB_STEP_SUMMARY
67+
jq '{"image": .["image.name"], "digest": .["containerimage.digest"], "size": .["containerimage.descriptor"].size}' docker-metadata.json >> $GITHUB_STEP_SUMMARY
68+
echo '```' >> $GITHUB_STEP_SUMMARY
69+
echo "" >> $GITHUB_STEP_SUMMARY
70+
71+
# Extract key metadata for easy reference
72+
IMAGE_DIGEST=$(jq -r '.["containerimage.digest"]' docker-metadata.json)
73+
echo "**Image Digest:** \`$IMAGE_DIGEST\`" >> $GITHUB_STEP_SUMMARY
74+
echo "" >> $GITHUB_STEP_SUMMARY
75+
fi
76+
77+
# SLSA metadata preview
78+
if [ -f slsa-predicate.json ]; then
79+
echo "### 🔐 SLSA Provenance Preview" >> $GITHUB_STEP_SUMMARY
80+
echo '```json' >> $GITHUB_STEP_SUMMARY
81+
jq '{buildType: .buildDefinition.buildType, builder: .runDetails.builder.id}' slsa-predicate.json >> $GITHUB_STEP_SUMMARY || echo "SLSA predicate will be generated"
82+
echo '```' >> $GITHUB_STEP_SUMMARY
83+
echo "" >> $GITHUB_STEP_SUMMARY
84+
fi
85+
86+
- name: Generate attestation summary and Archivista queries
6687
run: |
67-
echo "## Build Attestation Summary" >> $GITHUB_STEP_SUMMARY
88+
echo "## Witness Attestation Summary" >> $GITHUB_STEP_SUMMARY
89+
echo "" >> $GITHUB_STEP_SUMMARY
90+
echo "✅ **Provenance captured with Witness** - Complete build attestations generated" >> $GITHUB_STEP_SUMMARY
91+
echo "✅ **Uploaded to Archivista** - Attestations stored for verification and querying" >> $GITHUB_STEP_SUMMARY
92+
echo "" >> $GITHUB_STEP_SUMMARY
93+
echo "**Witness** captured attestations for: Git state, GitHub context, build commands, materials, products, Docker metadata, SLSA provenance, and secret scanning." >> $GITHUB_STEP_SUMMARY
94+
echo "" >> $GITHUB_STEP_SUMMARY
95+
echo "**Archivista** provides a GraphQL API to query and verify these attestations." >> $GITHUB_STEP_SUMMARY
96+
echo "" >> $GITHUB_STEP_SUMMARY
97+
98+
# Add Archivista GraphQL query examples
99+
echo "## Query Attestations in Archivista" >> $GITHUB_STEP_SUMMARY
100+
echo "" >> $GITHUB_STEP_SUMMARY
101+
echo "Use these GraphQL queries at [Archivista Query Explorer](https://archivista.testifysec.io/query)" >> $GITHUB_STEP_SUMMARY
102+
echo "" >> $GITHUB_STEP_SUMMARY
103+
echo "Click the links below to open pre-populated queries:" >> $GITHUB_STEP_SUMMARY
104+
echo "" >> $GITHUB_STEP_SUMMARY
105+
106+
echo "### 🔍 Get recent witness-demo attestations" >> $GITHUB_STEP_SUMMARY
107+
echo "[▶️ Run this query](https://archivista.testifysec.io/query?query=%7B%0A%20%20dsses(where%3A%20%7B%0A%20%20%20%20hasStatementWith%3A%20%7B%0A%20%20%20%20%20%20hasSubjectsWith%3A%20%7B%0A%20%20%20%20%20%20%20%20nameContains%3A%20%22ghcr.io%2Ftestifysec%2Fwitness-demo%22%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%2C%20first%3A%205)%20%7B%0A%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20gitoidSha256%0A%20%20%20%20%20%20%20%20payloadType%0A%20%20%20%20%20%20%20%20statement%20%7B%0A%20%20%20%20%20%20%20%20%20%20predicate%0A%20%20%20%20%20%20%20%20%20%20subjects%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)" >> $GITHUB_STEP_SUMMARY
108+
echo "" >> $GITHUB_STEP_SUMMARY
109+
echo '```graphql' >> $GITHUB_STEP_SUMMARY
110+
echo 'query {' >> $GITHUB_STEP_SUMMARY
111+
echo ' dsses(where: {' >> $GITHUB_STEP_SUMMARY
112+
echo ' hasStatementWith: {' >> $GITHUB_STEP_SUMMARY
113+
echo ' hasSubjectsWith: {' >> $GITHUB_STEP_SUMMARY
114+
echo ' nameContains: "ghcr.io/testifysec/witness-demo"' >> $GITHUB_STEP_SUMMARY
115+
echo ' }' >> $GITHUB_STEP_SUMMARY
116+
echo ' }' >> $GITHUB_STEP_SUMMARY
117+
echo ' }, first: 5) {' >> $GITHUB_STEP_SUMMARY
118+
echo ' edges {' >> $GITHUB_STEP_SUMMARY
119+
echo ' node {' >> $GITHUB_STEP_SUMMARY
120+
echo ' gitoidSha256' >> $GITHUB_STEP_SUMMARY
121+
echo ' payloadType' >> $GITHUB_STEP_SUMMARY
122+
echo ' statement {' >> $GITHUB_STEP_SUMMARY
123+
echo ' predicate' >> $GITHUB_STEP_SUMMARY
124+
echo ' subjects {' >> $GITHUB_STEP_SUMMARY
125+
echo ' edges {' >> $GITHUB_STEP_SUMMARY
126+
echo ' node {' >> $GITHUB_STEP_SUMMARY
127+
echo ' name' >> $GITHUB_STEP_SUMMARY
128+
echo ' }' >> $GITHUB_STEP_SUMMARY
129+
echo ' }' >> $GITHUB_STEP_SUMMARY
130+
echo ' }' >> $GITHUB_STEP_SUMMARY
131+
echo ' }' >> $GITHUB_STEP_SUMMARY
132+
echo ' }' >> $GITHUB_STEP_SUMMARY
133+
echo ' }' >> $GITHUB_STEP_SUMMARY
134+
echo ' }' >> $GITHUB_STEP_SUMMARY
135+
echo '}' >> $GITHUB_STEP_SUMMARY
136+
echo '```' >> $GITHUB_STEP_SUMMARY
137+
echo "" >> $GITHUB_STEP_SUMMARY
138+
139+
140+
echo "### 🔍 Find SLSA provenance attestations for witness-demo builds" >> $GITHUB_STEP_SUMMARY
141+
echo "[▶️ Run this query](https://archivista.testifysec.io/query?query=%7B%0A%20%20dsses(where%3A%20%7B%0A%20%20%20%20and%3A%20%5B%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20hasStatementWith%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20predicateHasPrefix%3A%20%22https%3A%2F%2Fslsa.dev%2Fprovenance%2F%22%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20hasStatementWith%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20hasSubjectsWith%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3A%20%22file%3Adocker-metadata.json%22%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%5D%0A%20%20%7D%2C%20first%3A%205)%20%7B%0A%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20gitoidSha256%0A%20%20%20%20%20%20%20%20statement%20%7B%0A%20%20%20%20%20%20%20%20%20%20predicate%0A%20%20%20%20%20%20%20%20%20%20subjects(first%3A%205)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)" >> $GITHUB_STEP_SUMMARY
68142
echo "" >> $GITHUB_STEP_SUMMARY
69-
echo "✅ Container image built and pushed to GHCR" >> $GITHUB_STEP_SUMMARY
70-
echo "✅ Provenance captured with Witness" >> $GITHUB_STEP_SUMMARY
71-
echo "✅ Signed with Sigstore" >> $GITHUB_STEP_SUMMARY
72-
echo "✅ Attestation uploaded to Archivista" >> $GITHUB_STEP_SUMMARY
143+
echo '```graphql' >> $GITHUB_STEP_SUMMARY
144+
echo 'query {' >> $GITHUB_STEP_SUMMARY
145+
echo ' dsses(where: {' >> $GITHUB_STEP_SUMMARY
146+
echo ' and: [' >> $GITHUB_STEP_SUMMARY
147+
echo ' {' >> $GITHUB_STEP_SUMMARY
148+
echo ' hasStatementWith: {' >> $GITHUB_STEP_SUMMARY
149+
echo ' predicateHasPrefix: "https://slsa.dev/provenance/"' >> $GITHUB_STEP_SUMMARY
150+
echo ' }' >> $GITHUB_STEP_SUMMARY
151+
echo ' },' >> $GITHUB_STEP_SUMMARY
152+
echo ' {' >> $GITHUB_STEP_SUMMARY
153+
echo ' hasStatementWith: {' >> $GITHUB_STEP_SUMMARY
154+
echo ' hasSubjectsWith: {' >> $GITHUB_STEP_SUMMARY
155+
echo ' name: "file:docker-metadata.json"' >> $GITHUB_STEP_SUMMARY
156+
echo ' }' >> $GITHUB_STEP_SUMMARY
157+
echo ' }' >> $GITHUB_STEP_SUMMARY
158+
echo ' }' >> $GITHUB_STEP_SUMMARY
159+
echo ' ]' >> $GITHUB_STEP_SUMMARY
160+
echo ' }, first: 5) {' >> $GITHUB_STEP_SUMMARY
161+
echo ' edges {' >> $GITHUB_STEP_SUMMARY
162+
echo ' node {' >> $GITHUB_STEP_SUMMARY
163+
echo ' gitoidSha256' >> $GITHUB_STEP_SUMMARY
164+
echo ' statement {' >> $GITHUB_STEP_SUMMARY
165+
echo ' predicate' >> $GITHUB_STEP_SUMMARY
166+
echo ' subjects(first: 5) {' >> $GITHUB_STEP_SUMMARY
167+
echo ' edges {' >> $GITHUB_STEP_SUMMARY
168+
echo ' node {' >> $GITHUB_STEP_SUMMARY
169+
echo ' name' >> $GITHUB_STEP_SUMMARY
170+
echo ' }' >> $GITHUB_STEP_SUMMARY
171+
echo ' }' >> $GITHUB_STEP_SUMMARY
172+
echo ' }' >> $GITHUB_STEP_SUMMARY
173+
echo ' }' >> $GITHUB_STEP_SUMMARY
174+
echo ' }' >> $GITHUB_STEP_SUMMARY
175+
echo ' }' >> $GITHUB_STEP_SUMMARY
176+
echo ' }' >> $GITHUB_STEP_SUMMARY
177+
echo '}' >> $GITHUB_STEP_SUMMARY
178+
echo '```' >> $GITHUB_STEP_SUMMARY
73179
echo "" >> $GITHUB_STEP_SUMMARY
74-
echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
180+
181+
echo "### 📊 Download and analyze attestation locally" >> $GITHUB_STEP_SUMMARY
182+
echo '```bash' >> $GITHUB_STEP_SUMMARY
183+
echo '# Download attestation by GitOID' >> $GITHUB_STEP_SUMMARY
184+
echo 'curl -s https://archivista.testifysec.io/download/<GITOID> -o attestation.json' >> $GITHUB_STEP_SUMMARY
185+
echo '' >> $GITHUB_STEP_SUMMARY
186+
echo '# Decode and explore the attestation' >> $GITHUB_STEP_SUMMARY
187+
echo 'jq -r ".payload" attestation.json | base64 -d | jq .' >> $GITHUB_STEP_SUMMARY
188+
echo '' >> $GITHUB_STEP_SUMMARY
189+
echo '# Extract specific attestation types' >> $GITHUB_STEP_SUMMARY
190+
echo 'jq -r ".payload" attestation.json | base64 -d | \' >> $GITHUB_STEP_SUMMARY
191+
echo ' jq ".predicate.attestations[] | select(.type == \"https://witness.dev/attestations/docker/v0.1\")"' >> $GITHUB_STEP_SUMMARY
192+
echo '' >> $GITHUB_STEP_SUMMARY
193+
echo '# Check GitHub actor from attestation' >> $GITHUB_STEP_SUMMARY
194+
echo 'jq -r ".payload" attestation.json | base64 -d | \' >> $GITHUB_STEP_SUMMARY
195+
echo ' jq ".predicate.attestations[] | select(.type == \"https://witness.dev/attestations/github/v0.1\") | .attestation.jwt.claims.actor"' >> $GITHUB_STEP_SUMMARY
196+
echo '```' >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)