# 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.

## How it works

A Teleport role allows a Teleport user to impersonate other roles or users. When a Teleport user authenticates with a role that allows impersonation, they can execute the `tctl auth sign` command to instruct the Teleport Auth Service to sign a certificate for another Teleport user. As with all Teleport user certificates, the certificate written by `tctl auth sign` includes the names of a Teleport user and that user's roles. TLS or SSH clients can then load the certificate in order to authenticate to Teleport as the impersonated user.

## Prerequisites

- A running Teleport cluster. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

- The `tctl` and `tsh` clients.

  Installing `tctl` and `tsh` clients

  1. Determine the version of your Teleport cluster. The `tctl` and `tsh` clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at `/v1/webapi/find` and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
     ```

  2. Follow the instructions for your platform to install `tctl` and `tsh` clients:

     **Mac**

     Download the signed macOS .pkg installer for Teleport, which includes the `tctl` and `tsh` clients:

     ```
     $ curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg
     ```

     In Finder double-click the `pkg` file to begin installation.

     ---

     DANGER

     Using Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-windows-amd64-bin.zip
     Unzip the archive and move the `tctl` and `tsh` clients to your %PATH%
     NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
     Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

* 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. For example, run the following command, assigning teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username:
  ```
  $ tsh login --proxy=teleport.example.com --user=email@example.com
  $ tctl status
  Cluster  teleport.example.com
  Version  19.0.0-dev
  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
```

---

TIP

You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

---

## 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`:

**Self-Hosted**

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

**Teleport Enterprise**

```
$ tsh login --proxy=mytenant.teleport.sh --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 jenkins@teleport.localhost:3023 -p 3022 jenkins@127.0.0.1
```

---

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")

```

Create the resources:

```
$ 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:

**Self-Hosted**

```
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
```

**Teleport Enterprise**

```
Once Alice logs in again, she will receive a new certificate with updated roles.
$ tsh login --proxy=mytenant.teleport.sh --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.

| Field                                             | Description                                                                                                            |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `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](https://goteleport.com/docs/reference/access-controls/predicate-language.md) guide for a more in depth explanation of the language.
