Fork me on GitHub

Teleport

Impersonating Teleport Users

Improve

Sometimes users need to create short-lived certificates for non-interactive users, for example, CI/CD systems. Your programs interacting with Teleport may need to create their own authentication as well. Teleport's impersonation allows users and robots to create short-lived certs for other users and roles.

Let's explore how interactive user Alice can create credentials for a non-interactive CI/CD user Jenkins and a security scanner.

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 >= 11.0.3.

    tctl version

    Teleport v11.0.3 go1.19

    tsh version

    Teleport v11.0.3 go1.19

    See Installation for details.

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

  • The tctl admin tool and tsh client tool version >= 11.0.3, which you can download by visiting the customer portal.

    tctl version

    Teleport v11.0.3 go1.19

    tsh version

    Teleport v11.0.3 go1.19

  • A Teleport Cloud account. If you do not have one, visit the sign up page to begin your free trial.

  • The tctl admin tool and tsh client tool version >= 10.3.8. To download these tools, visit the Downloads page.

    tctl version

    Teleport v10.3.8 go1.19

    tsh version

    Teleport v10.3.8 go1.19

To 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 11.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.

To connect to Teleport, log in to your cluster using tsh, then use tctl remotely:

tsh login --proxy=myinstance.teleport.sh [email protected]
tctl status

Cluster myinstance.teleport.sh

Version 10.3.8

CA pin sha256:sha-hash-here

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

Step 1/3: Create a CI/CD user and corresponding role

First, we will create a role called jenkins. Notice the max_session_ttl parameter, which limits the cert duration for certificates issued to users with this role. As a rule of thumb, the shorter the TTL, the better.

We will also create a user also named jenkins and assign the role to the user.

Save this file as jenkins.yaml:

kind: role
version: v5
metadata:
  name: jenkins
spec:
  # SSH options used for user sessions
  options:
    # max_session_ttl defines the TTL (time to live) of SSH certificates
    # issued to the users with this role.
    max_session_ttl: 240h

  # The allow section declares a list of resource/verb combinations that are
  # allowed for the users of this role. By default, nothing is allowed.
  allow:
    logins: ['jenkins']
    node_labels:
      '*': '*'
---
kind: user
version: v2
metadata:
  name: jenkins
spec:
  roles: ['jenkins']

Create the resources:

tctl create -f jenkins.yaml

Step 2/3: Create an impersonator role

Next, we will create a role called impersonator. Users with this role will be permitted to impersonate the jenkins user and role.

Save this role definition as impersonator.yaml:

kind: role
version: v5
metadata:
  name: impersonator
spec:
  # SSH options used for user sessions
  options:
    # max_session_ttl defines the TTL (time to live) of SSH certificates
    # issued to the users with this role.
    max_session_ttl: 10h

  # The allow section declares a list of resource/verb combinations that are
  # allowed for the users of this role. by default nothing is allowed.
  allow:
    impersonate:
      users: ['jenkins']
      roles: ['jenkins']

  # The deny section uses the identical format as the 'allow' section.
  # The deny rules always override allow rules.
  deny:
    node_labels:
      '*': '*'

Create the role resource:

tctl create -f impersonator.yaml

Next, create an interactive user named alice and assign the impersonator role so that alice can impersonate jenkins.

Access Role

We also assign the preset access role that allows users to access clusters for Alice's convenience.

tctl users add alice --roles=impersonator,access

Step 3/3: Use impersonation to issue a certificate

Alice can log in using tsh and issue a cert for jenkins:

tsh login --proxy=proxy.example.com --user=alice --auth=local
tctl auth sign --user=jenkins --format=openssh --out=jenkins --ttl=240h

Here is an example of how Alice can use the keys:

Start a fresh SSH agent for this session

eval $(ssh-agent)

Adds cert to the agent

ssh-add jenkins

ssh into the node as jenkins

Audit

Teleport's session.start event will capture an action done by alice who is impersonating jenkins.

session.start event:session.start impersonator:alice login:jenkins user:jenkins

The SSH certificate issued for jenkins contains information about impersonator - alice.

Advanced

Impersonation Rules

