[BE] A user can define permissions for projects in the Job token permissions settings
Why are we doing this work?
We are implementing this solution to give project owners and maintainers more control over the permissions available in a CI_JOB_TOKEN.
This will allow them to limit the scope of access and minimize security risks by specifying the maximum set of permissions needed for their CI/CD jobs.
These permissions will be restricted to those required for the APIs listed below, ensuring that the token only has access to what is necessary for the specific project.
By reducing unnecessary permissions, we can improve security, minimize potential misuse of the token, and align with best practices for least privilege access control.
Permissions
The following permissions were compiled based on findings from this investigation.
Containers
| Action | Permission(s) |
|---|---|
| Delete a registry repository tag |
:admin_container_image OR :destroy_container_image
|
| Delete a registry repository tags in bulk |
:admin_container_image OR :destroy_container_image
|
| Delete registry repository |
:admin_container_image OR :destroy_container_image
|
| Get details of a registry repository tag |
:admin_container_image OR :read_container_image
|
| List registry repositories |
:admin_container_image OR :read_container_image
|
| List registry repository tags |
:admin_container_image OR :read_container_image
|
Deployments
| Action | Permission(s) |
|---|---|
| List project deployments | :read_deployment |
| Get a specific deployment | :read_deployment |
| Create a deployment |
:read_deployment AND :create_deployment
|
| Update a deployment |
:read_deployment AND :update_deployment
|
| Delete a specific deployment | :destroy_deployment |
Environments
| Action | Permission(s) |
|---|---|
| List environments | :read_environment |
| Get a specific environment | :read_environment |
| Create a new environment | :create_environment |
| Update an existing environment | :update_environment |
| Delete an environment |
:read_environment AND :destroy_environment
|
| Delete multiple stopped review apps |
:read_environment AND :destroy_environment
|
| Stop an environment |
:read_environment AND :stop_environment
|
| Stop stale environments |
:read_environment AND :stop_environment
|
Jobs
| Action | Permission(s) |
|---|---|
| Get job token's job | :read_build |
Get GitLab agent by CI_JOB_TOKEN |
:read_build |
| Update pipeline metadata | :update_pipeline |
| Get job artifacts |
:read_build AND :read_job_artifacts
|
| Download the artifacts archive |
:read_build AND :read_job_artifacts
|
| Download a single artifact file by job ID |
:read_build AND :read_job_artifacts
|
| Download a single artifact file from a specific tag or branch |
:read_build AND :read_job_artifacts
|
Packages
| Route | Permission(s) |
|---|---|
| List packages | :read_package |
| Get a project package | :read_package |
| List package files | :read_package |
| List package pipelines |
:read_package AND :read_pipeline
|
| Delete a project package | :destroy_package |
| Delete a package file | :destroy_package |
PUT /projects/:id/packages/generic/:package_name/*package_version/(*path/):file_name/authorize
|
:read_project AND :create_package
|
GET /projects/:id/packages/generic/:package_name/*package_version/(*path/):file_name
|
:read_project AND :read_package
|
PUT /projects/:id/packages/generic/:package_name/*package_version/(*path/):file_name
|
:read_project |
Maven
| Permission(s) | Route |
|---|---|
| Download a package file at the instance level | :read_package |
| Download a package file at the group level |
:read_group AND :read_package
|
| Download a package file at the project level |
:read_project AND :read_package
|
| Upload a package file |
:read_project AND :create_package
|
PUT /projects/:id/packages/maven/*path/:file_name/authorize
|
:read_project AND :create_package
|
PyPI
| Permission(s) | Route |
|---|---|
| Download a package file from a group |
:read_group AND :read_package
|
| Group-level simple API index |
:read_group AND :read_package
|
| Group level simple API entry point |
:read_group AND :read_package
|
| Download a package file from a project |
:read_project AND :read_package
|
| Project-level simple API index |
:read_project AND :read_package
|
| Project-level simple API entry point |
:read_project AND :read_package
|
| Upload a package |
:read_project AND :create_package
|
POST /projects/:id/-/packages/pypi/authorize
|
:read_project AND :create_package
|
Composer
| Permission(s) | Route |
|---|---|
| Base repository request | :read_group |
| V1 packages list | :read_group |
| V2 Package Metadata | :read_group |
| Create a package | :create_package |
NPM
| Permission(s) | Route |
|---|---|
| Project-level: Download a package | :read_package |
| Project-level: Upload a package | :create_package |
| Group-level: Package Metadata | :read_package |
| Project-level: Package Metadata | :read_package |
| Group-level: List tags | :read_package |
| Project-level: List tags | :read_package |
| Group-level: Create or update a tag | :create_package |
| Project-level: Create or update a tag | :create_package |
| Group-level: Delete a tag | :destroy_package |
| Group-level: Delete a tag | :destroy_package |
POST /groups/:id/-/packages/npm/-/npm/v1/security/advisories/bulk
|
:read_package |
POST /groups/:id/-/packages/npm/-/npm/v1/security/audits/quick
|
:read_package |
POST /projects/:id/-/packages/npm/-/npm/v1/security/advisories/bulk
|
:read_package |
POST /projects/:id/-/packages/npm/-/npm/v1/security/audits/quick
|
:read_package |
Go Proxy
| Permission(s) | Route |
|---|---|
| List packages | :read_package |
| Version metadata | :read_package |
| Download module file | :read_package |
| Download module source | :read_package |
Releases
| Action | Permission(s) |
|---|---|
| List links of a release | :read_release |
| Get a release link | :read_release |
| Create a release link | :create_release |
| Update a release link | :update_release |
| Delete a release link | :destroy_release |
Secure Files
| Action | Permission(s) |
|---|---|
| List project secure files |
:read_secure_files OR :admin_secure_files
|
| Show secure file details |
:read_secure_files OR :admin_secure_files
|
| Create secure file | :admin_secure_files |
| Download secure file |
:read_secure_files OR :admin_secure_files
|
| Remove a secure file | :admin_secure_files |
Terraform
| Action | Permission(s) |
|---|---|
| Retrieve individual Terraform state version |
:read_terraform_state OR :admin_terraform_state
|
| Remove individual Terraform state version | :admin_terraform_state |
| Remove a state file | :admin_terraform_state |
| Retrieve a state file |
:read_terraform_state OR :admin_terraform_state
|
| Create a state file | :admin_terraform_state |
| Create a lock file | :admin_terraform_state |
| Delete a lock file | :admin_terraform_state |
Internal
| Action | Permission(s) |
|---|---|
POST /internal/dast/site_validations/:id/transition
|
:create_on_demand_dast_scan |
Relevant links
- CI Job Token
- Permissions investigation
- Architecture Design
- Solution Validation
- Mockup
- CI Job Token Allow list
Implementation Plan
-
database Add a permissions JSONBcolumn to theci_job_token_project_scope_linkstable. -
backend Provide an API to save enabled permissions to the ci_job_token_project_scope_links.permissionscolumn. -
UX Create mockups for the frontend -
frontend TBD
Verification steps
Edited by mo khan
