Skip to content

Commit

Permalink
Merge pull request #14323 from smartcontractkit/hotfix/add-keyless-co…
Browse files Browse the repository at this point in the history
…sign-build-publish

Add OIDC keyless cosign for docker build and goreleaser build
  • Loading branch information
momentmaker authored Sep 3, 2024
2 parents fe86959 + 5dee0ec commit 0359573
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 107 deletions.
92 changes: 25 additions & 67 deletions .github/actions/build-sign-publish-chainlink/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,11 @@ inputs:
description: When set to the string boolean value of "true", the resulting build image will be signed
default: "false"
required: false
cosign-private-key:
description: The private key to be used with cosign to sign the image
required: false
cosign-public-key:
description: The public key to be used with cosign for verification
required: false
cosign-password:
description: The password to decrypt the cosign private key needed to sign the image
required: false
sign-method:
description: Build image will be signed using keypair or keyless methods
default: "keypair"
required: true
verify-signature:
description: When set to the string boolean value of "true", the resulting build image signature will be verified
default: "false"
required: false

outputs:
docker-image-tag:
description: The docker image tag that was built and pushed
Expand All @@ -84,6 +72,8 @@ runs:
# See https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings
run: |
SHARED_IMAGES=${{ inputs.ecr-hostname }}/${{ inputs.ecr-image-name }}
OIDC_ISSUER=https://token.actions.githubusercontent.com
OIDC_IDENTITY=https://github.com/smartcontractkit/chainlink/.github/workflows/build-publish.yml@${{ github.ref }}
SHARED_TAG_LIST=$(cat << EOF
type=ref,event=branch,suffix=${{ inputs.ecr-tag-suffix }}
Expand All @@ -101,6 +91,9 @@ runs:
echo "$SHARED_IMAGES" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
echo "oidc-issuer=${OIDC_ISSUER}" >> $GITHUB_ENV
echo "oidc-identity=${OIDC_IDENTITY}" >> $GITHUB_ENV
echo "shared-tag-list<<EOF" >> $GITHUB_ENV
echo "$SHARED_TAG_LIST" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
Expand Down Expand Up @@ -171,7 +164,9 @@ runs:
run: |
IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-root.outputs.metadata)['image.name'] }}
IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1)
IMAGE_DIGEST=${{ fromJSON(steps.buildpush-root.outputs.metadata)['containerimage.digest'] }}
echo "root_image_name=${IMAGE_NAME}" >> $GITHUB_ENV
echo "root_image_digest=${IMAGE_DIGEST}" >> $GITHUB_ENV
- name: Generate docker metadata for non-root image
id: meta-nonroot
Expand Down Expand Up @@ -217,6 +212,7 @@ runs:
IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1)
IMAGE_TAG=$(echo "$IMAGES_NAME_RAW" | cut -d":" -f2)
echo "nonroot_image_name=${IMAGE_NAME}" >> $GITHUB_ENV
echo "nonroot_image_digest=${IMAGE_DIGEST}" >> $GITHUB_ENV
echo '### Docker Image' >> $GITHUB_STEP_SUMMARY
echo "Image Name: ${IMAGE_NAME}" >> $GITHUB_STEP_SUMMARY
echo "Image Digest: ${IMAGE_DIGEST}" >> $GITHUB_STEP_SUMMARY
Expand All @@ -239,74 +235,36 @@ runs:
- if: inputs.sign-images == 'true'
name: Install cosign
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
with:
cosign-release: "v1.6.0"
cosign-release: "v2.4.0"