To prevent unintended consequences, Teleport defines the following impersonation rules:

  • Even though Alice's max_session_ttl is 10 hours, she can issue a cert with a longer TTL of 240 hours, because the jenkins role allows it. A certificate's TTL issued using impersonation is extended to the maximum TTL of the roles being impersonated.
  • Even if the jenkins role could impersonate some other roles, Alice would not be able to use this permission. Teleport prevents recursive impersonation.
  • Alice can get a new jenkins certificate with the same TTL, but with the metadata updated, for example, to point to a different Teleport leaf cluster. Teleport allows impersonated users to renew their certificates with the reduced scope of the certificate.

Dynamic Impersonation

Sometimes you don't know in advance what roles will be created by the system.

You can use the where condition to allow one role to impersonate other roles based on matching labels.

For example, suppose you wanted to define a security-impersonator role that allowed the impersonation of any users or roles with the label group: security. This could be accomplished with the following role definition:

kind: role
version: v5
metadata:
  name: security-impersonator
spec:
  options:
    max_session_ttl: 10h

  # security-impersonator can impersonate any user or role with the 'group: security' label
  allow:
    impersonate:
      users: ['*']
      roles: ['*']
      where: >
        equals(impersonate_role.metadata.labels["group"], "security") && 
        equals(impersonate_user.metadata.labels["group"], "security")

  # The deny section uses the identical format as the 'allow' section.
  # The deny rules always override allow rules.
  deny:
    node_labels:
      '*': '*'
tctl create -f security-impersonator.yaml
tctl users update alice --set-roles=security-impersonator,access

Alice can now impersonate any role and user with a label group: security.

Now suppose we need to create another machine user for a security scanning tool. Create a user and a role security-scanner using the following template:

kind: role
version: v5
metadata:
  name: security-scanner
  labels:
    group: security
spec:
  options:
    max_session_ttl: 10h

  allow:
    logins: ['root']
    node_labels:
      '*': '*'
---
kind: user
version: v2
metadata:
  name: security-scanner
  labels:
    group: security
spec:
  roles: ['security-scanner']

Even though this role was created after Alice's user was configured, Alice can issue certificates for the security-scanner user because it is labeled with the group: security label.

tctl auth sign --user=security-scanner --format=openssh --out=security-scanner --ttl=10h

Matching user traits

We can also define impersonation rules by matching against user traits.

Here we updated the security-impersonator role to allow for the impersonation of any other users or roles where the group user trait contains the same value as the label on the role and/or user to impersonate:

kind: role
version: v5
metadata:
  name: security-impersonator
spec:
  options:
    max_session_ttl: 10h

  allow:
    impersonate:
      users: ['*']
      roles: ['*']
      where: >
        contains(user.spec.traits["group"], impersonate_role.metadata.labels["group"]) && 
        contains(user.spec.traits["group"], impersonate_user.metadata.labels["group"])

  # The deny section uses the identical format as the 'allow' section.
  # The deny rules always override allow rules.
  deny:
    node_labels:
      '*': '*'

While user traits typically come from an external identity provider, we can test with local user alice by manually updating Alice's account with traits.

kind: user
version: v2
metadata:
  name: alice
spec:
  traits:
    group: ['security', 'devops']
  roles:
  - security-impersonator
  - access

Since Alice's group trait contains security, and the security-scanner user has a label of group: security, Alice will be able to impersonate the security scanner.

Alice will need to log in again to receive the newly updated traits:

Once Alice logs in again, she will receive a new certificate with updated roles.

tsh login --proxy=teleport.example.com --user=alice --auth=local

Alice can now get a certificate for the security scanner

tctl auth sign --user=security-scanner --format=openssh --out=security-scanner --ttl=10h

Filter fields

Here is an explanation of the fields used in the where conditions within this guide.

FieldDescription
user.spec.traits["group"]The list of traits from a local or SSO user where the group trait typically comes from an external identity provider
impersonate_role.metadata.labels["<label key>"]The label value given the label key from a role to impersonate
impersonate_user.metadata.labels["<label key>"]The label value given the label key from a user to impersonate

Check out our predicate language guide for a more in depth explanation of the language.