Skip to content

Commit

Permalink
Document TPM join method (#40864)
Browse files Browse the repository at this point in the history
* Add TPM to join method reference page

* Skeleton out the Linux/TPM guide

* Add yaml for join token

* Flesh out TPM joining guide

* Try var

* Add note on FIPS 140-2 compliance

* Add more vars

* ADd more background to how TPM joining works

* Clarify statement on most secure

* Add `tbot tpm identify` to cli reference

* Rename background to `how it works`

* Update docs/config.json

Co-authored-by: Paul Gottschling <[email protected]>

* Update docs/pages/includes/tpm-joining-background.mdx

Co-authored-by: Paul Gottschling <[email protected]>

* Update docs/pages/includes/tpm-joining-background.mdx

Co-authored-by: Paul Gottschling <[email protected]>

* Update docs/pages/includes/tpm-joining-background.mdx

Co-authored-by: Paul Gottschling <[email protected]>

* Update docs/pages/machine-id/deployment/linux-tpm.mdx

Co-authored-by: Paul Gottschling <[email protected]>

* Use Create A Bot template

* Expand TPM

* Reword tpm joining background

* Fix trailing ,

* Mention enterprise licensing

* cspell

---------

Co-authored-by: Paul Gottschling <[email protected]>
  • Loading branch information
strideynet and ptgott authored Apr 30, 2024
1 parent 590407d commit 472ff77
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 14 deletions.
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,10 @@
"title": "Linux Server",
"slug": "/machine-id/deployment/linux/"
},
{
"title": "Linux Server (TPM)",
"slug": "/machine-id/deployment/linux-tpm/"
},
{
"title": "Kubernetes",
"slug": "/machine-id/deployment/kubernetes/"
Expand Down
2 changes: 2 additions & 0 deletions docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"CTAP",
"CXXXXXXXXX",
"Callouts",
"cryptoprocessor",
"Cgajq",
"DBSIZE",
"DEBU",
Expand Down Expand Up @@ -682,6 +683,7 @@
"pidof",
"pkill",
"pkinit",
"PKIX",
"plugindata",
"portforward",
"postgresqlselfhosted",
Expand Down
51 changes: 51 additions & 0 deletions docs/pages/includes/provision-token/tpm-spec.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
```yaml
kind: token
version: v2
metadata:
# name identifies the token. When configuring a bot or node to join using this
# token, this name should be specified.
name: tpm-token
spec:
# For Machine ID and TPM joining, roles will always be "Bot" and
# join_method will always be "tpm".
roles: [Bot]
join_method: tpm

# bot_name specifies the name of the bot that this token will grant access to
# when it is used.
bot_name: tpm-demo

# tpm specifies the TPM join method specific configuration for this token.
tpm:
# ekcert_allowed_cas is a list of CA certificates that will be used to
# validate TPM EKCerts. These should be PEM wrapped.
#
# When specified, joining TPMs must present an EKCert signed by one of the
# specified CAs. TPMs that do not present an EKCert will be not permitted to
# join.
#
# When unspecified, TPMs will be allowed to join with either an EKCert or an
# EKPubHash.
ekcert_allowed_cas:
- |
-----BEGIN CERTIFICATE-----
... CA Certificate Data ...
-----END CERTIFICATE-----
# allow is a list of Rules, the presented TPM must match one allow rule to
# be permitted to join using this token.
allow:
# description is a human-readable description of the rule. It has no
# bearing on whether a TPM is allowed to join, but can be used to
# associate a rule with a specific host (e.g the asset tag of the server
# in which the TPM resides).
- description: "example-build-server-100"
# ek_public_hash is the SHA256 hash of the EKPub marshaled in PKIX format
# and encoded in hexadecimal. This value will also be checked when a TPM
# has submitted an EKCert, and the public key in the EKCert will be used
# for this check.
ek_public_hash: "d4b4example6fabfc568d74f2example6c35a05337d7af9a6example6c891aa6"
# ek_certificate_serial is the serial number of the EKCert in hexadecimal
# with colon separated nibbles. This value will not be checked when a TPM
# does not have an EKCert configured.
ek_certificate_serial: "01:23:45:67:89:ex:am:pl:e0:23:45:67:89:ab:cd:ef"
```
30 changes: 30 additions & 0 deletions docs/pages/includes/tpm-joining-background.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
The `tpm` join method is a secure way for Bots and Agents to authenticate with
the Teleport Auth Service without using any shared secrets. Instead of using a
hared secret, the unique identity of the host's Trusted Platform Module (TPM)
and public key cryptography is used to authenticate the host.

In environments where there is no other form of identity available to machines,
e.g on-prem, this is the most secure method for joining. It avoids the need to
distribute a shared secret as is needed for the `token` join method.

A Trusted Platform Module (TPM) is a secure, physical cryptoprocessor that is
installed on a host. TPMs can store cryptographic material and perform a number
of cryptographic operations, without exposing the cryptographic material to the
operating system. Each TPM has a unique key pair burned-in known as the
Endorsement Key (EK).

Some TPMs also contain an X.509 certificate for this key pair that is signed by
the manufacturer's CA. This is known as the EK Certificate (EKCert). This
certificate can be used by the TPM to prove to a third-party (who trusts the
manufacturer's CA) that the TPM is genuine and abides by the TPM specification.

When using the `tpm` join method, you must first query the TPM's public key and
then create a join token that explicitly allows this public key. Even if the
host operating system is reinstalled, the EK public key will not change, meaning
that the TPM will still be usable to join your Teleport cluster. If you have a
large number of hosts, it may make sense to use automation tooling such as
ansible to query the TPMs across your fleet and then generate join tokens.

<Admonition type="warning">
The `tpm` join method is currently not compatible with FIPS 140-2.
</Admonition>
29 changes: 15 additions & 14 deletions docs/pages/machine-id/deployment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,24 @@ and [Architecture](./architecture.mdx) to plan your deployment.
Read the following guides for how to deploy Machine ID on your cloud platform or
on-prem infrastructure.

|Platform|Installation method|Join method|
|---|---|---|
|[Linux](./deployment/linux.mdx)|Package manager or TAR archive|Static join token|
|[GCP](./deployment/gcp.mdx)|Package manager, TAR archive, or Kubernetes pod|Identity document signed by GCP|
|[AWS](./deployment/aws.mdx)|Package manager, TAR archive, or Kubernetes pod|Identity document signed by AWS|
|[Azure](./deployment/azure.mdx)|Package manager or TAR archive|Identity document signed by Azure|
|[Kubernetes](./deployment/kubernetes.mdx)|Kubernetes pod|Identity document signed by your Kubernetes cluster|
| Platform | Installation method | Join method |
|-------------------------------------------|-------------------------------------------------|-----------------------------------------------------|
| [Linux](./deployment/linux.mdx) | Package manager or TAR archive | Static join token |
| [Linux (TPM)](./deployment/linux-tpm.mdx) | Package manager or TAR archive | Attestation from TPM 2.0 |
| [GCP](./deployment/gcp.mdx) | Package manager, TAR archive, or Kubernetes pod | Identity document signed by GCP |
| [AWS](./deployment/aws.mdx) | Package manager, TAR archive, or Kubernetes pod | Identity document signed by AWS |
| [Azure](./deployment/azure.mdx) | Package manager or TAR archive | Identity document signed by Azure |
| [Kubernetes](./deployment/kubernetes.mdx) | Kubernetes pod | Identity document signed by your Kubernetes cluster |

### CI/CD

Read the following guides for how to deploy Machine ID on a continuous
integration and continuous deployment platform

|Platform|Installation method|Join method|
|---|---|---|
|[CircleCI](./deployment/circleci.mdx)|TAR archive|CircleCI-signed identity document|
|[GitLab](./deployment/gitlab.mdx)|TAR archive|GitLab-signed identity document|
|[GitHub Actions](./deployment/github-actions.mdx)|Teleport job available through the GitHub Actions marketplace|GitHub-signed identity document.|
|[Jenkins](./deployment/jenkins.mdx)|Package manager or TAR archive|Static join token|
|[Spacelift](./deployment/spacelift.mdx)|Docker Image|Spacelift-signed identity document|
| Platform | Installation method | Join method |
|---------------------------------------------------|---------------------------------------------------------------|------------------------------------|
| [CircleCI](./deployment/circleci.mdx) | TAR archive | CircleCI-signed identity document |
| [GitLab](./deployment/gitlab.mdx) | TAR archive | GitLab-signed identity document |
| [GitHub Actions](./deployment/github-actions.mdx) | Teleport job available through the GitHub Actions marketplace | GitHub-signed identity document. |
| [Jenkins](./deployment/jenkins.mdx) | Package manager or TAR archive | Static join token |
| [Spacelift](./deployment/spacelift.mdx) | Docker Image | Spacelift-signed identity document |
208 changes: 208 additions & 0 deletions docs/pages/machine-id/deployment/linux-tpm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
---
title: Deploying Machine ID on Linux (TPM)
description: How to install and configure Machine ID on a Linux host and use a TPM 2.0 for authentication
---

This page explains how to deploy Machine ID on a Linux host, and use the
secure identify of the onboard TPM 2.0 chip for authenticating with the
Teleport cluster.

The `tpm` join method requires a valid Teleport Enterprise license to be
installed on the cluster's Auth Service.

## How it works

(!docs/pages/includes/tpm-joining-background.mdx!)

## Prerequisites

(!docs/pages/includes/edition-prereqs-tabs.mdx!)

- (!docs/pages/includes/tctl.mdx!)
- A Linux host that you wish to install Machine ID onto, with a TPM2.0
installed.
- A Linux user on that host that you wish Machine ID to run as. In the guide,
we will use `teleport` for this.

## Step 1/5. Install `tbot`

**This step is completed on the Linux host.**

First, `tbot` needs to be installed on the VM that you wish to use Machine ID
on.

Download the appropriate Teleport package for your platform:

(!docs/pages/includes/install-linux.mdx!)

### Granting `tbot` access to the TPM device

If the user that will run `tbot` is not `root`, you will also need to configure
Linux to allow the user to access the TPM device.

The simplest way to solve this is to check if your distro ships with the `tss`
group and assign it the user. If that is not possible, or you are looking
for a different solution, we recommend creating udev rules similar to the ones
shipped by the [TPM2 Software Stack](
https://github.com/tpm2-software/tpm2-tss/blob/ede63dd1ac1f0a46029d457304edcac2162bfab8/dist/tpm-udev.rules#L4).

## Step 2/5. Create a Bot

(!docs/pages/includes/machine-id/create-a-bot.mdx!)

## Step 3/5. Create a `tpm` join token

With the Bot created, we now need to create a token. The token will be used by
`tbot` to authenticate as the Bot to the Teleport cluster.

### Determining the EKPub Hash or EKCert Serial for your TPM

First, you need to determine the characteristics of the TPM on the host that
you wish to use Machine ID on. These characteristics will then be used within
the allow rules of the join token to grant access to this specific host.

On the machine, run `tbot tpm identify`:

```code
$ tbot tpm identify
TPM Information
EKPub Hash: 6c5aada1c5abee6d869369a0example2fd2beb41c850d3f0227f029c4fffc4ba
EKCert Detected: true
EKCert Serial: 5e:cd:5f:8e
```

Take the long hexadecimal string after `EKPub Hash` and assign it to
<Var name="ek-public-hash" />. This uniquely identifies this TPM and will be
used in the join token.

### Obtaining the manufacturer CA

If in the previous step, `EKCert Detected` was `false`, then you can disregard
this section.

If in the previous step, `EKCert Detected` was `true`, then it is recommended
to obtain the manufacturer's CA certificate. This will allow the TPM to be
validated as legitimately manufactured as part of the join process.

Instructions for obtaining the EKCert CA will vary from TPM to TPM. Consult
your TPM's documentation for more information or contact your supplier.

### Creating the join token

Create a file named `bot-token.yaml`:

```yaml
kind: token
version: v2
metadata:
# name identifies the token. Try to ensure that this is descriptive.
name: <Var name="my-bot-token" />
spec:
# For Machine ID and TPM joining, roles will always be "Bot" and
# join_method will always be "tpm".
roles: [Bot]
join_method: tpm

# bot_name specifies the name of the bot that this token will grant access to
# when it is used.
bot_name: <Var name="my-bot" />

# tpm specifies the TPM join method specific configuration for this token.
tpm:
# ekcert_allowed_cas is a list of CA certificates that will be used to
# validate TPM EKCerts. These should be PEM wrapped.
#
# When specified, joining TPMs must present an EKCert signed by one of the
# specified CAs. TPMs that do not present an EKCert will be not permitted to
# join.
ekcert_allowed_cas:
- |
-----BEGIN CERTIFICATE-----
... CA Certificate Data ...
-----END CERTIFICATE-----
# allow is a list of Rules, the presented TPM must match one allow rule to
# be permitted to join using this token.
allow:
# description is a human-readable description of the rule. It has no
# bearing on whether a TPM is allowed to join, but can be used to
# associate a rule with a specific host (e.g the asset tag of the server
# in which the TPM resides).
- description: "example-server-100"
# ek_public_hash is the SHA256 hash of the EKPub marshaled in PKIX format
# and encoded in hexadecimal. This value will also be checked when a TPM
# has submitted an EKCert, and the public key in the EKCert will be used
# for this check.
ek_public_hash: "<Var name="ek-public-hash" />"
```
If your TPM includes an EKCert and you have obtained the manufacturer's CA,
replace the `ekcert_allowed_cas` section with the PEM wrapped CA certificate.
Otherwise, remove this section.

If you have multiple hosts that you wish to authenticate as the same Bot, you
can add additional rules the `allow` list, one for each host.

Apply this to your Teleport cluster using `tctl`:

```code
$ tctl create -f bot-token.yaml
```

## Step 4/5. Configure `tbot`

Create `/etc/tbot.yaml`:

```yaml
version: v2
proxy_server: example.teleport.sh:443
onboarding:
join_method: tpm
token: <Var name="my-bot-token" />
storage:
type: directory
path: /var/lib/teleport/bot
# outputs will be filled in during the completion of an access guide.
outputs: []
```

Replace:

- `example.teleport.sh:443` with the address of your Teleport Proxy.

### Prepare the storage directory

The `tbot` service requires a way to store its state, such as internal
credentials, across restarts. This is known as the storage destination.

For this example, we will use the directory `/var/lib/teleport/bot`.

As this directory will store the bots sensitive credentials, it is important
to protect it. To do this, you will configure the directory to only be
accessible to the Linux user which `tbot` will run as.

Execute the following, replacing `teleport` with the Linux user that you will
run `tbot` as:

```code
# Make the bot directory and assign ownership to teleport user
$ sudo mkdir -p /var/lib/teleport/bot
$ sudo chown teleport:teleport /var/lib/teleport/bot
```

### Create a systemd service

(!docs/pages/includes/machine-id/daemon.mdx!)

## Step 5/5. Configure outputs

(!docs/pages/includes/machine-id/configure-outputs.mdx!)

## Next steps

- Follow the [access guides](../access-guides.mdx) to finish configuring `tbot` for
your environment.
- Read the [TPM joining reference](../../reference/join-methods.mdx#trusted-platform-module-tpm)
to learn more about `tpm`joining.
- Read the [configuration reference](../reference/configuration.mdx) to explore
all the available configuration options.
- [More information about `TELEPORT_ANONYMOUS_TELEMETRY`.](../reference/telemetry.mdx)
12 changes: 12 additions & 0 deletions docs/pages/reference/cli/tbot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The primary commands for `tbot` are as follows:
| `tbot init` | Initialize a certificate destination directory for writes from a separate bot user, configuring either file or POSIX ACL permissions. |
| `tbot db` | Connects to databases using native clients and queries database information. Functions as a wrapper for `tsh`, and requires `tsh` installation. |
| `tbot proxy` | Allows for access to Teleport resources on a cluster using TLS Routing. Functions as a wrapper for `tsh`, and requires `tsh` installation. |
| `tbot tpm identify` | Output identifying information related to the TPM (Trusted Platform Module) detected on the system. |

## tbot db

Expand Down Expand Up @@ -189,6 +190,7 @@ using database proxies.
| `--renewal-interval` | Interval at which short-lived certificates are renewed; must be less than the certificate TTL. |
| `--join-method` | Method to use to join the cluster. Can be `token` or `iam`. |
| `--oneshot` | If set, quit after the first renewal. |

## tbot start

Starts the Machine ID client `tbot`, fetching and writing certificates to disk at a set interval.
Expand Down Expand Up @@ -241,3 +243,13 @@ $ tbot start \
</TabItem>
</Tabs>

## tbot tpm identify

Output identifying information related to the TPM (Trusted Platform Module)
detected on the system.

### Flags

| Flag | Description |
|----------------------|------------------------------------|
| `-d/--debug` | Enable verbose logging to stderr. |
Loading

0 comments on commit 472ff77

Please sign in to comment.