- if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair'
name: Sign the published root Docker image using keypair method
shell: sh
env:
COSIGN_PASSWORD: "${{ inputs.cosign-password }}"
run: |
echo "${{ inputs.cosign-private-key }}" > cosign.key
cosign sign --key cosign.key "${{ env.root_image_name }}"
rm -f cosign.key
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair'
name: Verify the signature of the published root Docker image using keypair
shell: sh
run: |
echo "${{ inputs.cosign-public-key }}" > cosign.key
cosign verify --key cosign.key "${{ env.root_image_name }}"
rm -f cosign.key
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless'
# This automatically signs the image with the correct OIDC provider from Github
- if: inputs.sign-images == 'true'
name: Sign the published root Docker image using keyless method
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign sign "${{ env.root_image_name }}"
cosign sign "${{ env.root_image_name }}" --yes
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless'
- if: inputs.verify-signature == 'true'
name: Verify the signature of the published root Docker image using keyless
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign verify "${{ env.root_image_name }}"
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keypair'
name: Sign the published non-root Docker image using keypair method
shell: sh
env:
COSIGN_PASSWORD: "${{ inputs.cosign-password }}"
run: |
echo "${{ inputs.cosign-private-key }}" > cosign.key
cosign sign --key cosign.key "${{ env.nonroot_image_name }}"
rm -f cosign.key
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keypair'
name: Verify the signature of the published non-root Docker image using keypair
shell: sh
run: |
echo "${{ inputs.cosign-public-key }}" > cosign.key
cosign verify --key cosign.key "${{ env.nonroot_image_name }}"
rm -f cosign.key
cosign verify "${{ env.root_image_name }}" \
--certificate-oidc-issuer ${{ env.oidc-issuer }} \
--certificate-identity "${{ env.oidc-identity }}"
- if: inputs.sign-images == 'true' && inputs.sign-method == 'keyless'
# This automatically signs the image with the correct OIDC provider from Github
- if: inputs.sign-images == 'true'
name: Sign the published non-root Docker image using keyless method
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign sign "${{ env.nonroot_image_name }}"
cosign sign "${{ env.nonroot_image_name }}" --yes
- if: inputs.verify-signature == 'true' && inputs.sign-method == 'keyless'
- if: inputs.verify-signature == 'true'
name: Verify the signature of the published non-root Docker image using keyless
shell: sh
env:
COSIGN_EXPERIMENTAL: 1
run: |
cosign verify "${{ env.nonroot_image_name }}"
cosign verify "${{ env.nonroot_image_name }}" \
--certificate-oidc-issuer ${{ env.oidc-issuer }} \
--certificate-identity "${{ env.oidc-identity }}"
19 changes: 4 additions & 15 deletions .github/actions/goreleaser-build-sign-publish/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ inputs:
required: false
cosign-version:
description: The cosign version
default: v2.2.2
default: v2.4.0
required: false
macos-sdk-dir:
description: The macos sdk directory
Expand Down Expand Up @@ -62,15 +62,6 @@ inputs:
description: Enable signing of docker images
default: "false"
required: false
cosign-private-key:
description: The private key to be used with cosign to sign the image
required: false
cosign-public-key:
description: The public key to be used with cosign for verification
required: false
cosign-password:
description: The password to decrypt the cosign private key needed to sign the image
required: false
runs:
using: composite
steps:
Expand All @@ -96,7 +87,7 @@ runs:
version: ${{ inputs.zig-version }}
- name: Setup cosign
if: inputs.enable-cosign == 'true'
uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
with:
cosign-release: ${{ inputs.cosign-version }}
- name: Login to docker registry
Expand All @@ -113,7 +104,6 @@ runs:
- name: Run goreleaser release
shell: bash
env:
ENABLE_COSIGN: ${{ inputs.enable-cosign }}
ENABLE_GORELEASER_SNAPSHOT: ${{ inputs.enable-goreleaser-snapshot }}
ENABLE_GORELEASER_SPLIT: ${{ inputs.enable-goreleaser-split }}
ENABLE_DOCKER_PUBLISH: ${{ inputs.enable-docker-publish }}
Expand All @@ -122,9 +112,8 @@ runs:
IMAGE_TAG: ${{ inputs.docker-image-tag }}
GORELEASER_EXEC: ${{ inputs.goreleaser-exec }}
GORELEASER_CONFIG: ${{ inputs.goreleaser-config }}
COSIGN_PASSWORD: ${{ inputs.cosign-password }}
COSIGN_PUBLIC_KEY: ${{ inputs.cosign-public-key }}
COSIGN_PRIVATE_KEY: ${{ inputs.cosign-private-key }}
GORELEASER_KEY: ${{ inputs.goreleaser-key }}
GITHUB_TOKEN: ${{ github.token }}
MACOS_SDK_DIR: ${{ inputs.macos-sdk-dir }}
run: |
# https://github.com/orgs/community/discussions/24950
Expand Down
14 changes: 1 addition & 13 deletions .github/actions/goreleaser-build-sign-publish/action_utils
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
set -x
set -euo pipefail

