使用 Sigstore 进行无密钥签名和验证
Sigstore 项目提供了一个名为 Cosign 的 CLI,可用于使用极狐GitLab CI/CD 构建的容器镜像的无密钥签名。无密钥签名有很多优点,包括无需管理、保护和轮换私钥。Cosign 请求一个短期密钥对用于签名,将其记录在证书透明度日志中,然后将其丢弃。密钥是通过使用运行流水线的用户的 OIDC 身份从极狐GitLab 服务器获取的令牌生成的。该令牌包含证明该令牌是由 CI/CD 流水线生成的独特声明。要了解更多信息,请参阅有关无密钥签名的 Cosign 文档。
有关极狐GitLab OIDC 声明和 Fulcio 证书扩展之间映射的详细信息,请参阅将 OIDC 令牌声明映射到 Fulcio OID 的极狐GitLab 专栏。
要求:
- 您必须使用 JihuLab.com。
- 您项目的 CI/CD 配置必须位于项目中。
使用 Cosign 对容器镜像和构建产物进行签名和验证
您可以使用 Cosign 对容器镜像和构建产物进行签名和验证。
先决条件:
- 您必须使用版本为
>= 2.0.1
的 Cosign。
限制
- The
id_tokens
portion of the CI/CD configuration file must be located in the project that is being built and signed. AutoDevOps, CI files included from another repository, and child pipelines are not supported. Work to remove this limitation is being tracked in issue 411317. - CI/CD 配置文件中的
id_tokens
部分必须位于正在构建和签名的项目中。AutoDevOps、从另一个仓库包含的 CI 文件和子流水线不受支持。
最佳实践:
- 在构建和签名容器镜像时,在同一作业中构建和签名镜像,以防止镜像在签名之前被篡改。
- 在签名容器镜像时,签名摘要(不可变)而不是标签。
极狐GitLab ID 令牌可以由 Cosign 用于无密钥签名。令牌必须将 sigstore
设置为 aud
声明。当在 SIGSTORE_ID_TOKEN
环境变量中设置该令牌时,Cosign 可以自动使用该令牌。
要学习关于安装 Cosign 的更多详情,请参阅 Cosign 安装文档。
签名
容器镜像
Cosign.gitlab-ci.yml
模版可用于在极狐GitLab CI 中构建和签名容器镜像。签名会自动存储在与镜像相同的容器仓库中。
include:
- template: Cosign.gitlab-ci.yml
要学习关于签名容器的更多详情,请参阅 Cosign 签名容器文档。
构建产物
如下示例演示如何在极狐GitLab CI 中对构建产物进行签名。您应该保存 cosign.sign
生成的 cosign.bundle
文件,用于签名验证。
要学习关于签名产物的更多详情,请参阅 Cosign 签名 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 验证文档。
容器镜像
如下示例演示如何在极狐GitLab CI 中验证已签名的容器镜像。命令行参数在上方进行了描述。
verify_image:
image: alpine:3.20
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_REF_SLUG" --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.yml
路径之间的双反斜杠不是错误,而是验证成功所必需的。如果使用单斜杠,则通常会出现以下错误:Error: none of the expected identities matched what was in the certificate, got subjects
,后跟已签名的 URL,该 URL 在项目路径和.gitlab-ci.yml
路径之间有两个斜杠。 - 如果验证发生在与签名相同的流水线中,则可以使用此路径:
"${CI_PROJECT_URL}//.gitlab-ci.yml@refs/heads/${CI_COMMIT_REF_NAME}"
构建产物
以下示例演示了如何在极狐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"
额外信息:
- 如果项目路径和
.gitlab-ci.yml
路径中的双反斜杠不是错误,而是验证成功所必需的。如果使用单斜杠,则通常会出现以下错误:Error: none of the expected identities matched what was in the certificate, got subjects
,后跟已签名的 URL,该 URL 在项目路径和.gitlab-ci.yml
路径之间有两个斜杠。 - 如果验证发生在与签名相同的流水线中,则可以使用此路径:
"${CI_PROJECT_URL}//.gitlab-ci.yml@refs/heads/${CI_COMMIT_REF_NAME}"
使用 Sigstore 和 npm 生成无密钥来源
您可以使用 Sigstore 和 npm 以及极狐GitLab CI/CD 对构建产物进行数字签名,而无需花费密钥管理的开销。
关于 npm 来源
npm CLI 允许软件包维护者向用户提供来源证明。使用 npm CLI 来源生成允许用户信任并验证他们正在下载和使用的包是否来自您和构建它的构建系统。
有关如何发布 npm 包的更多信息,请参阅极狐GitLab npm 软件包库。
Sigstore
Sigstore 是一组工具,软件包管理器和安全专家可以使用它们来保护其软件供应链免受攻击。它汇集了 Fulcio、Cosign 和 Rekor 等免费使用的开源技术,可以处理数字签名、验证和来源检查,从而使开源软件的分发和使用更加安全。
相关主题:
在极狐GitLab CI/CD 中生成来源
现在,Sigstore 支持如上所述的极狐GitLab OIDC,您可以将 npm 来源与极狐GitLab CI/CD 和 Sigstore 一起使用,为极狐GitLab CI/CD 流水线中的 npm 包生成并签署来源。
先决条件
- 将您的极狐GitLab ID 令牌
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 透明度日志存储每个带有来源的发布的包的证书和证明。例如以下示例的条目。
由 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