-
Notifications
You must be signed in to change notification settings - Fork 207
docs(trust): add GitLab CI keyless signing integration #728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -268,10 +268,11 @@ These fields are matched against claims in the Fulcio certificate that Sigstore | |
| | Field | Description | Wildcards | | ||
| |-------|-------------|-----------| | ||
| | `name` | Human-readable label for this publisher (not matched against anything) | No | | ||
| | `issuer` | The OIDC provider URL. For GitHub Actions this is always `https://token.actions.githubusercontent.com` | No | | ||
| | `repository` | The `owner/repo` that ran the signing workflow (maps to the GitHub OIDC `repository` claim). Use `org/*` to trust all repos in an org | Yes (`org/*`) | | ||
| | `workflow` | Path to the workflow file that performed the signing, relative to the repo root | Yes (`*`) | | ||
| | `ref_pattern` | The git ref that triggered the workflow (e.g., `refs/heads/main`, `refs/tags/v1.0`). Use wildcards to trust a range of refs | Yes (`refs/tags/v*`) | | ||
| | `issuer` | The OIDC provider URL. GitHub Actions: `https://token.actions.githubusercontent.com`. GitLab: `https://gitlab.com` | No | | ||
| | `repository` | GitHub: the `owner/repo` string (maps to the `repository` OIDC claim). GitLab: the full project URL (e.g. `https://gitlab.com/org/repo`). Use wildcards to trust a range of repos | Yes (`org/*`, `https://gitlab.com/org/*`) | | ||
| | `workflow` | Path to the CI config file that performed the signing, relative to the repo root (e.g. `.github/workflows/sign.yml`) | Yes (`*`) | | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Supports CI_CONFIG_REF_URI after #706 which could be better than signer URL in some cases such as pipeline policies from security projects.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For GitLab, the |
||
| | `build_signer_uri` | GitLab CI only. Full URI of the CI configuration file and ref that performed the signing (e.g. `https://gitlab.com/org/repo//.gitlab-ci.yml@refs/heads/main`) | Yes (`*`) | | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The example for |
||
| | `ref_pattern` | The git ref that triggered the job (e.g., `refs/heads/main`, `refs/tags/v1.0`). Use wildcards to trust a range of refs | Yes (`refs/tags/v*`) | | ||
|
|
||
| ### blocklist | ||
|
|
||
|
|
@@ -367,6 +368,79 @@ jobs: | |
|
|
||
| This policy declares: only trust files signed by a GitHub Actions workflow in `my-org/my-repo`, from the `main` branch. | ||
|
|
||
| ## GitLab CI Integration | ||
|
|
||
| Keyless signing also integrates with GitLab CI's OIDC tokens. The signing job must request an ID token with the `sigstore` audience so Fulcio can issue a certificate. | ||
|
|
||
| ### Signing Job | ||
|
|
||
| ```yaml | ||
| nono-cli-sign: | ||
| image: | ||
| name: ghcr.io/always-further/nono:0.36.0 | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outdated already 😬 In the GitLab docs we could refer to CI/CD component equivalent of the GitHub action for attestation. We can point this entire GitLab signing section to GitLab docs if that makes sense. 👍🏽
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Additionally I’m playing around with having a Flow which can be enabled in GitLab.com projects which has nono and glab installed to download bundle from the latest pipeline from a default branch or tag. |
||
| entrypoint: [""] | ||
| script: | ||
| - nono trust sign --all --keyless | ||
| id_tokens: | ||
| SIGSTORE_ID_TOKEN: | ||
| aud: sigstore | ||
| artifacts: | ||
| paths: | ||
| - "**/*.bundle" | ||
| ``` | ||
|
|
||
| The `id_tokens` block instructs GitLab to inject a short-lived OIDC token into `$SIGSTORE_ID_TOKEN`. Nono reads this variable automatically when `--keyless` is specified — no additional configuration is needed. | ||
|
|
||
| ### Trust Policy for CI-Signed Files | ||
|
|
||
| GitLab uses `build_signer_uri` instead of `workflow` to identify the signing pipeline. The `repository` field takes the full project URL, and `issuer` is `https://gitlab.com`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| **Branch ref:** | ||
|
|
||
| ```json | ||
| { | ||
| "version": 1, | ||
| "includes": ["SKILLS*", "CLAUDE*"], | ||
| "publishers": [ | ||
| { | ||
| "name": "erran-skills@main", | ||
| "issuer": "https://gitlab.com", | ||
| "build_signer_uri": "https://gitlab.com/erran/skills//.gitlab-ci.yml@refs/heads/main", | ||
| "repository": "https://gitlab.com/erran/skills", | ||
|
Comment on lines
+408
to
+409
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| "ref_pattern": "refs/heads/main" | ||
| } | ||
| ], | ||
| "blocklist": { "digests": [] }, | ||
| "enforcement": "deny" | ||
| } | ||
| ``` | ||
|
|
||
| **Tag ref:** | ||
|
|
||
| ```json | ||
| { | ||
| "version": 1, | ||
| "includes": ["SKILLS*", "CLAUDE*"], | ||
| "publishers": [ | ||
| { | ||
| "name": "erran-skills@0.0.9", | ||
| "issuer": "https://gitlab.com", | ||
| "build_signer_uri": "https://gitlab.com/erran/skills//.gitlab-ci.yml@refs/tags/0.0.9", | ||
| "repository": "https://gitlab.com/erran/skills", | ||
|
Comment on lines
+428
to
+429
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| "ref_pattern": "refs/tags/0.0.9" | ||
| } | ||
| ], | ||
| "blocklist": { "digests": [] }, | ||
| "enforcement": "deny" | ||
| } | ||
| ``` | ||
|
|
||
| Note the double slash in the `build_signer_uri` path separator (`org/repo//.gitlab-ci.yml`). This is the format Fulcio embeds in the certificate — copy it exactly from `nono trust verify` output if you are unsure. | ||
|
|
||
| <Warning> | ||
| Wildcards in `build_signer_uri` and `repository` make it easy to over-trust. An entry with `issuer: https://gitlab.com` and `repository: https://gitlab.com/*` trusts any project on GitLab.com — including forks and unrelated projects. Scope `repository` to the specific project URL, and use `ref_pattern` to restrict to protected branches or release tags. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The warning example should use the project path format for consistency with the implementation. |
||
| </Warning> | ||
|
|
||
| ## Signing Modes | ||
|
|
||
| There are two signing modes, with two key storage backends for keyed signing: | ||
|
|
||



There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The description for GitLab's
repositoryfield states it should be the "full project URL", but the implementation ingitlab_keyless_predicate(line 616 oftrust_cmd.rs) usesCI_PROJECT_PATH, which is thenamespace/projectstring. Using the full URL in the trust policy will cause verification to fail as it won't match the identity claim extracted from the OIDC token.