GitLab

The Conjur integration with GitLab creates a Docker image that includes a Go binary, which you can use to authenticate a JWT against Conjur to retrieve secrets. The secrets are returned to STDOUT and can be used in a GitLab CI pipeline.

This integration supports both GitLab Enterprise Edition and self-host GitLab.

Supported operating systems

Integrations are available for:

  • Alpine

  • Ubuntu

  • UBI-FIPS

Requirements

  • Docker

  • Go 1.20.2 or later

  • GitLab on Docker (gitlab/gitlab-ce:15.11.2-ce.0 or later)

  • GitLab Runner on Docker (gitlab/gitlab-runner:v15.8.2 or later)

  • Make sure that the Conjur CLI v8.x is installed.

Configure the Conjur-GitLab integration

This section describes how to set up GitLab to integrate with Conjur.

Step 1: Self-hosted GitLab only: Configure self-hosted GitLab on Docker

Skip this step if you are using GitLab Enterprise Edition.

  1. Copy the following code snippet to a text editor:

    #!/bin/bash
    #============ Variables ===============
    # Is sudo required to run docker/podman - leave empty if no need
    SUDO=
    # Using docker/podman
    CONTAINER_MGR=docker
    # Docker image URL
    CONTAINER_IMG=gitlab/gitlab-ce:latest
    # GitLab URL (if available, use the external hostname)
    GITLAB_ADDRESS=
    # GitLab HTTP port
    GITLAB_HTTP_PORT=9080
    # GitLab admin user password
    GITLAB_ROOT_PASSWORD=pqr@123
    #============ Deploying GitLab ===============
    $SUDO $CONTAINER_MGR run --detach \
      --hostname "$GITLAB_ADDRESS" \
      --publish "$GITLAB_HTTP_PORT":$GITLAB_HTTP_PORT \
      --name gitlab-server \
      --restart always \
      --shm-size 1gb \
      --env GITLAB_ROOT_PASSWORD="$GITLAB_ROOT_PASSWORD" \
      --env GITLAB_OMNIBUS_CONFIG="external_url 'http://$GITLAB_ADDRESS:$GITLAB_HTTP_PORT/';" \
      "$CONTAINER_IMG"
  2. Provide the following values:

    Parameter

    Description

    GITLAB_ADDRESS

    The URL of your GitLab environment, without HTTP/HTTPS. For example, gitlab.example.com.

    GITLAB_HTTP_PORT

    The GitLab port number.

    Default: 9080

  3. Run the script.

Step 2: Configure self-hosted GitLab Runner on Docker

  1. Create a project in GitLab.

  2. In the project, go to SettingsCI/CDRunner.

  3. From the Project runner section, note the GitLab Runner registration token.

  4. Copy the following code snippet to a text editor:

    #!/bin/bash
    #============ Variables ===============
    # Is sudo required to run docker/podman - leave empty if no need
    SUDO=
    # Using docker/podman
    CONTAINER_MGR=docker
    # Docker image URL
    CONTAINER_IMG=gitlab/gitlab-runner:latest
    # GitLab Host
    GITLAB_HOST=$(hostname -f)
    # GitLab port
    GITLAB_PORT=9080
    # GitLab Instance Registration Token
    GITLAB_REGISTRATION_TOKEN=
    #============ Deploying GitLab Runner ===============
    $SUDO $CONTAINER_MGR volume create gitlab-runner-conjur-config
    $SUDO $CONTAINER_MGR run -d --name gitlab-runner-conjur --restart always \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v gitlab-runner-conjur-config:/etc/gitlab-runner \
        "$CONTAINER_IMG"
    # Registering GitLab runner
    $SUDO $CONTAINER_MGR run --rm -it -v gitlab-runner-conjur-config:/etc/gitlab-runner \
        "$CONTAINER_IMG" register -u "http://$GITLAB_HOST:$GITLAB_PORT" -r "$GITLAB_REGISTRATION_TOKEN" \
        --description "Demo Runner" -n --tag-list "conjur-demo" --executor docker --docker-image alpine:latest
  5. Provide the following values:

    Parameter

    Description

    GITLAB_REGISTRATION_TOKEN

    The GitLab Runner registration token that you obtained above.

    docker-image

    The relevant Docker image for your environment.

    Example: alpine:latest

  6. Run the script.

