Fork me on GitHub

Teleport

Using Machine ID with GitLab CI

Improve

Machine ID for GitLab is available starting from Teleport v12.2.

In this guide, you will use Teleport Machine ID to allow a GitLab pipeline to securely connect to a Teleport SSH node without the need for long-lived secrets.

Machine ID for GitLab works with GitLab's cloud-hosted option and with self-hosted GitLab installations. The minimum supported GitLab version is 15.7.

This mitigates the risk of long-lived secrets such as passwords or SSH private keys being exfiltrated from your GitLab organization and provides many of the other benefits of Teleport such as auditing and finely-grained access control.

Prerequisites

  • A running Teleport cluster. For details on how to set this up, see one of our Getting Started guides.

  • The tctl admin tool and tsh client tool version >= 13.0.3.

    tctl version

    Teleport v13.0.3 go1.20

    tsh version

    Teleport v13.0.3 go1.20

    See Installation for details.

  • A running Teleport Enterprise cluster. For details on how to set this up, see our Enterprise Getting Started guide.

  • The Enterprise tctl admin tool and tsh client tool version >= 13.0.3, which you can download by visiting your Teleport account.

    tctl version

    Teleport Enterprise v13.0.3 go1.20

    tsh version

    Teleport v13.0.3 go1.20

Cloud is not available for Teleport v.
Please use the latest version of Teleport Enterprise documentation.
  • Make sure you can connect to Teleport. Log in to your cluster using tsh, then use tctl remotely:
    tsh login --proxy=teleport.example.com [email protected]
    tctl status

    Cluster teleport.example.com

    Version 13.0.3

    CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

    You can run subsequent tctl commands in this guide on your local machine.

    For full privileges, you can also run tctl commands on your Auth Service host.

  • A running instance of the Teleport SSH Service registered with your Teleport cluster. For instructions on setting this up, see the Getting Started Guide. The SSH node must include a user you want to grant access to. In this guide, we will call the SSH node my-node and the user ci-user. Replace these with values appropriate to your setup.
  • A GitLab project to connect to Teleport. This can either be on GitLab's cloud-hosted offering (gitlab.com) or on a self-hosted GitLab instance. When using a self-hosted GitLab instance, your Teleport Auth Server must be able to connect to your GitLab instance and your GitLab instance must be configured with a valid TLS certificate.

Step 1/3. Create a join token

To allow GitLab CI to authenticate to your Teleport cluster, you'll first need to create a join token. A GitLab join token contains allow rules that describe which pipelines can use that token in order to join the Teleport cluster. A rule can contain multiple fields, and any pipeline that matches all of the fields within a single rule is granted access.

In this example, you will create a token with a rule that grants access to any GitLab CI job within a specific GitLab project. Determine the fully qualified path of your GitLab project. This will include your username (or group) and the name of your project, e.g my-user/my-project.

Create a file named gitlab-token.yaml. Ensure you substitute any values as suggested by the comments in this example:

kind: token
version: v2
metadata:
  name: gitlab-demo
spec:
  # The Bot role indicates that this token grants access to a bot user, rather
  # than allowing a node to join. This role is built in to Teleport.
  roles: [Bot]
  join_method: gitlab
  # The bot_name indicates which bot user this token grants access to. This
  # should match the name of the bot that you create in step 2.
  bot_name: gitlab-demo
  gitlab:
    # domain should be the domain of your GitLab instance. If you are using
    # GitLab's cloud hosted offering, omit this field entirely.
    domain: gitlab.example.com
    # allow specifies rules that control which GitLab tokens will be accepted
    # by Teleport. Tokens not matching any allow rule will be denied.
    allow:
        # project_path should be the fully qualified path of your GitLab
        # project that you determined earlier. This will grant access to any
        # GitLab CI run in that project.
      - project_path: my-user/my-project

You can find a full list of the token configuration options for GitLab joining on the GitLab CI reference page.

Apply this to your Teleport cluster using tctl:

tctl create -f gitlab-token.yaml

Step 2/3. Create a Machine ID bot

With the join token created, the next step is to create the Machine ID bot that the token will grant access to.

In this example, the bot is given the preset access role. In a production environment, the principle of least privilege should be applied and you should create a role that grants the bot access to the precise resources that will be needed in your CI/CD pipeline.

From your workstation enter the following command, replacing theci-user value with a Linux user on the host that you want your GitHub Actions flow to be able to connect to:

tctl bots add gitlab-demo --roles=access --token=gitlab-demo --logins=ci-user

Step 3/3. Configure a GitLab Pipeline

With the bot and join token created, you can now create a GitLab pipeline that uses these to access a node in your cluster.

Create a file called .gitlab-ci.yml in the root of your repository. Replace:

  • teleport.example.com with the name of your Teleport cluster
  • teleport.example.com:443 with the public address and port of your Teleport Proxy
  • my-node and ci-user with the user and host you wish to connect to
stages:
  - deploy

deploy-job:
  stage: deploy
  id_tokens:
    # See https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html
    # for further explanation of the id_tokens configuration.
    TBOT_GITLAB_JWT:
      # An environment variable named TBOT_GITLAB_JWT must exist and contain
      # an ID token with an audience that matches your Teleport cluster's name.
      aud: teleport.example.com
  script:
    - cd /tmp
    - 'curl -O https://cdn.teleport.dev/teleport-v13.0.3-linux-amd64-bin.tar.gz'
    - tar -xvf teleport-v13.0.3-linux-amd64-bin.tar.gz
    - sudo ./teleport/install
    - 'tbot start --token=gitlab-demo --destination-dir=/tmp/tbot-user --data-dir=/tmp/tbot-data --auth-server=teleport.example.com:443 --join-method=gitlab --oneshot'
    - 'tsh -i /tmp/tbot-user/identity --proxy teleport.example.com:443 ssh [email protected] "echo $CI_JOB_ID >> ~/gitlab_run_log"'

Commit and push this to the repository. Check your GitLab CI status, and examine the log results from the commit for failure. If the job has succeeded, you should see a file in the home directory of ci-user called gitlab_run_log that includes the ID of the CI run.

Further steps

For more information about GitLab itself, read their documentation.

For more information about GitLab joining, read the GitLab CI reference page.

More information about TELEPORT_ANONYMOUS_TELEMETRY.