Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3ab1ab6

Browse files
committed
chore: add GitHub Actions attestations for SLSA provenance on Docker images
This adds GitHub Actions attestations to both CI and release workflows,providing SLSA provenance verification for all Docker images built in thepipeline. This complements our existing cosign SBOM attestations to improveour software supply chain security posture.- Add attestations:write permission to both workflows- Add SLSA provenance attestation for all Docker image tags- Include error handling to make attestation failures non-blocking- Add detailed comments explaining the attestation strategyChange-Id: I06761204cdcd31a0a648acfd057bcd45f55bdc9cSigned-off-by: Thomas Kosiewski <tk@coder.com>
1 parentb84ddea commit3ab1ab6

File tree

2 files changed

+290
-0
lines changed

2 files changed

+290
-0
lines changed

‎.github/workflows/ci.yaml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,10 @@ jobs:
10251025
packages:write
10261026
# Necessary for GCP authentication (https://github.com/google-github-actions/setup-gcloud#usage)
10271027
# Also necessary for keyless cosign (https://docs.sigstore.dev/cosign/signing/overview/)
1028+
# And for GitHub Actions attestation
10281029
id-token:write
1030+
# Required for GitHub Actions attestation
1031+
attestations:write
10291032
env:
10301033
DOCKER_CLI_EXPERIMENTAL:"enabled"
10311034
outputs:
@@ -1181,6 +1184,138 @@ jobs:
11811184
done
11821185
fi
11831186
1187+
# GitHub attestation provides SLSA provenance for the Docker images, establishing a verifiable
1188+
# record that these images were built in GitHub Actions with specific inputs and environment.
1189+
# This complements our existing cosign attestations which focus on SBOMs.
1190+
#
1191+
# We attest each tag separately to ensure all tags have proper provenance records.
1192+
# TODO: Consider refactoring these steps to use a matrix strategy or composite action to reduce duplication
1193+
# while maintaining the required functionality for each tag.
1194+
-name:GitHub Attestation for Docker image
1195+
id:attest_main
1196+
if:github.ref == 'refs/heads/main'
1197+
continue-on-error:true
1198+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
1199+
with:
1200+
subject-name:"ghcr.io/coder/coder-preview:main"
1201+
predicate-type:"https://slsa.dev/provenance/v1"
1202+
predicate:|
1203+
{
1204+
"buildType": "https://github.com/actions/runner-images/",
1205+
"builder": {
1206+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
1207+
},
1208+
"invocation": {
1209+
"configSource": {
1210+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
1211+
"digest": {
1212+
"sha1": "${{ github.sha }}"
1213+
},
1214+
"entryPoint": ".github/workflows/ci.yaml"
1215+
},
1216+
"environment": {
1217+
"github_workflow": "${{ github.workflow }}",
1218+
"github_run_id": "${{ github.run_id }}"
1219+
}
1220+
},
1221+
"metadata": {
1222+
"buildInvocationID": "${{ github.run_id }}",
1223+
"completeness": {
1224+
"environment": true,
1225+
"materials":true
1226+
}
1227+
}
1228+
}
1229+
push-to-registry:true
1230+
1231+
-name:GitHub Attestation for Docker image (latest tag)
1232+
id:attest_latest
1233+
if:github.ref == 'refs/heads/main'
1234+
continue-on-error:true
1235+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
1236+
with:
1237+
subject-name:"ghcr.io/coder/coder-preview:latest"
1238+
predicate-type:"https://slsa.dev/provenance/v1"
1239+
predicate:|
1240+
{
1241+
"buildType": "https://github.com/actions/runner-images/",
1242+
"builder": {
1243+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
1244+
},
1245+
"invocation": {
1246+
"configSource": {
1247+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
1248+
"digest": {
1249+
"sha1": "${{ github.sha }}"
1250+
},
1251+
"entryPoint": ".github/workflows/ci.yaml"
1252+
},
1253+
"environment": {
1254+
"github_workflow": "${{ github.workflow }}",
1255+
"github_run_id": "${{ github.run_id }}"
1256+
}
1257+
},
1258+
"metadata": {
1259+
"buildInvocationID": "${{ github.run_id }}",
1260+
"completeness": {
1261+
"environment": true,
1262+
"materials":true
1263+
}
1264+
}
1265+
}
1266+
push-to-registry:true
1267+
1268+
-name:GitHub Attestation for version-specific Docker image
1269+
id:attest_version
1270+
if:github.ref == 'refs/heads/main'
1271+
continue-on-error:true
1272+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
1273+
with:
1274+
subject-name:"ghcr.io/coder/coder-preview:${{ steps.build-docker.outputs.tag }}"
1275+
predicate-type:"https://slsa.dev/provenance/v1"
1276+
predicate:|
1277+
{
1278+
"buildType": "https://github.com/actions/runner-images/",
1279+
"builder": {
1280+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
1281+
},
1282+
"invocation": {
1283+
"configSource": {
1284+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
1285+
"digest": {
1286+
"sha1": "${{ github.sha }}"
1287+
},
1288+
"entryPoint": ".github/workflows/ci.yaml"
1289+
},
1290+
"environment": {
1291+
"github_workflow": "${{ github.workflow }}",
1292+
"github_run_id": "${{ github.run_id }}"
1293+
}
1294+
},
1295+
"metadata": {
1296+
"buildInvocationID": "${{ github.run_id }}",
1297+
"completeness": {
1298+
"environment": true,
1299+
"materials":true
1300+
}
1301+
}
1302+
}
1303+
push-to-registry:true
1304+
1305+
# Report attestation failures but don't fail the workflow
1306+
-name:Check attestation status
1307+
if:github.ref == 'refs/heads/main'
1308+
run:|
1309+
if [[ "${{ steps.attest_main.outcome }}" == "failure" ]]; then
1310+
echo "::warning::GitHub attestation for main tag failed"
1311+
fi
1312+
if [[ "${{ steps.attest_latest.outcome }}" == "failure" ]]; then
1313+
echo "::warning::GitHub attestation for latest tag failed"
1314+
fi
1315+
if [[ "${{ steps.attest_version.outcome }}" == "failure" ]]; then
1316+
echo "::warning::GitHub attestation for version-specific tag failed"
1317+
fi
1318+
11841319
-name:Prune old images
11851320
if:github.ref == 'refs/heads/main'
11861321
uses:vlaurin/action-ghcr-prune@0cf7d39f88546edd31965acba78cdcb0be14d641# v0.6.0

