$CI_JOB_TOKEN on protected branch permission issues?

Problem to solve

I am trying to use docker login with $CI_JOB_TOKEN as password. However it keeps returning:

Error response from daemon: Get "https://registry.gitlab.com/v2/": unauthorized: HTTP Basic: Access denied. If a password was provided for Git authentication, the password was incorrect or you're required to use a token instead of a password. If a token was provided, it was either incorrect, expired, or improperly scoped.

The pipeline is triggered when a branch is merged onto a protected default branch. The job works on an unprotected branch so I assume it’s some form of permission problem.

I have added the group to the CI/CD job token allowlist and have selected “Only this project and any groups and projects in the allowlist”.

2FA is enabled for all users

Configuration

containerize:
  stage: container
  needs: [obfuscate]
  image: docker
  services:
    - docker:dind
  rules:
    - if: $CI_COMMIT_TAG
      when: never # Do not run this job when a tag is created manually
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
  before_script:
    - echo "$CI_JOB_TOKEN" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
  script:
    - echo $ENV_PROD
    # File is outside of build context, so make local copy.
    - cp $ENV_PROD .env
    - docker build -t $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_REF_SLUG
      --build-arg APP_PORT:APP_PORT .
    - docker push $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_REF_SLUG
    - docker tag $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_REF_SLUG $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_SHORT_SHA
    - docker push $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_SHORT_SHA

Versions

  • Self-managed
  • GitLab.com SaaS
  • Dedicated
  • Self-hosted Runners

Took a few days of Googling and reading docs but I finally got it to work.

For anyone in the future reading this, don’t use the CI_JOB_TOKEN.
Create a deploy token for your project.
Copy the username & password (can’t be retrieved after page refresh).
Create a new CI/CD variable for each of these.
Call them CI_DEPLOY_USER & CI_DEPLOY_PASSWORD.
Make them protected IF you intend to use them on a protected branch.
Set the permissions to which you want.
Change the login in your YAML script to

- echo "$CI_DEPLOY_PASSWORD" | docker login $CI_REGISTRY -u $CI_DEPLOY_USER --password-stdin

Imo there are too many kinds of tokens and all different kind of ways to configure them that it just becomes a confusing mess for the inexperienced.

Deploy tokens | GitLab
How to use the deploy token correctly - GitLab CI/CD - GitLab Forum
How do I get Docker registry username and password in gitlab.com? - Stack Overflow (2nd answer which lead me into the right direction)