Eficode’s Managed Services team works with great many of our customers to deploy GitLab properly. This work has led to many deep discussions about the best practices of Identity and Access Management (IAM). One recurring topic is the proper use of the different tokens GitLab offers.

I felt tokens warrant a blog post as they are a powerful tool but require some understanding to use optimally.

The seven pillars of tokens

By my calculation, we have twelve different tokens that can be divided into several categories, including: Personal, Project, Group, Runner, Integration, Admin, and Global. The downside of this fine-grained system is that it allows far too many ways of automating your IAM profiles. 

The following table gives an overview of how the different types of tokens should be used:

Category

Token name

Description

Recommendation

Who can modify

Personal

Personal access token

Usage of SSO platforms (e.g., Azure AD), enables API usage, enables usage of Git in SSO if SSH is prevented 

Should always be used instead of username+password for API calls.

Users themselves

Project

Project access token

API access and capability to push to a project; meant for automatic management of project and API access

In monorepo environments, these tokens enable easy access to many repositories and their central management.

Capability to push tags to a Git repository.

Project Owner & Maintainer

Project

Deploy token

The default way of reading Git and pushing/pulling from Docker & package registry with no pushing to Git repository

We recommend this for monorepo projects needing to read Git repository outside of GitLab and capability to push/read binaries.

Project Owner & Maintainer

Group

Group access token

API access and capability to push to project, meant for automated management of the whole group of projects and API access

In multirepo environments, these tokens enable easy access to many repositories and their central management.

Capability to push tags to a Git repository.

Group Owner & Maintainer

Group

Group deploy token 

The default way of reading Git and pushing/pulling from docker & package registry without pushing to a Git repository. Good for multirepo projects as they allow using the same token for many Git pulls.

Recommendation for multirepo projects needing to access Git repositories outside of GitLab and capability to push/read binaries.

Group Owner & Maintainer

Global

Access token

Grants global admin permissions for all repositories and APIs based on scopes.

Should not be used unless you really need to manage the whole instance via API.

Global admin

Global

Deploy token

Grants global admin permissions for all repositories for reading.

Should not be used unless you really need to read every Git repository in the instance.

 

Global admin

Project and Group

Trigger tokens

Allows CI/CD pipelines to be triggered remotely. Allows you to do a POST request to GitLab to trigger a CI/CD job without any other authentication.

This token is very powerful for creating separation of duties or automating tasks via GitLab Jobs.

Project Owner, Group Owner & Maintainer

Integration 

Oauth 2.0

Allows you to create authentication between many services. 

Most of our customers need this for Jira integrations

Group owner and Global admin

Integration

JSON Web Token (JWT)

Allows you to create secret management between a multitude of services. 

For example, to be used for integration to Hashicorp Vault 

Group owner and Global admin

Runner

Runner Registration

Allows runners to register to GitLab to be used

Should be only used to integrate the GitLab runners

Group Owner, Project Owner, Global admin

Admin

Impersonation token

A token meant to be used by the administrator to see what a given user sees and can see to debug issues. 

You should aim never to use these tokens, but when you have a question about visibility and need to debug, this is a very powerful token to help in admin work.

Global admin 

Why I love tokens

When we create modern IAM models, we usually start by enforcing Multi-Factor Authentication (MFA) and Single Sign-On (SSO) and limiting the technical accounts (also called service accounts) organizations have aiming to have control over the technical access of system. This practice prevents using APIs with just a username/password combo or by using some technical account that someone created that ends up being a bit too accessible. 

What we need is a convenient and secure way of identifying users and controlling access. Tokens are just the thing: they make access management super easy, even when we do not integrate the system to Active Directory or a comparable LDAP provider with active passwords synced to the system. Tokens are a great way of letting users automate steps without needing technical accounts and the extra complexity they bring to the IAM model. 

However, you need to take care of your tokens. Leaving tokens hanging around for too long will always lead to nasty surprises. We usually recommend expiring any access tokens after a maximum of 90 days, as longer expiry periods usually mean no one remembers the tokens have gone old. Furthermore, if old tokens can be freely used, there is little incentive to automate their usage with Hashicorp Vault or a comparable proper secret management solution. 

Tokens should also be rotated often enough to prevent unauthorized access due to leaking and ensure the teams that integrate with you automate the process of the token fetching.

Using tokens properly

Using tokens is not difficult, but you must take care to use the proper procedures and syntax. 

The table below provides guidance and examples for correct GitLab token usage. GitLab’s documentation for creating tokens is also pretty good (links in the table).

 Token

 Command examples

Trigger token

#export SECURE_TRIGGER_TOKEN=<token>
#export MY_PROJECT_ID=<your project id>
#curl --fail --request POST --form token=$SECURE_TRIGGER_TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/$MY_PROJECT_ID/trigger/pipeline

Personal Access token

Token used normally as password

image (3)

Project/Group access token

Username: Token name 

Password: Token secret

image (4)-1

 

Deploy token

Username: Can be changed in UI, but defaults to gitlab+deploy-token-{n}

Password: Token secret

GitLab Deploy Token

image (1)

JWT tokens with Vault

JWT token addition to Vault 

vault write auth/jwt/config \
   jwks_url="https://gitlab.example.com/-/jwks" \
    bound_issuer="gitlab.example.com"

GitLab CI runner:

build-job:  
  stage: build
  secrets:
    DATABASE_PASSWORD:
      vault: db_admin/value@example2
  script:
    - echo "$DATABASE_PASSWORD"

Think least privilege!

GitLab offers many token types, but by default, you should always aim to use the following order when thinking about what kind of tokens you need to ensure you follow the least privilege principles:

  • Personal Access token
  • Project Deploy token
  • Group Deploy token
  • Project token
  • Group token
  • Global Deploy token
  • Global Access token

Getting started with tokens

My recommendation is to work with your teams to find what is the most suitable way to use GitLab tokens in your organization, but hopefully, this brief introduction gives you some idea of the many possibilities there are in GitLab.

 

If you want more guidance or some hands-on support for your GitLab token journey, check out our GitLab services.

 

Published: Jun 30, 2022

Updated: Nov 29, 2023

DevOpsEficode ROOTCI/CD