ENABLE_COSIGN=${ENABLE_COSIGN:-false}
ENABLE_GORELEASER_SNAPSHOT=${ENABLE_GORELEASER_SNAPSHOT:-false}
ENABLE_GORELEASER_SPLIT=${ENABLE_GORELEASER_SPLIT:-false}
ENABLE_DOCKER_PUBLISH=${ENABLE_DOCKER_PUBLISH:-false}
COSIGN_PASSWORD=${COSIGN_PASSWORD:-""}
GORELEASER_EXEC=${GORELEASER_EXEC:-goreleaser}
GORELEASER_CONFIG=${GORELEASER_CONFIG:-.goreleaser.yaml}
IMAGE_PREFIX=${IMAGE_PREFIX:-"localhost:5001"}
Expand Down Expand Up @@ -69,26 +67,16 @@ goreleaser_release() {
flags=$(printf "%s " "${goreleaser_flags[@]}")
flags=$(echo "$flags" | sed 's/ *$//')

if [[ $ENABLE_COSIGN == "true" ]]; then
echo "$COSIGN_PUBLIC_KEY" > cosign.pub
echo "$COSIGN_PRIVATE_KEY" > cosign.key
fi

if [[ -n $MACOS_SDK_DIR ]]; then
MACOS_SDK_DIR=$(echo "$(cd "$(dirname "$MACOS_SDK_DIR")" || exit; pwd)/$(basename "$MACOS_SDK_DIR")")
fi

$GORELEASER_EXEC release ${flags} --config "$GORELEASER_CONFIG" "$@"

if [[ $ENABLE_DOCKER_PUBLISH == "true" ]]; then
if [[ $ENABLE_DOCKER_PUBLISH == "true" ]] && [[ $ENABLE_GORELEASER_SNAPSHOT == "true" ]]; then
_publish_snapshot_images
_publish_snapshot_manifests
fi

if [[ $ENABLE_COSIGN == "true" ]]; then
rm -rf cosign.pub
rm -rf cosign.key
fi
}

"$@"
14 changes: 3 additions & 11 deletions .github/workflows/build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,9 @@ jobs:
aws-region: ${{ secrets.AWS_REGION }}
ecr-hostname: ${{ env.ECR_HOSTNAME }}
ecr-image-name: ${{ env.ECR_IMAGE_NAME }}
sign-images: true
sign-method: "keypair"
cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }}
cosign-public-key: ${{ secrets.COSIGN_PUBLIC_KEY }}
cosign-password: ${{ secrets.COSIGN_PASSWORD }}
dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }}
dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }}
sign-images: true
verify-signature: true

- name: Collect Metrics
Expand Down Expand Up @@ -97,19 +93,15 @@ jobs:
id: goreleaser-build-sign-publish
uses: ./.github/actions/goreleaser-build-sign-publish
with:
enable-docker-publish: "true"
docker-registry: ${{ env.ECR_HOSTNAME}}
docker-image-name: ${{ env.ECR_IMAGE_NAME }}
docker-image-tag: ${{ github.ref_name }}
goreleaser-exec: ./tools/bin/goreleaser_wrapper
goreleaser-config: .goreleaser.develop.yaml
goreleaser-key: ${{ secrets.GORELEASER_KEY }}
zig-version: 0.11.0
enable-cosign: "true"
cosign-version: 3.4.0
cosign-password: ${{ secrets.COSIGN_PASSWORD }}
cosign-public-key: ${{ secrets.COSIGN_PUBLIC_KEY }}
cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }}
enable-cosign: true
cosign-version: "v2.4.0"

- name: Output image name and digest
shell: sh
Expand Down
9 changes: 8 additions & 1 deletion .goreleaser.develop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,10 @@ docker_manifests:
# See https://goreleaser.com/customization/docker_sign/
docker_signs:
- artifacts: all
stdin: "{{ .Env.COSIGN_PASSWORD }}"
args:
- "sign"
- "${artifact}"
- "--yes"

checksum:
name_template: "checksums.txt"
Expand All @@ -203,6 +206,10 @@ snapshot:
partial:
by: target

# See https://goreleaser.com/customization/release/
release:
disable: true

changelog:
sort: asc
filters:
Expand Down

0 comments on commit 0359573

Please sign in to comment.