Set up the Conjur resources

Before using the plugin, you need to define the following resources in Conjur:

  • If you want to use JWT authentications, you need to set up a JWT Authenticator (requires Conjur admin permissions. )

  • A workload identity in Conjur that represents your workload.

  • For information and guidelines about setting up JWT authentication , see JWT Authentication.

  • All policies in the examples below are samples only, for the purpose of this documentation. You can copy the samples and apply to your own environment.

Step 1: Define a JWT Authenticator

  1. Copy the following policy into a text editor:

    - !policy
      id: conjur/authn-jwt/gitlab
      annotations:
        description: JWT Authenticator web service for gitlab
        gitlab: true
      body:
        # Create the conjur/authn-jwt/gitlab web service
        - !webservice
    
        # Optional: Uncomment any or all of the following variables:
        # * token-app-propery
        # * identity-path  conjur/authn-jwt/gitlab/identity-path  gitlab/root
        # * issuer
        # identity-path is always used together with token-app-property
        # however, token-app-property can be used without identity-path
    
        - !variable
          id: token-app-property
          annotations:
            description: JWT Authenticator bases authentication on claims from the JWT. You can base authentication on identifying clams such as the name, the user, and so on. If you can customize the JWT, you can create a custom claim and base authentication on this claim.
    
        - !variable
          id: identity-path
          annotations:
            description: JWT Authenticator bases authentication on a combination of the claim in the token-app-property and the full path of the workload identity (host) in Conjur. This variable is optional, and is used in conjunction with token-app-property. It has no purpose when standing alone.
    
        - !variable
          id: issuer
          annotations:
            description: JWT Authenticator bases authentication on the JWT issuer. This variable is optional, and is relevant only if there is an iss claim in the JWT. The issuer variable and iss claim values must match.
    
        - !variable
          id: jwks-uri
    
          ## Group of hosts that can authenticate using this JWT Authenticator
        - !group
          id: apps
    
        # Permit the consumers group to authenticate to the authn-jwt/gitlab web service
        - !permit
          role: !group apps
          privilege: [ read, authenticate ]
          resource: !webservice
    
        # Create a web service for checking authn-jwt/gitlab status
        - !webservice
          id: status
    
        # Group of users who can check the status of authn-jwt/gitlab
        - !group
          id: operators
    
        # Permit group to check the status of authn-jwt/gitlab
        - !permit
          role: !group operators
          privilege: read
          resource: !webservice status
  2. Save the policy as authn-jwt-gitlab.yml, and use the Conjur CLI to load the policy into root:

    conjur policy load -f /path/to/file/authn-jwt-gitlab.yml -b root
  3. Using the Conjur CLI, populate the variables as follows:

    conjur variable set -i conjur/authn-jwt/gitlab/token-app-property -v 'namespace_path'
    conjur variable set -i conjur/authn-jwt/gitlab/identity-path -v 'gitlab-apps'
    conjur variable set -i conjur/authn-jwt/gitlab/issuer -v 'https://gitlab.com'
    conjur variable set -i conjur/authn-jwt/gitlab/jwks-uri -v 'https://gitlab.com/-/jwks/'

    For GitLab self-hosted, for the issuer and jwks-uri, use http://gitlab.example.com:9080 (instead of https://gitlab.com).

  4. Enable the JWT Authenticator in Conjur.

    For details, see Allowlist the authenticators.

Step 2: Define a workload identity in Conjur to represent your workload

In this step, you define your workload in Conjur.

