Loading
Bugfix : Add missing ID token claims for MR pipelines from forked projects
What does this MR do and why?
- Fixes the regression reported in #561735 (closed)
- Resolves #565925 (closed)
- Since the fix for #548165 (closed),
project_pathin the CI ID tokensubclaim is the path of the fork for merge request pipelines from forks that run in the parent project - Cloud providers that only check
sub(like AWS IAM on GitLab Self-Managed) cannot bind these jobs to the parent project, andjob_project_pathis rejected as asubcomponent. Trust policies like that stopped working for these pipelines in 18.2.2 - This MR allows
job_project_path,job_project_id,source_project_pathandsource_project_idassubcomponents, including as the first one - It adds
source_project_id,source_project_path,source_namespace_idandsource_namespace_pathclaims - The burned reclaimed path check covers the new path based components
- Docs include a warning on what
job_project_pathandjob_project_idmean for pipelines from forks
Notes for reviewers
- The reclaimed path check now runs the same way when a runner picks up a job and when the token is minted. Before, the pickup check always used the project running the job, so for pipelines from forks it could check the wrong project. It also fixes that for the existing
project_path. For merge request pipelines, pickup now loads the merge request, and token minting reuses it on the same job - Merged results and merge train pipelines behave the same as other merge request pipelines here. The claims only depend on whether the MR is from a fork and which project the pipeline runs in
- No feature flag, same as the earlier
subcomponent additions (ref_protected,project_idas the first component) - Backports: 19.4 !259313 (merged), 19.3 !259314 (merged), 19.2 !259316 (merged)
End to end testing on GDK
- Tested end to end on GDK with this MR's code, a runner in Docker, and a real merge request pipeline from a fork run in the parent project
- Each job decoded its ID token and printed the claims
- New claims and
subcomponents work as expected, and the reclaimed path check now drops the right jobs at pickup - On
master, the same fork case is picked up and then fails withscheduler_failure
Setup and results
Setup
- Parent project
mr258245-grp/oidc-parent(ID384) and forkuser_one/oidc-parent(ID385) - A commit on the fork's
main, and an MR from the fork'smaininto the parent'smain - The MR pipeline run in the parent project by a parent maintainer. A
mainbranch pipeline in the parent for comparison - A job with
id_tokenson a tagged runner, decoding the token payload
Claims with the default sub
| Claim | MR pipeline from fork, in parent | Parent main pipeline |
|---|---|---|
project_path, project_id |
fork | parent |
job_project_path, job_project_id |
parent | parent |
source_project_*, source_namespace_* |
fork | parent |
ref_protected |
false |
true |
Projects API validation
masterrejectsjob_project_pathas the first component- This MR accepts
job_project_path,job_project_id,source_project_pathandsource_project_idas the first component refas the first component is rejected withthe first element of the sub claim must be one of: project_path, project_id, job_project_path, job_project_id, source_project_path, source_project_id- An unknown component is still rejected
sub for each first component
ci_id_token_sub_claim_components set to [<first>, "ref_type", "ref"]:
| First component | MR pipeline from fork, in parent | Parent main pipeline |
|---|---|---|
job_project_path |
job_project_path:mr258245-grp/oidc-parent:ref_type:branch:ref:main |
same |
job_project_id |
job_project_id:384:ref_type:branch:ref:main |
same |
source_project_path |
source_project_path:user_one/oidc-parent:ref_type:branch:ref:main |
source_project_path:mr258245-grp/oidc-parent:ref_type:branch:ref:main |
source_project_id |
source_project_id:385:ref_type:branch:ref:main |
source_project_id:384:ref_type:branch:ref:main |
project_id |
project_id:385:ref_type:branch:ref:main |
project_id:384:ref_type:branch:ref:main |
With job_project_* the two pipelines get the same sub, as the docs warning says. Adding ref_protected separates them: job_project_id:384:ref_type:branch:ref:main:ref_protected:false vs ...:ref_protected:true.
Reclaimed path check
A burned route row inserted for the fork's path, then for the parent's path:
| Burned path | Dropped at pickup with id_token_burned_project_path |
Token issued |
|---|---|---|
| Fork | project_path and source_project_path on the MR pipeline from the fork |
job_project_path and job_project_id on the MR pipeline from the fork |
| Parent | job_project_path on both pipelines. project_path on the parent main pipeline |
project_path on the MR pipeline from the fork. source_project_id on both |
| Fork, row owned by the fork itself | none | source_project_path on the MR pipeline from the fork |
The same fork case on master, with project_path: the job is picked up and then fails with scheduler_failure, because Gitlab::Ci::OidcBurnedPathError is raised while minting the token.
The dropped jobs show the new failure message.
References
- Issue - #565925 (closed)
- Regression report and the decision to add
job_project_*claims - #561735 (closed) - Security fix that changed
project_pathfor forks - #548165 (closed) - MR that added the
job_project_*claims - !202241 (merged)
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Edited by Jayakrishnan Mallissery