Fork me on GitHub
Teleport

Impersonating Teleport Users

Impersonation

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

Verify that your Teleport client is connected:

$ tctl status

# Cluster  tele.example.com
# Version  7.1.3
# CA pin   sha256:sha-hash-here
Connecting to the cloud

To try this flow in the cloud, login into your cluster using tsh, then use tctl remotely:

$ tsh login --proxy=myinstance.teleport.sh
$ tctl status

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

First, let's 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.

Next, we'll create a user also named jenkins and assign the role to the user.

Save this file as jenkins.yaml to create the user and role:

kind: role
version: v4
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']
Audit

Here and below follow along and create yaml resources using tctl create -f:

tctl create -f jenkins.yaml

Step 2/3: Create an impersonator role

Let's create a role 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: v4
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:
      '*': '*'

Next, create an interactive user 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 login using tsh and issue a cert for jenkins:

tsh login --proxy=teleport.localhost --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 metadata updated, for example pointing 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 folowing role definition:

kind: role
version: v4
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: v4
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 update 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: v4
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 Alices'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.

Login
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

Here is a summary of variables and functions we used in this guide:

Variable or Function Description
user.spec.traits Access traits of local or SSO user.
contains(list, var) Checks whether list contains variable
equals(var, var) Checks whether one variable is equal another
Have a suggestion or can’t find something?
IMPROVE THE DOCS