‎.github/workflows/release.yaml

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ jobs:
123123
packages:write
124124
# Necessary for GCP authentication (https://github.com/google-github-actions/setup-gcloud#usage)
125125
# Also necessary for keyless cosign (https://docs.sigstore.dev/cosign/signing/overview/)
126+
# And for GitHub Actions attestation
126127
id-token:write
128+
# Required for GitHub Actions attestation
129+
attestations:write
127130
env:
128131
# Necessary for Docker manifest
129132
DOCKER_CLI_EXPERIMENTAL:"enabled"
@@ -409,7 +412,52 @@ jobs:
409412
echo "$manifests" | grep -q linux/arm64
410413
echo "$manifests" | grep -q linux/arm/v7
411414
415+
# GitHub attestation provides SLSA provenance for Docker images, establishing a verifiable
416+
# record that these images were built in GitHub Actions with specific inputs and environment.
417+
# This complements our existing cosign attestations (which focus on SBOMs) by adding
418+
# GitHub-specific build provenance to enhance our supply chain security.
419+
#
420+
# TODO: Consider refactoring these attestation steps to use a matrix strategy or composite action
421+
# to reduce duplication while maintaining the required functionality for each distinct image tag.
422+
-name:GitHub Attestation for Base Docker image
423+
id:attest_base
424+
if:${{ !inputs.dry_run && steps.image-base-tag.outputs.tag != '' }}
425+
continue-on-error:true
426+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
427+
with:
428+
subject-name:${{ steps.image-base-tag.outputs.tag }}
429+
predicate-type:"https://slsa.dev/provenance/v1"
430+
predicate:|
431+
{
432+
"buildType": "https://github.com/actions/runner-images/",
433+
"builder": {
434+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
435+
},
436+
"invocation": {
437+
"configSource": {
438+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
439+
"digest": {
440+
"sha1": "${{ github.sha }}"
441+
},
442+
"entryPoint": ".github/workflows/release.yaml"
443+
},
444+
"environment": {
445+
"github_workflow": "${{ github.workflow }}",
446+
"github_run_id": "${{ github.run_id }}"
447+
}
448+
},
449+
"metadata": {
450+
"buildInvocationID": "${{ github.run_id }}",
451+
"completeness": {
452+
"environment": true,
453+
"materials":true
454+
}
455+
}
456+
}
457+
push-to-registry:true
458+
412459
-name:Build Linux Docker images
460+
id:build_docker
413461
run:|
414462
set -euxo pipefail
415463
@@ -428,18 +476,125 @@ jobs:
428476
# being pushed so will automatically push them.
429477
make push/build/coder_"$version"_linux.tag
430478
479+
# Save multiarch image tag for attestation
480+
multiarch_image="$(./scripts/image_tag.sh)"
481+
echo "multiarch_image=${multiarch_image}" >> $GITHUB_OUTPUT
482+
483+
# For debugging, print all docker image tags
484+
docker images
485+
431486
# if the current version is equal to the highest (according to semver)
432487
# version in the repo, also create a multi-arch image as ":latest" and
433488
# push it
489+
created_latest_tag=false
434490
if [[ "$(git tag | grep '^v' | grep -vE '(rc|dev|-|\+|\/)' | sort -r --version-sort | head -n1)" == "v$(./scripts/version.sh)" ]]; then
435491
./scripts/build_docker_multiarch.sh \
436492
--push \
437493
--target "$(./scripts/image_tag.sh --version latest)" \
438494
$(cat build/coder_"$version"_linux_{amd64,arm64,armv7}.tag)
495+
created_latest_tag=true
496+
echo "created_latest_tag=true" >> $GITHUB_OUTPUT
497+
else
498+
echo "created_latest_tag=false" >> $GITHUB_OUTPUT
439499
fi
440500
env:
441501
CODER_BASE_IMAGE_TAG:${{ steps.image-base-tag.outputs.tag }}
442502

