Skip to main content

Impersonating Teleport Users

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 version 14.3.33 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool.

    Visit Installation for instructions on downloading tctl and tsh.

  • To check that you can connect to your Teleport cluster, sign in with tsh login, then verify that you can run tctl commands using your current credentials. tctl is supported on macOS and Linux machines. For example:
    $ tsh login --proxy=teleport.example.com [email protected]
    $ tctl status
    # Cluster teleport.example.com
    # Version 14.3.33
    # CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
    If you can connect to the cluster and run the tctl status command, you can use your current credentials to run subsequent tctl commands from your workstation. If you host your own Teleport cluster, you can also run tctl commands on the computer that hosts the Teleport Auth Service for full permissions.

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']

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
$ ssh -J [email protected]:3023 -p 3022 [email protected]
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")
$ 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"])

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.