256 lines
11 KiB
Markdown
256 lines
11 KiB
Markdown
---
|
|
stage: Verify
|
|
group: Continuous Integration
|
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
|
type: reference
|
|
---
|
|
|
|
# New CI job permissions model
|
|
|
|
> Introduced in GitLab 8.12.
|
|
|
|
GitLab 8.12 has a completely redesigned [job permissions](../permissions.md#job-permissions) system. You can find
|
|
all discussion and all our concerns when choosing the current approach in issue
|
|
[#18994](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18994).
|
|
|
|
Jobs permissions should be tightly integrated with the permissions of a user
|
|
who is triggering a job.
|
|
|
|
The reasons to do it like that are:
|
|
|
|
- We already have a permissions system in place: group and project membership
|
|
of users.
|
|
- We already fully know who is triggering a job (using `git push`, using the
|
|
web UI, executing triggers).
|
|
- We already know what user is allowed to do.
|
|
- We use the user permissions for jobs that are triggered by the user.
|
|
- It opens a lot of possibilities to further enforce user permissions, like
|
|
allowing only specific users to access runners or use secure variables and
|
|
environments.
|
|
- It is simple and convenient that your job can access everything that you
|
|
as a user have access to.
|
|
- Short living unique tokens are now used, granting access for time of the job
|
|
and maximizing security.
|
|
|
|
With the new behavior, any job that is triggered by the user, is also marked
|
|
with their read permissions. When a user does a `git push` or changes files through
|
|
the web UI, a new pipeline is usually created. This pipeline is marked
|
|
as created by the pusher (local push or via the UI) and any job created in this
|
|
pipeline has the read permissions of the pusher but not write permissions.
|
|
|
|
This allows us to make it really easy to evaluate the access for all projects
|
|
that have [Git submodules](../../ci/git_submodules.md) or are using container images that the pusher
|
|
would have access too. **The permission is granted only for the time that the job
|
|
is running. The access is revoked after the job is finished.**
|
|
|
|
## Types of users
|
|
|
|
It is important to note that we have a few types of users:
|
|
|
|
- **Administrators**: CI jobs created by Administrators don't have access
|
|
to all GitLab projects, but only to projects and container images of projects
|
|
that the administrator is a member of. That means that if a project is either
|
|
public or internal users have access anyway, but if a project is private, the
|
|
Administrator has to be a member of it in order to have access to it
|
|
via another project's job.
|
|
|
|
- **External users**: CI jobs created by [external users](../permissions.md#external-users) have
|
|
access only to projects to which the user has at least Reporter access. This
|
|
rules out accessing all internal projects by default.
|
|
|
|
This allows us to make the CI and permission system more trustworthy.
|
|
Let's consider the following scenario:
|
|
|
|
1. You are an employee of a company. Your company has a number of internal tools
|
|
hosted in private repositories and you have multiple CI jobs that make use
|
|
of these repositories.
|
|
|
|
1. You invite a new [external user](../permissions.md#external-users). CI jobs created by that user do not
|
|
have access to internal repositories, because the user also doesn't have the
|
|
access from within GitLab. You as an employee have to grant explicit access
|
|
for this user. This allows us to prevent from accidental data leakage.
|
|
|
|
## Job token
|
|
|
|
When a pipeline job is about to run, GitLab generates a unique token and injects it as the
|
|
[`CI_JOB_TOKEN` predefined variable](../../ci/variables/predefined_variables.md).
|
|
This token can authenticate [API requests](../../api/README.md)
|
|
from the job script (Runner) that needs to access the project's resources (for example, when
|
|
fetching a job artifact).
|
|
|
|
Once the token is authenticated, GitLab identifies the user who triggered the job and uses this user
|
|
to authorize access to the resource. Therefore, this user must be assigned to
|
|
[a role that has the required privileges](../permissions.md).
|
|
|
|
The job token has these limitations:
|
|
|
|
- Not all APIs allow job tokens for authentication. See [this list](../../api/README.md#gitlab-ci-job-token)
|
|
for available endpoints.
|
|
- The token is valid only while the pipeline job runs. Once the job finishes, the token can't be
|
|
used for authentication.
|
|
|
|
Although a job token is handy to quickly access a project's resources without any configuration, it
|
|
sometimes gives extra permissions that aren't necessary. There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559)
|
|
to redesign the feature for more strategic control of the access permissions.
|
|
|
|
If you need your CI pipeline to push to the Package Registry, consider using [deploy tokens](deploy_tokens/index.md).
|
|
|
|
We try to make sure that this token doesn't leak by:
|
|
|
|
1. Securing all API endpoints to not expose the job token.
|
|
1. Masking the job token from job logs.
|
|
1. Granting permissions to the job token **only** when the job is running.
|
|
|
|
However, this brings up a question about the runner's security. To make sure that
|
|
this token doesn't leak, you should also make sure that you configure
|
|
your runners in the most possible secure way, by avoiding the following:
|
|
|
|
1. Any usage of Docker's `privileged` mode is risky if the machines are re-used.
|
|
1. Using the `shell` executor since jobs run on the same machine.
|
|
|
|
By using an insecure GitLab Runner configuration, you allow the rogue developers
|
|
to steal the tokens of other jobs.
|
|
|
|
## Before GitLab 8.12
|
|
|
|
In versions before GitLab 8.12, all CI jobs would use the runner's token
|
|
to checkout project sources.
|
|
|
|
The project's runner token was a token that you could find under the
|
|
project's **Settings > Pipelines** and was limited to access only that
|
|
project.
|
|
It could be used for registering new specific runners assigned to the project
|
|
and to checkout project sources.
|
|
It could also be used with the GitLab Container Registry for that project,
|
|
allowing pulling and pushing Docker images from within the CI job.
|
|
|
|
GitLab would create a special checkout URL like:
|
|
|
|
```plaintext
|
|
https://gitlab-ci-token:<project-runners-token>/gitlab.com/gitlab-org/gitlab-foss.git
|
|
```
|
|
|
|
And then the users could also use it in their CI jobs all Docker related
|
|
commands to interact with GitLab Container Registry. For example:
|
|
|
|
```shell
|
|
docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
|
|
```
|
|
|
|
Using single token had multiple security implications:
|
|
|
|
- The token would be readable to anyone who had Developer access to a project
|
|
that could run CI jobs, allowing the developer to register any specific
|
|
runner for that project.
|
|
- The token would allow to access only the project's sources, forbidding from
|
|
accessing any other projects.
|
|
- The token was not expiring and was multi-purpose: used for checking out sources,
|
|
for registering specific runners and for accessing a project's container
|
|
registry with read-write permissions.
|
|
|
|
All the above led to a new permission model for jobs that was introduced
|
|
with GitLab 8.12.
|
|
|
|
## Making use of the new CI job permissions model
|
|
|
|
With the new job permissions model, there is now an easy way to access all
|
|
dependent source code in a project. That way, we can:
|
|
|
|
1. Access a project's dependent repositories
|
|
1. Access a project's [Git submodules](../../ci/git_submodules.md)
|
|
1. Access private container images
|
|
1. Access project's and submodule LFS objects
|
|
|
|
Below you can see the prerequisites needed to make use of the new permissions
|
|
model and how that works with Git submodules and private Docker images hosted on
|
|
the container registry.
|
|
|
|
### Prerequisites to use the new permissions model
|
|
|
|
With the new permissions model in place, there may be times that your job
|
|
fails. This is most likely because your project tries to access other project's
|
|
sources, and you don't have the appropriate permissions. In the job log look
|
|
for information about 403 or forbidden access messages.
|
|
|
|
In short here's what you need to do should you encounter any issues.
|
|
|
|
As an administrator:
|
|
|
|
- **500 errors**: You need to update [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) to at
|
|
least 0.8.2. This is done automatically for Omnibus installations, you need to
|
|
[check manually](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/update) for installations from source.
|
|
- **500 errors**: Check if you have another web proxy sitting in front of NGINX (HAProxy,
|
|
Apache, etc.). It might be a good idea to let GitLab use the internal NGINX
|
|
web server and not disable it completely. See [this comment](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22484#note_16648302) for an
|
|
example.
|
|
- **403 errors**: You need to make sure that your installation has [HTTP(S)
|
|
cloning enabled](../admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols). HTTP(S) support is now a **requirement** by GitLab CI
|
|
to clone all sources.
|
|
|
|
As a user:
|
|
|
|
- Make sure you are a member of the group or project you're trying to have
|
|
access to. As an Administrator, you can verify that by impersonating the user
|
|
and retry the failing job in order to verify that everything is correct.
|
|
|
|
### Dependent repositories
|
|
|
|
The [CI/CD variable](../../ci/variables/README.md#predefined-cicd-variables) `CI_JOB_TOKEN` can be used to
|
|
authenticate any clones of dependent repositories. For example:
|
|
|
|
```shell
|
|
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/<user>/<mydependentrepo>.git
|
|
```
|
|
|
|
It can also be used for system-wide authentication
|
|
(only do this in a Docker container, it overwrites `~/.netrc`):
|
|
|
|
```shell
|
|
echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
|
|
```
|
|
|
|
### Git submodules
|
|
|
|
To properly configure submodules with GitLab CI/CD, read the
|
|
[Git submodules documentation](../../ci/git_submodules.md).
|
|
|
|
### Container Registry
|
|
|
|
With the update permission model we also extended the support for accessing
|
|
Container Registries for private projects.
|
|
|
|
GitLab Runner versions prior to 1.8 don't incorporate the introduced changes
|
|
for permissions. This makes the `image:` directive not work with private
|
|
projects automatically and it needs to be configured manually on the GitLab Runner host
|
|
with a predefined account (for example administrator's personal account with
|
|
access token created explicitly for this purpose). This issue is resolved with
|
|
latest changes in GitLab Runner 1.8 which receives GitLab credentials with
|
|
build data.
|
|
|
|
Starting from GitLab 8.12, if you have [2FA](../profile/account/two_factor_authentication.md) enabled in your account, you need
|
|
to pass a [personal access token](../profile/personal_access_tokens.md) instead of your password in order to
|
|
login to the Container Registry.
|
|
|
|
Your jobs can access all container images that you would normally have access
|
|
to. The only implication is that you can push to the Container Registry of the
|
|
project for which the job is triggered.
|
|
|
|
This is how an example usage can look like:
|
|
|
|
```yaml
|
|
test:
|
|
script:
|
|
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
|
|
- docker pull $CI_REGISTRY/group/other-project:latest
|
|
- docker run $CI_REGISTRY/group/other-project:latest
|
|
```
|
|
|
|
### Pipeline triggers
|
|
|
|
Since 9.0 [pipeline triggers](../../ci/triggers/README.md#ci-job-token) do support the new permission model.
|
|
The new triggers do impersonate their associated user including their access
|
|
to projects and their project permissions.
|
|
|
|
### API
|
|
|
|
GitLab API can be used via `CI_JOB_TOKEN`, see [the relevant documentation](../../api/README.md#gitlab-ci-job-token).
|