In the sample policy below, we use information from the following GitLab token for JWT authentication.

  1. Define a workload (host) policy that uses your JWT Authenticator to authenticate to Conjur.

    Copy the following policy into a text editor:

    - !policy
      id: gitlab-apps
      body:
    
          # Group of hosts that can authenticate using this JWT Authenticator
        - !group
    
            # `gitlab_name` is the primary identifying claim
        - &hosts
          - !host
            id: namespace1
            annotations:
              description: Host identity for authn-jwt-gitlab project in root namespace within GitLab
              authn-jwt/gitlab/ref: master
              authn-jwt/gitlab/project_path: namespace1/jwt-example
    
        # Grant all hosts in collection above to be members of projects group
        - !grant
          role: !group
          members: *hosts
    
    - !grant
      role: !group conjur/authn-jwt/gitlab/apps
      member: !group gitlab-apps
  2. Save the policy as authn-jwt-hosts.yml, and use the Conjur CLI to load it into root:

    conjur policy load -f /path/to/file/authn-jwt-hosts.yml -b root

Step 3: Give your workload access to the secrets synced from your PAM solution

In the following example, we assume that secrets in the my-secrets-safe Safe have been synced to Conjur from Privilege Cloud.

  1. Copy the following policy to a text editor:

    - !grant
      role: !group vault/my-secrets-safe/delegation/consumers
      member: !group gitlab-apps
  2. Save the policy as secret-access.yml, and use the Conjur CLI to load it into root:

    conjur policy load -f /path/to/file/secret-access.yml -b root

Usage

Once GitLab has been set up to integrate with Conjur, and your Conjur resources are in place, the integration can run.

To set up your pipeline to fetch secrets from Conjur:

For GitLab self-hosted, in the samples snippets below replace https://gitlab.com with http://gitlab.example.com:9080

  1. Choose the relevant GitLab Runner Docker container image for your environment. The following images are available:

    • authn-jwt-gitlab:alpine-1.0.0

    • authn-jwt-gitlab:ubuntu-1.0.0

    • authn-jwt-gitlab:ubi-1.0.0

  2. Include the image in your GitLab CI Pipeline file.

    For example, for Alpline, this would look as follows:

    alpine:
      id_tokens:
        ID_TOKEN_1:
          aud: https://gitlab.com
      variables:
        CONJUR_AUTHN_JWT_TOKEN: $ID_TOKEN_1
      image: authn-jwt-gitlab:alpine-1.0.0
  3. Optional: Tag the job in the GitLab CI Pipleline file with the proper tag to run on the GitLab Runner.

  4. Set up the following environment variables in the GitLab CI pipeline file for the GitLab runner Docker container to consume:

    • CONJUR_APPLIANCE_URL

    • CONJUR_ACCOUNT

    • CONJUR_AUTHN_JWT_SERVICE_ID

    • CONJUR_AUTHN_JWT_TOKEN

    • CONJUR_SECRET_ID

    • CONJUR_SSL_CERTIFICATE or CONJUR_CERT_FILE (if you're using a self-signed certificate to connect to Conjur)

    The following is an example of a binary that you can use in a job executed on GitLab Runner:

    variables:
      CONJUR_APPLIANCE_URL: "https://conjur-server"
      CONJUR_ACCOUNT: "conjur"
      CONJUR_AUTHN_JWT_SERVICE_ID: "gitlab"
    
    alpine:
      id_tokens:
        ID_TOKEN_1:
          aud: https://gitlab.com
      variables:
        CONJUR_AUTHN_JWT_TOKEN: $ID_TOKEN_1
      image: cyberark/authn-jwt-gitlab:alpine-1.0.0
      script:
        - export TEST_USERNAME=$(CONJUR_SECRET_ID="/vault/my-safe-secrets/username" /authn-jwt-gitlab)
        - export TEST_PASSWORD=$(CONJUR_SECRET_ID="/vault/my-safe-secrets/password" /authn-jwt-gitlab)
  5. Recommended: In GitLab, check your project's job results.