Add pipeline source event and target ref to the custom claims of JWT
-
Please check this box if this contribution uses AI-generated content (including content generated by GitLab Duo features) as outlined in the GitLab DCO & CLA. As a benefit of being a GitLab Community Contributor, you receive complimentary access to GitLab Duo.
What does this MR do and why?
This MR adds three new JWT claims to CI job tokens for merge request pipelines to enable more granular access control in Vault bound claims:
-
pipeline_source_event- Distinguishes between regular merge request pipelines ("merge_request") and merge train pipelines ("merge_train") -
target_ref- Provides the target branch name of the merge request (e.g.,"main","develop") -
target_ref_protected- Indicates whether the target branch is protected ("true"or"false")
These claims are only included for merge request event pipelines (pipeline.merge_request_event?).
Use case: Organizations using Vault for secrets management can now create more precise bound claims policies. For example, allowing only merge train pipelines to access production secrets, or restricting deployments based on target branch protection status.
References
Screenshots or screen recordings
This change affects JWT token payload structure (backend only), no UI changes.
Example JWT payload for merge train pipeline:
{
"pipeline_source": "merge_request_event",
"pipeline_source_event": "merge_train",
"target_ref": "main",
"target_ref_protected": "true",
...
}
Example Vault role configuration:
bound_claims:
project_path: "my-org/my-project"
pipeline_source_event: "merge_train"
target_ref: "main"
target_ref_protected: "true"
How to set up and validate locally
# Create test objects
user = User.first || FactoryBot.create(:user)
project = Project.first || FactoryBot.create(:project)
mr = FactoryBot.create(:merge_request, source_project: project, target_project: project)
pipeline = FactoryBot.create(:ci_pipeline, :detached_merge_request_pipeline, merge_request: mr, project: project)
build = FactoryBot.create(:ci_build, pipeline: pipeline, project: project)
# Test JWT
jwt = Gitlab::Ci::Jwt.new(build, ttl: 300)
payload = jwt.payload
# Verify claims
puts payload[:pipeline_source_event] # Should be "detached"
puts payload[:target_ref] # Should be target branch
puts payload[:target_ref_protected] # Should be "true" or "false"
MR acceptance checklist
-
Evaluated this MR against the MR acceptance checklist.
Closes #574759 (closed)
Edited by Jayakrishnan Mallissery