Enforce allowlisted permissions for CI Jobs
What does this MR do and why?
When accessing another project from a CI Job with a CI_JOB_TOKEN, only API endpoints tagged with allowlisted permissions on the inbound project are authorized.
How to set up and validate locally
- Enable the
enforce_job_token_policiesfeature flag:Feature.enable(:enforce_job_token_policies) - Create 2 projects:
project_aandproject_b, ensuremy_userhas at least developer access to both projects - Get the token for a running job in
project_a:pipeline = FactoryBot.create(:ci_pipeline, project: project_a) job = FactoryBot.create(:ci_build, :running, pipeline: pipeline, user: my_user) job.token - Verify the endpoint is unauthorized:
CI_JOB_TOKEN=#job.token PROJECT_B_ID=#project_b.id curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments" {"message":"403 Forbidden - Authentication by CI/CD job token not allowed from project_a to project_b."} - Create a project scope_link:
scope = Ci::JobToken::ProjectScopeLink.create(target_project: project_a, source_project: project_b, direction: :inbound) - Verify the endpoint is now authorized:
curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments" [] - Enable fine grained permissions:
scope.update(default_permissions: false) - Verify the endpoint is now unauthorized and contains a message with the missing policy:
curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments" {"message":"403 Forbidden - The read_environments permission on project_b is not authorized for this CI/CD job token."} - Update the project scope_link with the allowed policy:
scope.update(job_token_policies: [:read_environments]) - Verify the endpoint is now authorized:
curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments" [] - Verify untagged endpoints are unauthorized:
curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/deployments" {"message":"403 Forbidden - This action is not authorized for CI/CD job tokens."} - Disable fine grained permissions:
scope.update(default_permissions: true) - Verify untagged endpoints are now authorized:
curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/deployments" []
Edited by Alex Buijs