diff --git a/docs/config.json b/docs/config.json
index cc9f0c9a03b83..7aff183fc0dcf 100644
--- a/docs/config.json
+++ b/docs/config.json
@@ -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/"
diff --git a/docs/cspell.json b/docs/cspell.json
index 5d40a1c279a33..ebafcffeef288 100644
--- a/docs/cspell.json
+++ b/docs/cspell.json
@@ -37,6 +37,7 @@
"CTAP",
"CXXXXXXXXX",
"Callouts",
+ "cryptoprocessor",
"Cgajq",
"DBSIZE",
"DEBU",
@@ -682,6 +683,7 @@
"pidof",
"pkill",
"pkinit",
+ "PKIX",
"plugindata",
"portforward",
"postgresqlselfhosted",
diff --git a/docs/pages/includes/provision-token/tpm-spec.mdx b/docs/pages/includes/provision-token/tpm-spec.mdx
new file mode 100644
index 0000000000000..5ba8a6b021061
--- /dev/null
+++ b/docs/pages/includes/provision-token/tpm-spec.mdx
@@ -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"
+```
\ No newline at end of file
diff --git a/docs/pages/includes/tpm-joining-background.mdx b/docs/pages/includes/tpm-joining-background.mdx
new file mode 100644
index 0000000000000..1291a403b3b94
--- /dev/null
+++ b/docs/pages/includes/tpm-joining-background.mdx
@@ -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.
+
+
+The `tpm` join method is currently not compatible with FIPS 140-2.
+
\ No newline at end of file
diff --git a/docs/pages/machine-id/deployment.mdx b/docs/pages/machine-id/deployment.mdx
index a9acf98671cf2..f1724bd92970e 100644
--- a/docs/pages/machine-id/deployment.mdx
+++ b/docs/pages/machine-id/deployment.mdx
@@ -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 |
diff --git a/docs/pages/machine-id/deployment/linux-tpm.mdx b/docs/pages/machine-id/deployment/linux-tpm.mdx
new file mode 100644
index 0000000000000..82db23016d99b
--- /dev/null
+++ b/docs/pages/machine-id/deployment/linux-tpm.mdx
@@ -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
+. 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:
+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 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: ""
+```
+
+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:
+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)
\ No newline at end of file
diff --git a/docs/pages/reference/cli/tbot.mdx b/docs/pages/reference/cli/tbot.mdx
index 3c0314a32fc8b..104b60e460b2e 100644
--- a/docs/pages/reference/cli/tbot.mdx
+++ b/docs/pages/reference/cli/tbot.mdx
@@ -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
@@ -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.
@@ -241,3 +243,13 @@ $ tbot start \
+## 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. |
\ No newline at end of file
diff --git a/docs/pages/reference/join-methods.mdx b/docs/pages/reference/join-methods.mdx
index 5399b05d814a7..003c5ca065d28 100644
--- a/docs/pages/reference/join-methods.mdx
+++ b/docs/pages/reference/join-methods.mdx
@@ -121,6 +121,7 @@ Delegated join methods are:
- [`circleci`](#circleci-circleci)
- [`gitlab`](#gitlab-gitlab)
- [`kubernetes`](#kubernetes-kubernetes)
+- [`tpm`](#trusted-platform-module-tpm)
### Renewable vs non-renewable
@@ -152,6 +153,7 @@ Non-renewable join methods are:
- [`circleci`](#circleci-circleci)
- [`gitlab`](#gitlab-gitlab)
- [`kubernetes`](#kubernetes-kubernetes)
+- [`tpm`](#trusted-platform-module-tpm)
## Token resource reference
@@ -413,3 +415,13 @@ to contain the new Kubernetes singing keys (update the
- [Deploying Machine ID on Kubernetes](../machine-id/deployment/kubernetes.mdx)
+
+### Trusted Platform Module: `tpm`
+
+(!docs/pages/includes/tpm-joining-background.mdx!)
+
+(!docs/pages/includes/provision-token/tpm-spec.mdx!)
+
+
+- [Deploying Machine ID on Linux: TPM](../machine-id/deployment/linux-tpm.mdx)
+
\ No newline at end of file