キーレス署名と検証にはSigstoreを使用します。
Sigstoreプロジェクトは、GitLab CI/CDでビルドされたコンテナイメージのキーレス署名に使用できるCosignというCLIを提供しています。キーレス署名には、秘密鍵の管理、保護、ローテーションの必要性をなくすなど、多くの利点があります。Cosignは署名に使用する短命のキーペアを要求し、証明書の透明性ログに記録して破棄します。鍵は、パイプラインを実行したユーザーのOIDC IDを使用してGitLabサーバーから取得したトークンによって生成されます。このトークンには、トークンがCI/CDパイプラインによって生成されたことを証明する固有のクレームが含まれています。詳細については、キーレス署名に関するCosignのドキュメントを参照してください。
GitLab OIDC claim と Fulcio certificate extensions のマッピングの詳細については、Mapping OIDC token claims to Fulcio OIDs の GitLab コラムを参照してください。
要件
- GitLab.comを使用している必要があります。
- プロジェクトのCI/CD設定がプロジェクト内にあること。
Cosignを使用してコンテナイメージとビルドアーティファクトに署名または検証します。
Cosignを使用して、コンテナイメージとビルドアーティファクトに署名し、検証することができます。
要件
-
>= 2.0.1
のバージョンのCosignを使用する必要があります。
制限事項
- CI/CD設定ファイルの
id_tokens
部分は、ビルドと署名が行われるプロジェクトに配置する必要があります。AutoDevOps、別のリポジトリからインクルードされたCIファイル、および子パイプラインはサポートされていません。この制限を削除する作業は、イシュー411317 で追跡されています。
ベストプラクティス
- ベストプラクティス:イメージ/アーティファクトのビルドと署名は同じジョブで行い、署名前に改ざんされないようにします。
- コンテナイメージに署名する場合は、タグではなくダイジェスト(不変)に署名します。
GitLabID トークンは、キーレス署名のために Cosign で使用することができます。トークンはsigstore
をaud
クレームとして設定する必要があります。トークンがSIGSTORE_ID_TOKEN
環境変数に設定されている場合、Cosign は自動的にトークンを使用できます。
Cosignのインストール方法の詳細については、Cosignインストールドキュメントを参照してください。
署名
コンテナイメージ
以下の例は、GitLab CIでコンテナイメージに署名する方法を示しています。署名は自動的にイメージと同じコンテナリポジトリに保存されます。
コンテナへの署名の詳細については、Cosign Signing Containers ドキュメントを参照してください。
build_and_sign_image:
stage: build
image: docker:latest
services:
- docker:dind
variables:
COSIGN_YES: "true"
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
before_script:
- apk add --update cosign
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
- IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA)
- cosign sign $IMAGE_DIGEST
アーティファクトのビルド
以下の例は、GitLab CIでビルドアーティファクトに署名する方法を示しています。署名検証に使用されるcosign sign-blob
によって生成されたcosign.bundle
ファイルを保存してください。
アーティファクトへの署名の詳細については、Cosign Signing Blobs ドキュメントを参照してください。
build_and_sign_artifact:
stage: build
image: alpine:latest
variables:
COSIGN_YES: "true"
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
before_script:
- apk add --update cosign
script:
- echo "This is a build artifact" > artifact.txt
- cosign sign-blob artifact.txt --bundle cosign.bundle
artifacts:
paths:
- artifact.txt
- cosign.bundle
検証
コマンドライン引数
名前 | 値 |
---|---|
--certificate-identity | Fulcio が発行した署名証明書の SAN。イメージ/アーティファクトが署名されたプロジェクトの以下の情報を使って構築できます:GitLab インスタンス URL + プロジェクトパス +// + CI 設定パス +@ + 参照パス。 |
--certificate-oidc-issuer | イメージ/アーティファクトが署名された GitLab インスタンス URL。例えば、https://gitlab.com 。 |
--bundle |
cosign sign-blob が生成したbundle ファイル。ビルドアーティファクトの検証にのみ使われます。 |
署名されたイメージ/アーティファクトの検証の詳細については、Cosign Verifyingドキュメントを参照してください。
コンテナイメージ
以下の例は、GitLab CIで署名されたコンテナイメージを検証する方法を示しています。コマンドライン引数は上記の通りです。
verify_image:
image: alpine:3.18
stage: verify
before_script:
- apk add --update cosign docker
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- cosign verify "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" --certificate-identity "https://gitlab.com/my-group/my-project//path/to/.gitlab-ci.yml@refs/heads/main" --certificate-oidc-issuer "https://gitlab.com"
アーティファクトのビルド
以下の例は、GitLab CIで署名されたビルドアーティファクトを検証する方法を示しています。アーティファクトを検証するには、アーティファクト自身とcosign sign-blob
によって生成されたcosign.bundle
ファイルの両方が必要です。コマンドライン引数については前述のとおりです。
verify_artifact:
stage: verify
image: alpine:latest
before_script:
- apk add --update cosign
script:
- cosign verify-blob artifact.txt --bundle cosign.bundle --certificate-identity "https://gitlab.com/my-group/my-project//path/to/.gitlab-ci.yml@refs/heads/main" --certificate-oidc-issuer "https://gitlab.com"
Sigstoreとnpmを使用してキーレス実証を生成します。
SigstoreとnpmをGitLab CI/CDと併用することで、鍵管理のオーバーヘッドなしにビルドアーティファクトにデジタル署名することができます。
npm プロボナンスについて
npm CLIは、パッケージメンテナーがユーザーに証明書を提供することを可能にします。npm CLI の証明生成機能を使うことで、ユーザーはダウンロードして使っているパッケージが、あなたとそのパッケージをビルドしたビルドシステムのものであることを信頼し、確認することができます。
npm パッケージの公開方法についてはGitLab npm Package Registry を参照してください。
シグストア
Sigstoreは、パッケージマネージャやセキュリティ専門家が、ソフトウェアのサプライチェーンを攻撃から保護するために使用できるツールのセットです。Fulcio、Cosign、Rekorのようなフリーで使用できるオープンソース技術を結集し、オープンソースソフトウェアをより安全にディストリビューションし、使用するために必要なデジタル署名、検証、出所のチェックを行います。
関連トピック:
GitLab CI/CDでのプロバンス生成
上記のようにSigstoreがGitLab OIDCをサポートするようになったので、npm ProvenanceをGitLab CI/CDとSigstoreと一緒に使うことで、GitLab CI/CDパイプラインでnpmパッケージのProvenanceを生成して署名することができます。
前提条件
- GitLabID トークン
aud
をsigstore
に設定します。 -
--provenance
フラグを追加して npm にパブリッシュさせます。
.gitlab-ci.yml
ファイルに追加するコンテンツの例:
image: node:latest
build:
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
script:
- npm publish --provenance --access public
npmのGitLabテンプレートもこの機能を提供します。例はテンプレートのドキュメントにあります。
npm プロボナンスの検証
npm CLI には、エンドユーザーがパッケージの出所を確認する機能もあります。
npm audit signatures
audited 1 package in 0s
1 package has a verified registry signature
実績メタデータの検査
Rekor transparency log には、証明書と証明書が、実績とともに公開されたパッケージごとに保存されています。例えば、以下の例のエントリは以下の通りです。
npm によって生成された証明ドキュメントの例です:
_type: https://in-toto.io/Statement/v0.1
subject:
- name: pkg:npm/%40strongjz/strongcoin@0.0.13
digest:
sha512: >-
924a134a0fd4fe6a7c87b4687bf0ac898b9153218ce9ad75798cc27ab2cddbeff77541f3847049bd5e3dfd74cea0a83754e7686852f34b185c3621d3932bc3c8
predicateType: https://slsa.dev/provenance/v0.2
predicate:
buildType: https://github.com/npm/CLI/gitlab/v0alpha1
builder:
id: https://gitlab.com/strongjz/npm-provenance-example/-/runners/12270835
invocation:
configSource:
uri: git+https://gitlab.com/strongjz/npm-provenance-example
digest:
sha1: 6e02e901e936bfac3d4691984dff8c505410cbc3
entryPoint: deploy
parameters:
CI: 'true'
CI_API_GRAPHQL_URL: https://gitlab.com/api/graphql
CI_API_V4_URL: https://gitlab.com/api/v4
CI_COMMIT_BEFORE_SHA: 7d3e913e5375f68700e0c34aa90b0be7843edf6c
CI_COMMIT_BRANCH: main
CI_COMMIT_REF_NAME: main
CI_COMMIT_REF_PROTECTED: 'true'
CI_COMMIT_REF_SLUG: main
CI_COMMIT_SHA: 6e02e901e936bfac3d4691984dff8c505410cbc3
CI_COMMIT_SHORT_SHA: 6e02e901
CI_COMMIT_TIMESTAMP: '2023-05-19T10:17:12-04:00'
CI_COMMIT_TITLE: trying to publish to gitlab reg
CI_CONFIG_PATH: .gitlab-ci.yml
CI_DEFAULT_BRANCH: main
CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: gitlab.com:443/strongjz/dependency_proxy/containers
CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX: gitlab.com:443/strongjz/dependency_proxy/containers
CI_DEPENDENCY_PROXY_SERVER: gitlab.com:443
CI_DEPENDENCY_PROXY_USER: gitlab-ci-token
CI_JOB_ID: '4316132595'
CI_JOB_NAME: deploy
CI_JOB_NAME_SLUG: deploy
CI_JOB_STAGE: deploy
CI_JOB_STARTED_AT: '2023-05-19T14:17:23Z'
CI_JOB_URL: https://gitlab.com/strongjz/npm-provenance-example/-/jobs/4316132595
CI_NODE_TOTAL: '1'
CI_PAGES_DOMAIN: gitlab.io
CI_PAGES_URL: https://strongjz.gitlab.io/npm-provenance-example
CI_PIPELINE_CREATED_AT: '2023-05-19T14:17:21Z'
CI_PIPELINE_ID: '872773336'
CI_PIPELINE_IID: '40'
CI_PIPELINE_SOURCE: push
CI_PIPELINE_URL: https://gitlab.com/strongjz/npm-provenance-example/-/pipelines/872773336
CI_PROJECT_CLASSIFICATION_LABEL: ''
CI_PROJECT_DESCRIPTION: ''
CI_PROJECT_ID: '45821955'
CI_PROJECT_NAME: npm-provenance-example
CI_PROJECT_NAMESPACE: strongjz
CI_PROJECT_NAMESPACE_ID: '36018'
CI_PROJECT_PATH: strongjz/npm-provenance-example
CI_PROJECT_PATH_SLUG: strongjz-npm-provenance-example
CI_PROJECT_REPOSITORY_LANGUAGES: javascript,dockerfile
CI_PROJECT_ROOT_NAMESPACE: strongjz
CI_PROJECT_TITLE: npm-provenance-example
CI_PROJECT_URL: https://gitlab.com/strongjz/npm-provenance-example
CI_PROJECT_VISIBILITY: public
CI_REGISTRY: registry.gitlab.com
CI_REGISTRY_IMAGE: registry.gitlab.com/strongjz/npm-provenance-example
CI_REGISTRY_USER: gitlab-ci-token
CI_RUNNER_DESCRIPTION: 3-blue.shared.runners-manager.gitlab.com/default
CI_RUNNER_ID: '12270835'
CI_RUNNER_TAGS: >-
["gce", "east-c", "linux", "ruby", "mysql", "postgres", "mongo",
"git-annex", "shared", "docker", "saas-linux-small-amd64"]
CI_SERVER_HOST: gitlab.com
CI_SERVER_NAME: GitLab
CI_SERVER_PORT: '443'
CI_SERVER_PROTOCOL: https
CI_SERVER_REVISION: 9d4873fd3c5
CI_SERVER_SHELL_SSH_HOST: gitlab.com
CI_SERVER_SHELL_SSH_PORT: '22'
CI_SERVER_URL: https://gitlab.com
CI_SERVER_VERSION: 16.1.0-pre
CI_SERVER_VERSION_MAJOR: '16'
CI_SERVER_VERSION_MINOR: '1'
CI_SERVER_VERSION_PATCH: '0'
CI_TEMPLATE_REGISTRY_HOST: registry.gitlab.com
GITLAB_CI: 'true'
GITLAB_FEATURES: >-
elastic_search,ldap_group_sync,multiple_ldap_servers,seat_link,usage_quotas,zoekt_code_search,repository_size_limit,admin_audit_log,auditor_user,custom_file_templates,custom_project_templates,db_load_balancing,default_branch_protection_restriction_in_groups,extended_audit_events,external_authorization_service_api_management,geo,instance_level_scim,ldap_group_sync_filter,object_storage,pages_size_limit,project_aliases,password_complexity,enterprise_templates,git_abuse_rate_limit,required_ci_templates,runner_maintenance_note,runner_performance_insights,runner_upgrade_management,runner_jobs_statistics
GITLAB_USER_ID: '31705'
GITLAB_USER_LOGIN: strongjz
environment:
name: 3-blue.shared.runners-manager.gitlab.com/default
architecture: linux/amd64
server: https://gitlab.com
project: strongjz/npm-provenance-example
job:
id: '4316132595'
pipeline:
id: '872773336'
ref: .gitlab-ci.yml
metadata:
buildInvocationId: https://gitlab.com/strongjz/npm-provenance-example/-/jobs/4316132595
completeness:
parameters: true
environment: true
materials: false
reproducible: false
materials:
- uri: git+https://gitlab.com/strongjz/npm-provenance-example
digest:
sha1: 6e02e901e936bfac3d4691984dff8c505410cbc3