diff options
Diffstat (limited to 'doc/ci/yaml/signing_examples.md')
-rw-r--r-- | doc/ci/yaml/signing_examples.md | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/doc/ci/yaml/signing_examples.md b/doc/ci/yaml/signing_examples.md new file mode 100644 index 00000000000..5609bd2374e --- /dev/null +++ b/doc/ci/yaml/signing_examples.md @@ -0,0 +1,310 @@ +--- +stage: Verify +group: Pipeline Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Use Sigstore for keyless signing and verification **(FREE SAAS)** + +The [Sigstore](https://www.sigstore.dev/) project provides a CLI called +[Cosign](https://docs.sigstore.dev/cosign/overview/) which can be used for keyless signing of container images built +with GitLab CI/CD. Keyless signing has many advantages, including eliminating the need to manage, safeguard, and rotate a private +key. Cosign requests a short-lived key pair to use for signing, records it on a certificate transparency log, and +then discards it. The key is generated through a token obtained from the GitLab server using the OIDC identity of the user who +ran the pipeline. This token includes unique claims that certify the token was generated by a CI/CD pipeline. To learn more, +see Cosign [documentation](https://docs.sigstore.dev/cosign/overview/#example-working-with-containers) on keyless signatures. + +For details on the mapping between GitLab OIDC claims and Fulcio certificate extensions, see the GitLab column of +[Mapping OIDC token claims to Fulcio OIDs](https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md#mapping-oidc-token-claims-to-fulcio-oids). + +**Requirements:** + +- You must be using GitLab.com. +- Your project's CI/CD configuration must be located in the project. +- You must use a version of Cosign that is `>= 2.0.1`. + +## Container images + +### Sign a container image with Cosign + +GitLab [ID tokens](../secrets/id_token_authentication.md) can be used by Cosign for +[keyless signing](https://docs.sigstore.dev/cosign/overview/#example-working-with-containers). The token must have `sigstore` set as the +[`aud`](../secrets/id_token_authentication.md#token-payload) claim. The token can be used by Cosign automatically when +it is set in the `SIGSTORE_ID_TOKEN` environment variable. + +**Best practices**: + +- Build and sign a container image in the same job to prevent the image from being tampered with before it is + signed. + +See [Cosign documentation](https://docs.sigstore.dev/cosign/signing_with_containers/) to learn more about signing. + +```yaml +build_and_sign: + 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 +``` + +### Verify a container image with Cosign + +```yaml +verify: + 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" +``` + +## Use Sigstore and npm to generate keyless provenance + +You can use Sigstore and npm, together with GitLab CI/CD, to digitally sign build artifacts without the overhead of key management. + +### About npm provenance + +[npm CLI](https://docs.npmjs.com/cli) allows package maintainers to provide users with provenance attestations. Using npm +CLI provenance generation allows users to trust and verify that the package they are downloading and using is from you and the +build system that built it. + +For more information on how to publish npm packages, see [GitLab npm Package Registry](../../user/packages/npm_registry/index.md). + +### Sigstore + +[Sigstore](https://www.sigstore.dev/) is a set of tools that package managers and security experts can use to secure their software +supply chains against attacks. Bringing together free-to-use open source technologies like Fulcio, Cosign, and Rekor, it +handles digital signing, verification, and checks for provenance +needed to make it safer to distribute and use open source software. + +**Related topics**: + +- [SLSA Provenance definition](https://slsa.dev/provenance/v1) +- [npm Docs](https://docs.npmjs.com/generating-provenance-statements) +- [npm Provenance RFC](https://github.com/npm/rfcs/blob/main/accepted/0049-link-packages-to-source-and-build.md#detailed-steps-to-publish) + +### Generating provenance in GitLab CI/CD + +Now that Sigstore supports GitLab OIDC as described above, you can use npm provenance together with GitLab CI/CD and Sigstore to +generate and sign provenance for your npm packages in a GitLab CI/CD pipeline. + +#### Prerequisites + +1. Set your GitLab [ID token](../secrets/id_token_authentication.md) `aud` to `sigstore`. +1. Add the `--provenance` flag to have npm publish. + +Example content to be added to `.gitlab-ci.yml` file: + +```yaml +image: node:latest + +build: + id_tokens: + SIGSTORE_ID_TOKEN: + aud: sigstore + script: + - npm publish --provenance --access public +``` + +The npm GitLab template provides this functionality as well, the example is in +the [templates documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/npm.gitlab-ci.yml). + +## Verifying npm provenance + +npm CLI also provides functionality for end users to verify the provenance of packages. + +```plaintext +npm audit signatures +audited 1 package in 0s +1 package has a verified registry signature +``` + +### Inspecting the provenance metadata + +The Rekor transparency log stores certificates and attestations for every package that is published with provenance. +For example, here is the [entry for the below example](https://search.sigstore.dev/?logIndex=21076013). + +An example provenance document generated by npm: + +```yaml +_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 +``` + +## Build artifacts + +You can use Cosign to both sign build artifacts and verify artifacts that were signed with Cosign. + +### Sign a build artifact with Cosign + +GitLab [ID tokens](../secrets/id_token_authentication.md) can be used by Cosign for keyless signing of build artifacts. +The token must have `sigstore` set as the [`aud`](../secrets/id_token_authentication.md#token-payload) claim. The token can be used by Cosign automatically when +it is set in the `SIGSTORE_ID_TOKEN` environment variable. + +**Best practices**: + +- Build and sign an artifact in the same job to prevent the artifact from being tampered with before it is + signed. + +To learn more about signing artifacts, see [Cosign documentation](https://docs.sigstore.dev/cosign/signing_with_blobs/#keyless-signing-of-blobs-and-files). + +```yaml +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 +``` + +### Verify a build artifact with Cosign + +Verifying an artifact requires both the artifact itself and the `cosign.bundle` file produced by `cosign sign-blob`. +The `--certificate-identity` option should reference the project and branch where the artifact was signed. The +`--certificate-oidc-issuer` option should reference the GitLab instance where the artifact was signed. + +To learn more about verifying signed artifacts, see [Cosign documentation](https://docs.sigstore.dev/cosign/verify/). + +```yaml +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" +``` |