bartcode
bartcode

Reputation: 589

How can I securely push from a GitLab Runner KubernetesExecutor pod to a private container registry?

Goal

Build a CI/CD pipeline multiple GitLab repositories with a certain project structure can make use of. For this, a Docker container with Python code is built and subsequently securely pushed to Google Cloud's Container Registry.

Set up

Problem

How can I push the image to the Container Registry without adding a service account key to a Docker image (otherwise, please convince me this isn't bad practice)?

Code

.gitlab-ci.yml

services:
  - docker:19.03.1-dind

stages:
  - build

build:
  stage: build
  script:
    - docker build -t ${CONTAINER_REGISTRY}/pyton-container-test:latest .
    # This line is where I'd need to use `docker login`, I guess.
    - docker push ${CONTAINER_REGISTRY}/python-container-test:latest

values.yaml (Helm)

It's worth mentioning that the following environment variables are set by the GitLab Runner:

runners:
  env:
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://localhost:2375
    DOCKER_TLS_CERTDIR: ""
    CONTAINER_REGISTRY: eu.gcr.io/<project_id>

Direction of solution

I think I should be able to mount a secret from the Kubernetes cluster to the GitLab Runner build pod, but I can't seem to find a way to do that. Then, I should be able to add the following line into .gitlab-ci.yml:

cat mounted_secret.json | docker login -u _json_key --password-stdin https://eu.gcr.io

Setting up config.toml to use a secret volume should work. However, with a Helm chart this doesn't seem possible yet.

Notes

Upvotes: 1

Views: 1196

Answers (2)

agotfrid
agotfrid

Reputation: 597

You can add DOCKER_AUTH_CONFIG CI/CD variable with auth values from ~/.docker/config.json. The variable will look like this:

{
    "auths": {
        "northamerica-northeast1-docker.pkg.dev": {
            "auth": "{JSON key here}"
        },
        "us.gcr.io": {
            "auth": "{JSON key here}"
        }
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/19.03.13 (linux)"
    }
}

This way, next time your gitlab runner is trying to pull a docker image from private repo, it will be able to do so.

Upvotes: 2

bartcode
bartcode

Reputation: 589

It's not possible with the default Helm chart as provided by GitLab. However, there is a workaround when you customise theirs.

In templates/configmap.yaml, it's possible to edit the entrypoint. At the very end, the runner is started as follows:

# Start the runner
exec /entrypoint run --user=gitlab-runner \
     --working-directory=/home/gitlab-runner

For this to work, a config.toml is generated based upon the provided values.yaml (with the right Runner token). This means that right before this step, we could edit the config.toml to our needs. In my case, I simply added:

echo "    [[runners.kubernetes.volumes.secret]]" >> ${CONFIG_FILE}
echo "      name = \"{{ .Values.secretName }}\"" >> ${CONFIG_FILE}
echo "      mount_path = \"/keys\"" >> ${CONFIG_FILE}
echo "      read_only = true" >> ${CONFIG_FILE}

Where ${CONFIG_FILE} is /home/gitlab-runner/.gitlab-runner/config.toml.

Finally, you can deploy your GitLab Runner using:

$ helm install project_name -f values.yaml <path to chart>

Upvotes: 1

Related Questions