この記事は、3-shake Advent Calendar 2023 24日目のエントリ記事です。
Container image が適切な方法で build されたものかどうかを確認するために署名をするためのツールとして cosign があります。
キーペアを作成して秘密鍵で署名し、公開鍵で検証を行うことができるのですが、サポートされた OIDC の token issuer であれば keyless での署名が可能となっています。
private な container image などで署名する場合は transparency log の保存先や公開について検討が必要そうですが、ひとまず署名とその確認をやってみます。
sigstore/cosign-installer を使うと GitHub Actions の Job 内で簡単に cosign をインストールすることが可能です。使い方も README に書かれています。
Image の tag と digest が必要になるので docker/metadata-action と docker/build-push-action と一緒に使うのが便利です。
また、keyless のために OIDC の token を利用するためには permissions で id-token: write
が必要になります。
GitHub Actions で sign する
jobs:
build-and-push-image:
name: Build and push container image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # needed for signing the images with GitHub OIDC Token
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
yteraoka/example
ghcr.io/yteraoka/example
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
id: build-and-push
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Sign the published Docker image with GitHub OIDC Token
env:
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
検証する
cosign verify \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp ^https://github.com/yteraoka/example/ \
ghcr.io/yteraoka/example:0.0.1
--certificate-oidc-issuer
と --certificate-oidc-issuer-regexp
のどちらかと --certificate-identity
と --certificate-identity-regexp
のどちらかは指定が必須です。
identity の方は Subject として入っている https://github.com/yteraoka/example/.github/workflows/build-and-push.yaml@refs/tags/v0.0.1
のような値との比較になります。期待する build の手順を踏んでいるかどうかの確認ができます。
Kubernetes での検証
署名された Container image しか実行させないようにするためには AdmissionWebhook を使うことになるかと思います。
cosign と同じく sigstore の提供する policy-controller (heml chart)であったり connaisseur や kyverno などが候補でしょうか。