-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2d3c03f
commit 71543bc
Showing
5 changed files
with
307 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,299 @@ | ||
--- | ||
title: Impersonating Teleport Users | ||
description: How to issue short-lived certs on behalf of Teleport users using impersonation. | ||
--- | ||
|
||
# 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 | ||
|
||
- Installed [Teleport](../getting-started.mdx) or [Teleport Cloud](../../cloud.mdx) >= {{teleport_version}} | ||
- [Tctl admin tool](https://goteleport.com/teleport/download) >= {{teleport_version}} | ||
|
||
Verify that your Teleport client is connected: | ||
|
||
```bash | ||
$ tctl status | ||
Cluster acme.example.com | ||
Version 6.0.2 | ||
Host CA never updated | ||
User CA never updated | ||
Jwt CA never updated | ||
CA pin sha256:e63c7c44be468d37a5b0276b70e9d10b17f24f4be19d6b579810fc94eaa31783 | ||
``` | ||
|
||
## Step 1/3 Create a CI/CD user | ||
|
||
First, let's create a user `jenkins`. Notice parameter `max_session_ttl` that limits | ||
cert duration for this user at 10 days. As a rule of thumb, the shorter the TTL, the better. | ||
|
||
Save this file as `jenkins.yaml` and create a user and a role: | ||
|
||
```yaml | ||
kind: role | ||
version: v3 | ||
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 | ||
|
||
# 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'] | ||
``` | ||
<Admonition | ||
type="note" | ||
title="Audit" | ||
> | ||
Here and below follow along and create yaml resources using `tctl create -f`: | ||
|
||
```bash | ||
$ tctl create -f jenkins.yaml | ||
``` | ||
</Admonition> | ||
|
||
## Step 2/3 Create an Impersonator | ||
|
||
Let's create a role `impersonator`. Save this role as `impersonator.yaml`: | ||
|
||
```yaml | ||
kind: role | ||
version: v3 | ||
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 | ||
# 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 an interactive user `alice` who can access the cluster | ||
and impersonate `jenkins`. We assigned a preset `access` role that allows users to access clusters for | ||
Alice's convenience. | ||
|
||
```bash | ||
$ tctl users add alice --roles=impersonator,access | ||
``` | ||
|
||
Alice can login using `tsh` and issue a cert for `jenkins`: | ||
|
||
```bash | ||
$ tsh login --proxy=teleport.localhost:3080 --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: | ||
|
||
```bash | ||
# 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] | ||
``` | ||
|
||
<Admonition | ||
type="note" | ||
title="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`. | ||
</Admonition> | ||
### 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 `jenkins` role allows it. A certificate's TTL issued using impersonation is limited to the `max_session_ttl` of the roles being impersonated. | ||
- Even in case if `jenkins` role could impersonate some other roles, Alice would not be able | ||
to use this permission. Teleport prevents impersonating users recursively. | ||
- 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. | ||
## Step 3/3 Dynamic Impersonation | ||
Sometimes you don't know in advance what roles will be created by the system. | ||
You can use `where` condition to allow one role to impersonate other roles | ||
based on matching labels. | ||
Save the role `security-impersonator` in a file `security-impersonator.yaml` and create it using `tctl`. | ||
```yaml | ||
kind: role | ||
version: v3 | ||
metadata: | ||
name: security-impersonator | ||
spec: | ||
options: | ||
max_session_ttl: 10h | ||
# Allow security-impersonator to impersonate any user and role with 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: | ||
'*': '*' | ||
``` | ||
|
||
```bash | ||
$ 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`. | ||
|
||
Create a user and a role `security-scanner`. Save a file `security-scanner.yaml` and create user and group: | ||
|
||
```yaml | ||
kind: role | ||
version: v3 | ||
metadata: | ||
name: 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'] | ||
``` | ||
Alice can issue certificates for a security scanner: | ||
``` bash | ||
$ tctl auth sign --user=security-scanner --format=openssh --out=security-scanner --ttl=10h | ||
``` | ||
|
||
**Matching user traits** | ||
|
||
We can make the `security-impersonator` role more flexible by matching source user and target role parameters: | ||
|
||
```yaml | ||
kind: role | ||
version: v3 | ||
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: | ||
'*': '*' | ||
``` | ||
This role will work with SSO users, but we can test locally, by updating Alice's account | ||
entry with traits: | ||
```yaml | ||
kind: user | ||
version: v2 | ||
metadata: | ||
name: alice | ||
spec: | ||
traits: | ||
group: ['security', 'devops'] | ||
roles: | ||
- security-impersonator | ||
- access | ||
``` | ||
```bash | ||
# 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: | ||
|
||
<table> | ||
<th> | ||
<td>Variable or Function</td> | ||
<td>Description</td> | ||
</th> | ||
<tr> | ||
<td>`user.spec.traits`</td> | ||
<td>Access traits of local or SSO user.</td> | ||
</tr> | ||
<tr> | ||
<td>`contains(list, var)`</td> | ||
<td>Checks whether list contains variable</td> | ||
</tr> | ||
<tr> | ||
<td>`equals(var, var)`</td> | ||
<td>Checks whether one variable is equal another</td> | ||
</tr> | ||
</table> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters