diff --git a/docs/img/infrastructure-as-code/terraform-cloud-variables.png b/docs/img/infrastructure-as-code/terraform-cloud-variables.png
new file mode 100644
index 0000000000000..cba8e494f4c07
Binary files /dev/null and b/docs/img/infrastructure-as-code/terraform-cloud-variables.png differ
diff --git a/docs/pages/admin-guides/infrastructure-as-code/terraform-provider.mdx b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider.mdx
index df189522e1811..052d8b5522b4d 100644
--- a/docs/pages/admin-guides/infrastructure-as-code/terraform-provider.mdx
+++ b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider.mdx
@@ -17,15 +17,16 @@ is executed. You must pick the correct guide for your setup:
| Guide | Use-case | How it works |
|---------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
-| [Run the Teleport Terraform provider locally](./terraform-provider/local.mdx) | This is the best way to get started with the Teleport terraform provider, write some initial Terraform code and get familiar with IaC. | You're using you local credentials to create a temporary bot, obtain short-lived credentials, and store them in environment variables. |
+| [Run the Teleport Terraform provider locally](./terraform-provider/local.mdx) | You are getting started with the Teleport Terraform provider and managing Teleport resources with IaC. | You use local credentials to create a temporary bot, obtain short-lived credentials, and store them in environment variables. |
+| [Run the Teleport Terraform provider on Terraform Cloud](./terraform-provider/terraform-cloud.mdx) | You're running on HCP Terraform (Terraform Cloud) or self-hosted Terraform Enterprise. | Terraform Cloud Workload Identity issues a proof of identity and the Teleport Terraform provider uses it to authenticate. |
| [Run the Teleport Terraform provider in CI or a cloud VM](./terraform-provider/ci-or-cloud.mdx) | You already have a working Terraform module configuring Teleport and want to run it in CI to benefit from review and audit capabilities from your versioning system (e.g. git). | You're using a proof provided by your runtime (CI engine, cloud provider) to prove your identity and join using MachineID. |
| [Run the Teleport Terraform provider on Spacelift](./terraform-provider/spacelift.mdx) | You already have a working Terraform module configuring Teleport and want to run it on the Spacelift platform. | You're using a proof provided by Spacelift to prove your identity and join using MachineID. |
| [Run the Teleport Terraform provider from a server](./terraform-provider/dedicated-server.mdx) | You have working Terraform code and want to run it on a dedicated server. The server is long-lived, like a bastion or a task runner. | You setup a MachineID daemon (`tbot`) that obtains and refreshes credentials for the Terraform provider. |
-| [Run the Teleport Terraform provider with long-lived credentials.](./terraform-provider/long-lived-credentials.mdx) | This method is discouraged as less secure than the 3 others. This should be used when none of the other methods work in your case (short-lived CI environments that don't have dedicated Teleport join methods). | You sign one long lived certificate allowing the Terraform provider to connect to Teleport. |
+| [Run the Teleport Terraform provider with long-lived credentials.](./terraform-provider/long-lived-credentials.mdx) | This method is discouraged as less secure than the others. This should be used when none of the other methods work in your case (short-lived CI environments that don't have dedicated Teleport join methods). | You sign one long lived certificate allowing the Terraform provider to connect to Teleport. |
## Resource guides
-Once you have a functional Teleport Terraform provider, you will want to configure your resources with it.
+Once you have a functional Teleport Terraform provider, you will want to configure your resources with it.
You can find the list of supported resources and their fields is
available [in the Terraform reference](../../reference/terraform-provider.mdx).
diff --git a/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/ci-or-cloud.mdx b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/ci-or-cloud.mdx
index 87810c8ee8cac..f105b2c2f52cf 100644
--- a/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/ci-or-cloud.mdx
+++ b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/ci-or-cloud.mdx
@@ -23,6 +23,9 @@ join method and token to the provider.
- [Kubernetes MachineID guide](../../../enroll-resources/machine-id/deployment/kubernetes.mdx)
- [TPM MachineID guide](../../../enroll-resources/machine-id/deployment/linux-tpm.mdx)
+HCP Terraform (Terraform Cloud) and self-hosted Terraform Enterprise are
+supported but require special configuration, so refer to our
+[dedicated guide](./terraform-cloud.mdx).
This guide does not cover running Teleport locally, on a dedicated server or on
@@ -289,7 +292,7 @@ Copy the `main.tf` file on the GCP VM you will run Terraform from.
-### Step 4/4. Run Terraform
+## Step 4/4. Run Terraform
This step shows minimal examples on how to run Terraform based on your environment. This code uses the default local
backend which is not fit for production purposes. Especially in CI, you must
diff --git a/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/terraform-cloud.mdx b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/terraform-cloud.mdx
new file mode 100644
index 0000000000000..cf1145ee2f314
--- /dev/null
+++ b/docs/pages/admin-guides/infrastructure-as-code/terraform-provider/terraform-cloud.mdx
@@ -0,0 +1,294 @@
+---
+title: Run the Teleport Terraform Provider on Terraform Cloud
+description: How to manage dynamic resources using the Teleport Terraform provider on HCP Terraform, Terraform Cloud, and Terraform Enterprise.
+---
+
+This guide demonstrates how to use the Terraform provider for Teleport using
+HCP Terraform or Terraform Enterprise.
+
+This guide does not cover running the Terraform provider locally, in other CI/CD
+environments, or in short-lived cloud VMs. In any of these cases, refer to a
+dedicated guide:
+
+- [Run the Terraform Provider in CI or cloud VMs](./ci-or-cloud.mdx)
+- [Run the Terraform Provider locally](./local.mdx)
+
+## How it works
+
+
+ Terraform Cloud joining with self-hosted Terraform Enterprise requires
+ Teleport Enterprise. Terraform Cloud joining with public HCP Terraform
+ (https://app.terraform.io) is supported in Teleport Community Edition.
+
+
+When running the Teleport Terraform provider on Terraform Cloud, you can use its
+built-in Machine ID support to dynamically authenticate to your Teleport cluster
+without any shared secrets. When run in this configuration, the Terraform
+provider proves its identity to the Teleport Auth Service using Terraform
+Cloud's [Workload Identity][tf-workload-id] tokens.
+
+While following this guide, you'll configure your Teleport cluster to accept
+join requests from Terraform Cloud runs and configure the provider to
+authenticate using the Terraform Cloud join method.
+
+Note that this guide applies to both the public HCP Terraform a.k.a. Terraform
+Cloud, as well as self-hosted Terraform Enterprise. This does **not** apply
+to Terraform or OpenTofu when run on other CI/CD platforms like Spacelift, so
+refer to our generic [CI and Cloud guide](./ci-or-cloud.mdx) to configure the
+provider in these environments.
+
+## Prerequisites
+
+(!docs/pages/includes/commercial-prereqs-tabs.mdx!)
+
+- (!docs/pages/includes/tctl.mdx!)
+- [Terraform >= (=terraform.version=)+](https://learn.hashicorp.com/tutorials/terraform/install-cli)
+
+ ```code
+ $ terraform version
+ # Terraform v(=terraform.version=)
+ ```
+
+ To import existing Teleport resources as Terraform resources, you must have
+ Terraform version `v1.5.0` or above.
+
+- An account and project on either the public Terraform Cloud SaaS or a
+ Terraform Enterprise instance
+
+- The Teleport Terraform provider, v16.4.0 or later
+
+## Step 1/4: Configure Terraform Cloud joining in Teleport
+
+To start, the Teleport Auth Service needs to be configured to accept join
+requests from Terraform Cloud runs. We'll do this by creating a bot named
+`terraform` which the Teleport Terraform provider will use in a later step.
+
+```yaml
+kind: bot
+version: v1
+metadata:
+ name: terraform
+spec:
+ # The terraform-provider role is a built-in role granting access to every
+ # resource supported by the terraform provider.
+ roles: ["terraform-provider"]
+```
+
+Create the bot from the new YAML manifest:
+
+```code
+$ tctl create -f terraform_bot.yaml
+bot 'terraform' has been created
+```
+
+Next, the new bot needs to be allowed to authenticate with Terraform Cloud
+Workload Identity credentials. Create a file named `terraform_token.yaml`
+with this content, depending on whether you are using Terraform Cloud or
+self-hosted Terraform Enterprise:
+
+
+
+ ```yaml
+ kind: token
+ version: v2
+ metadata:
+ name: terraform
+ spec:
+ roles: [Bot]
+ join_method: terraform_cloud
+ bot_name: terraform
+ terraform_cloud:
+ allow:
+ - organization_name: ExampleOrganization
+ project_name: example-project
+ workspace_name: example-workspace
+ ```
+
+
+
+ Teleport Enterprise is required to use Terraform Enterprise joining.
+
+
+ Self-hosted Terraform Enterprise installations will need to additionally
+ configure the `hostname` parameter:
+
+ ```yaml
+ kind: token
+ version: v2
+ metadata:
+ name: terraform
+ spec:
+ roles: [Bot]
+ join_method: terraform_cloud
+ bot_name: terraform
+ terraform_cloud:
+ hostname: terraform.example.com
+ allow:
+ - organization_name: ExampleOrganization
+ project_name: example-project
+ workspace_name: example-workspace
+ ```
+
+ This `hostname` value should match the `iss` parameter of the JWTs issued
+ to your Terraform Enterprise runs, without the `https://` prefix. For more
+ information, refer to the [Terraform Enterprise documentation][tf-workload-id].
+ Note that if `hostname` is not configured, it will default to the Terraform
+ Cloud issuer and join attempts will fail.
+
+
+
+This token, named `terraform`, allows Terraform Cloud runs to authenticate
+with Teleport when all 3 of the values allowed in the token match those
+of the job run by Terraform Cloud.
+
+Make sure to replace the organization, project, and workspace names to match
+your Terraform Cloud project or projects. If desired, the fields
+`organization_id`, `project_id`, and `workspace_id` can be used as well to
+specify exact resource IDs. The values must exactly match those shown in the
+Terraform Cloud dashboard.
+
+Note that each `allow` rule must specify at least an `organization_name` or
+`organization_id`, and at least one other option (workspace and/or project).
+If desired, all workspaces under a project can be allowed by leaving
+`workspace_name` (or `workspace_id`) unset. You can specify as many `allow`
+rules as you want, and at least one must match for a run to be able to join.
+
+Once finished, create the token:
+
+```code
+$ tctl create -f terraform_token.yaml
+token 'terraform' has been created
+```
+
+## Step 2/4: Configure Terraform Cloud to issue Workload Identity tokens
+
+Terraform Cloud needs to be configured to issue JWTs during runs. This only
+requires that an environment variable is set in the Terraform Cloud dashboard.
+To do so:
+
+1. Navigate to https://app.terraform.io/
+1. Navigate to your desired organization, project, and workspace
+1. From the workspace sidebar, select "Variables"
+1. Under "Workspace Variables", click the "Add variable" button
+1. Select the "Environment variable" ("env") category
+1. For the key, enter: `TFC_WORKLOAD_IDENTITY_AUDIENCE_TELEPORT`
+1. For the value, enter your Teleport cluster name. If using Teleport Enterprise
+ (Cloud), this would look like `example.teleport.sh`.
+1. If desired, enter a description. For example, "Workload identity token
+ request for Teleport"
+
+The end result should look like this:
+
+
+
+Once this variable is set, all subsequent runs in this workspace will be issued
+JWTs with the audience configured in the variable value, i.e.
+`example.teleport.sh` as shown here.
+
+## Step 3/4: Configure the Terraform Provider
+
+In your `provider.tf` or similar, configure the `teleport` provider:
+
+```hcl
+provider "teleport" {
+ addr = "example.teleport.sh:443"
+ join_method = "terraform_cloud"
+ join_token = "terraform"
+ audience_tag = "teleport"
+}
+```
+
+These parameters must be set:
+- `addr` should match the public hostname and port of your Teleport cluster
+- `join_method` should be `terraform_cloud`. Note that Terraform Enterprise also
+ uses the same join method, with a hostname as configured in Step 1.
+- `join_token` should match the name of the `token` resource created in Step #2
+- `audience_tag` should match the suffix on the key of the variable created in
+ the Terraform Cloud dashboard. For example, given the variable key
+ `TFC_WORKLOAD_IDENTITY_AUDIENCE_TELEPORT`, the audience tag should be
+ `teleport`.
+
+Be sure to remove any preexisting `identity_file_path`; it is replaced by
+`join_method` and `join_token`.
+
+For a complete example, consider this minimal `provider.tf`:
+
+```hcl
+terraform {
+ cloud {
+ organization = "ExampleOrganization"
+
+ workspaces {
+ name = "example-workspace"
+ }
+ }
+
+ required_providers {
+ teleport = {
+ source = "terraform.releases.teleport.dev/gravitational/teleport"
+ version = "(=teleport.plugin.version=)"
+ }
+ }
+}
+
+provider "teleport" {
+ addr = "example.teleport.sh:443"
+ join_method = "terraform_cloud"
+ join_token = "terraform"
+ audience_tag = "teleport"
+}
+
+resource "teleport_role" "test" {
+ version = "v7"
+ metadata = {
+ name = "test"
+ description = "Dummy role to validate Terraform Provider setup"
+ labels = {
+ test = "yes"
+ }
+ }
+}
+```
+
+## Step 4/4: Run Terraform
+
+You should now be able to perform a Terraform `plan` or `apply`. All types of
+triggers should work, including CLI, API, and Git, so long as the run is
+coordinated by Terraform Cloud.
+
+Assuming your local `terraform` is authenticated to Terraform Cloud, try:
+```code
+$ terraform plan
+```
+
+The workflow should successfully execute, depending on your Terraform
+configuration.
+
+## Troubleshooting
+
+### Extracting a JWT for debugging purposes
+
+If you need to view a JWT sample for debugging purposes, you can create a
+`null_resource` that prints the JWT for the run:
+
+```hcl
+resource "null_resource" "print_token" {
+ provisioner "local-exec" {
+ command = "echo TFC_WORKLOAD_IDENTITY_TOKEN_TELEPORT: $TFC_WORKLOAD_IDENTITY_TOKEN_TELEPORT"
+ }
+}
+```
+
+Once applied, you should see the encoded JWT printed in your Terraform log.
+These values can be decoded either by hand or with any number of tools, for
+example [`jwt-cli`].
+
+Note that these JWTs are generally valid for 2 hours and can potentially be used
+to authenticate to your Teleport cluster, so this value should be treated with
+care. The full encoded token should not be shared.
+
+This may be useful for determining the exact issuer (`iss`) value needed to
+configure Terraform Enterprise join tokens, or if you need to request support.
+
+[tf-workload-id]: https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/workload-identity-tokens
+[`jwt-cli`]: https://github.com/mike-engel/jwt-cli
diff --git a/docs/pages/enroll-resources/machine-id/deployment.mdx b/docs/pages/enroll-resources/machine-id/deployment.mdx
index aff3a54a3d35b..adf801987cf0a 100644
--- a/docs/pages/enroll-resources/machine-id/deployment.mdx
+++ b/docs/pages/enroll-resources/machine-id/deployment.mdx
@@ -66,10 +66,11 @@ on-prem infrastructure.
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](../../admin-guides/infrastructure-as-code/terraform-provider/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](../../admin-guides/infrastructure-as-code/terraform-provider/spacelift.mdx) | Docker Image | Spacelift-signed identity document |
+| [Terraform Cloud](../../admin-guides/infrastructure-as-code/terraform-provider/terraform-cloud.mdx) | Teleport Terraform Provider via Teleport's Terraform Registry | Terraform Cloud-signed identity document |
\ No newline at end of file
diff --git a/docs/pages/includes/provision-token/terraform-spec.mdx b/docs/pages/includes/provision-token/terraform-spec.mdx
new file mode 100644
index 0000000000000..2660faccf142b
--- /dev/null
+++ b/docs/pages/includes/provision-token/terraform-spec.mdx
@@ -0,0 +1,44 @@
+```yaml
+kind: token
+version: v2
+metadata:
+ name: terraform
+spec:
+ roles: [Bot]
+ join_method: terraform
+
+ # This must match a bot name, created either with `tctl bots add` or by
+ # creating a `bot` resource.
+ bot_name: terraform
+
+ terraform:
+ # Manually override the expected audience. If unset, defaults to the
+ # Teleport cluster name. It is not recommended to override this value.
+ audience: ''
+
+ # Specify the hostname of a Terraform Enterprise instance. Overriding this
+ # value to use Terraform Enterprise requires Teleport Enterprise.
+ # If unset, refers to the public `app.terraform.io` instance.
+ hostname: ''
+
+ allow:
+ # At least one of `organization_name` or `organization_id` must be set.
+ # Values are case and whitespace sensitive.
+ - organization_name: OrgName
+ organization_id: org-foo
+
+ # At least one of `project_name`, `project_id`, `workspace_name`, or
+ # `workspace_id` must also be set.
+ project_name: ProjectName
+ project_id: prj-bar
+
+ # If no `workspace_name` or `workspace_id` are set, all workspaces
+ # within the specified project will be allowed to join.
+ workspace_name: WorkspaceName
+ workspace_id: ws-baz
+
+ # If set, requires that a run be using a particular run phase. For
+ # example, this could allow a particular run to only be used for
+ # planning. Valid values: empty, `plan`, or `apply`.
+ run_phase: ''
+```
diff --git a/docs/pages/reference/join-methods.mdx b/docs/pages/reference/join-methods.mdx
index f7a9cf17214bd..e4c1ec1dd90e1 100644
--- a/docs/pages/reference/join-methods.mdx
+++ b/docs/pages/reference/join-methods.mdx
@@ -123,6 +123,7 @@ Delegated join methods are:
- [`gitlab`](#gitlab-gitlab)
- [`kubernetes`](#kubernetes-kubernetes)
- [`tpm`](#trusted-platform-module-tpm)
+- [`terraform_cloud`](#terraform-cloud-terraform_cloud)
### Renewable vs non-renewable
@@ -426,3 +427,21 @@ to contain the new Kubernetes signing keys (update the
- [Deploying Machine ID on Linux: TPM](../enroll-resources/machine-id/deployment/linux-tpm.mdx)
+
+### Terraform Cloud: `terraform_cloud`
+
+This join method is used to authenticate using Terraform Cloud Workload
+Identity. It is typically used by the Teleport Terraform provider on either
+HCP Terraform or self-hosted Terraform Enterprise. It can not be used to join
+Terraform runs on other platforms and dedicated join methods should be used
+instead.
+
+
+Support for self-hosted Terraform Enterprise requires Teleport Enterprise.
+
+
+(!docs/pages/includes/provision-token/terraform-spec.mdx!)
+
+
+- [Run the Teleport Terraform Provider on Terraform Cloud](../admin-guides/infrastructure-as-code/terraform-provider/terraform-cloud.mdx)
+