Attestation
各イメージには、ビルドの成果物についての検証可能な証拠が付属します。 この証拠を attestation と呼びます。 attestation は、OCI referrers としてイメージの digest に直接紐づく、署名済みのステートメントです。 そのため、イメージをどこへミラーしても、attestation は digest とのつながりを保ちます。
署名も同じ仕組みの一部です。 リリースのパイプラインが、GitHub Actions の OIDC で発行される短命の証明書を使い、公開 Sigstore に対して各イメージへ keyless 署名(keyless signing)を行います。 証明書は Fulcio が発行し、署名のイベントは公開の Rekor transparency log に記録されるため、長期の署名鍵を管理・配布する必要はありません。 この同じ keyless の identity が、SLSA Provenance、SBOM、VEX の3種類の attestation にも署名します。 署名は、multi-arch index の digest と、アーキテクチャごとの子 digest の両方に付きます。
署名の検証
署名を検証すると、そのイメージがどのビルドパイプラインの実行によって作られたかを確認できます。 署名は multi-arch index に付いているので、タグに対してそのまま検証でき、index の解決は cosign に任せられます。 次は busybox イメージで署名を検証し、署名対象の digest を表示する例です。
$ cosign verify \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github.com/flatt-security/takumi-images/.github/workflows/release.yml@.*' \
images.flatt.tech/takumi/busybox:latest \
2>/dev/null | jq -r '.[0].critical.image["docker-manifest-digest"]'
sha256:3a8d31becc2516f6fdf236964622d0d70c4b83843a91d370b6ea737a4735bd4b
identity には、ワークフローのパス(.../release.yml)を指定します。
この条件により、そのリリースワークフローが行った署名だけを受け入れます。
@.* は、リリースが実行された ref(ブランチでもタグでも)に一致させるためのものです。
ワークフローのパスまで固定しないと、別のワークフローや別のリポジトリで作られた署名まで受け入れる可能性があります。
attestation の検証
SLSA Provenance、SBOM、VEX も、同じ identity で検証します。
cosign verify-attestation に、種類ごとの predicate type(slsaprovenance1、cyclonedx、openvex)を指定します。
どの digest に対して検証するかは、添付先によって変わります。
SLSA Provenance と SBOM はアーキテクチャごとの子 digest に添付するので、まず index から子 digest を取り出し、その digest に対して検証します。
# index からアーキテクチャごとの子 digest を取り出す
$ crane manifest images.flatt.tech/takumi/busybox:latest \
| jq -r '.manifests[] | select(.platform.architecture=="amd64").digest'
sha256:7481eedfc1b6c70596d335f24665422438c17162e5cf97ee4584ae84b2629bf7
VEX はマルチアーキテクチャの index に添付するので、タグ(または index の digest)に対してそのまま検証します。
cosign verify-attestation \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'https://github.com/flatt-security/takumi-images/.github/workflows/release.yml@.*' \
--type openvex \
images.flatt.tech/takumi/busybox:latest \
| jq -r '.payload' | base64 -d | jq '.predicate'
各 attestation の中身や、アーキテクチャごとの子 digest の取り出し方は、SLSA Provenance、SBOM、VEX のページを参照してください。
3つの attestation
3 種類の attestation は、記録する内容も、紐づく対象も異なります。
| attestation | 形式(predicate type) | 記録する内容 | 紐づく対象 | 主な用途 |
|---|---|---|---|---|
| SLSA Provenance | in-toto / SLSA v1(slsaprovenance1) | ビルドに使ったソースリビジョンと、実行したワークフロー | アーキテクチャごとの子 digest | ビルドの出どころの検証、再現可能ビルドとの突き合わせ |
| SBOM | CycloneDX(cyclonedx) | ランタイム closure に含まれるコンポーネント一覧 | アーキテクチャごとの子 digest | 構成の把握、脆弱性スキャンの入力 |
| VEX | OpenVEX(openvex) | 検出結果ごとの not-affected / affected の判定と根拠 | マルチアーキテクチャの index | スキャン結果のトリアージ、誤検知の除外 |
SLSA Provenance と SBOM は、アーキテクチャごとに内容が変わるため、アーキテクチャごとの 子 digest に添付しています。 VEX は index 全体に対する判断を記録するため、index の digest に紐づけています。