Skip to content

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

  1. Enable the enforce_job_token_policies feature flag:
    Feature.enable(:enforce_job_token_policies)
  2. Create 2 projects: project_a and project_b, ensure my_user has at least developer access to both projects
  3. 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
  4. 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."}
  5. Create a project scope_link:
    scope = Ci::JobToken::ProjectScopeLink.create(target_project: project_a, source_project: project_b, direction: :inbound)
  6. Verify the endpoint is now authorized:
    curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments"
    []
  7. Enable fine grained permissions:
    scope.update(default_permissions: false)
  8. 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."}
  9. Update the project scope_link with the allowed policy:
    scope.update(job_token_policies: [:read_environments])
  10. Verify the endpoint is now authorized:
    curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/environments"
    []
  11. 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."}
  12. Disable fine grained permissions:
    scope.update(default_permissions: true)
  13. Verify untagged endpoints are now authorized:
    curl -H "JOB-TOKEN: $CI_JOB_TOKEN" "http://gdk.test:3000/api/v4/projects/$PROJECT_B_ID/deployments"
    []

Issue: gitlab-org/govern/authorization/team-tasks#67

Edited by Alex Buijs

Merge request reports

Loading