503+
-name:GitHub Attestation for Docker image
504+
id:attest_main
505+
if:${{ !inputs.dry_run }}
506+
continue-on-error:true
507+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
508+
with:
509+
subject-name:${{ steps.build_docker.outputs.multiarch_image }}
510+
predicate-type:"https://slsa.dev/provenance/v1"
511+
predicate:|
512+
{
513+
"buildType": "https://github.com/actions/runner-images/",
514+
"builder": {
515+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
516+
},
517+
"invocation": {
518+
"configSource": {
519+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
520+
"digest": {
521+
"sha1": "${{ github.sha }}"
522+
},
523+
"entryPoint": ".github/workflows/release.yaml"
524+
},
525+
"environment": {
526+
"github_workflow": "${{ github.workflow }}",
527+
"github_run_id": "${{ github.run_id }}"
528+
}
529+
},
530+
"metadata": {
531+
"buildInvocationID": "${{ github.run_id }}",
532+
"completeness": {
533+
"environment": true,
534+
"materials":true
535+
}
536+
}
537+
}
538+
push-to-registry:true
539+
540+
# Get the latest tag name for attestation
541+
-name:Get latest tag name
542+
id:latest_tag
543+
if:${{ !inputs.dry_run && steps.build_docker.outputs.created_latest_tag == 'true' }}
544+
run:echo "tag=$(./scripts/image_tag.sh --version latest)" >> $GITHUB_OUTPUT
545+
546+
# If this is the highest version according to semver, also attest the "latest" tag
547+
-name:GitHub Attestation for "latest" Docker image
548+
id:attest_latest
549+
if:${{ !inputs.dry_run && steps.build_docker.outputs.created_latest_tag == 'true' }}
550+
continue-on-error:true
551+
uses:actions/attest@a63cfcc7d1aab266ee064c58250cfc2c7d07bc31# v2.2.1
552+
with:
553+
subject-name:${{ steps.latest_tag.outputs.tag }}
554+
predicate-type:"https://slsa.dev/provenance/v1"
555+
predicate:|
556+
{
557+
"buildType": "https://github.com/actions/runner-images/",
558+
"builder": {
559+
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
560+
},
561+
"invocation": {
562+
"configSource": {
563+
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
564+
"digest": {
565+
"sha1": "${{ github.sha }}"
566+
},
567+
"entryPoint": ".github/workflows/release.yaml"
568+
},
569+
"environment": {
570+
"github_workflow": "${{ github.workflow }}",
571+
"github_run_id": "${{ github.run_id }}"
572+
}
573+
},
574+
"metadata": {
575+
"buildInvocationID": "${{ github.run_id }}",
576+
"completeness": {
577+
"environment": true,
578+
"materials":true
579+
}
580+
}
581+
}
582+
push-to-registry:true
583+
584+
# Report attestation failures but don't fail the workflow
585+
-name:Check attestation status
586+
if:${{ !inputs.dry_run }}
587+
run:|
588+
if [[ "${{ steps.attest_base.outcome }}" == "failure" && "${{ steps.attest_base.conclusion }}" != "skipped" ]]; then
589+
echo "::warning::GitHub attestation for base image failed"
590+
fi
591+
if [[ "${{ steps.attest_main.outcome }}" == "failure" ]]; then
592+
echo "::warning::GitHub attestation for main image failed"
593+
fi
594+
if [[ "${{ steps.attest_latest.outcome }}" == "failure" && "${{ steps.attest_latest.conclusion }}" != "skipped" ]]; then
595+
echo "::warning::GitHub attestation for latest image failed"
596+
fi
597+
443598
-name:Generate offline docs
444599
run:|
445600
version="$(./scripts/version.sh)"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp