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_path in the CI ID token sub claim 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, and job_project_path is rejected as a sub component. Trust policies like that stopped working for these pipelines in 18.2.2
  • This MR allows job_project_path, job_project_id, source_project_path and source_project_id as sub components, including as the first one
  • It adds source_project_id, source_project_path, source_namespace_id and source_namespace_path claims
  • The burned reclaimed path check covers the new path based components
  • Docs include a warning on what job_project_path and job_project_id mean 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 sub component additions (ref_protected, project_id as 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 sub components 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 with scheduler_failure
Setup and results

Setup

  • Parent project mr258245-grp/oidc-parent (ID 384) and fork user_one/oidc-parent (ID 385)
  • A commit on the fork's main, and an MR from the fork's main into the parent's main
  • The MR pipeline run in the parent project by a parent maintainer. A main branch pipeline in the parent for comparison
  • A job with id_tokens on 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

  • master rejects job_project_path as the first component
  • This MR accepts job_project_path, job_project_id, source_project_path and source_project_id as the first component
  • ref as the first component is rejected with the 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

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

Merge request reports

Loading
Loading