# Terraform

The Terraform Cloud secret backend for Vault generates [Terraform Cloud](https://cloud.hashicorp.com/products/terraform) API tokens dynamically for Organizations, Teams, and Users.

This page will show a quick start for this backend. For detailed documentation on every path, use `vault path-help` after mounting the backend.

\~> **Terraform Enterprise Support:** this secret engine supports both Terraform Cloud ([app.terraform.io](https://app.terraform.io/session)) as well as on-prem Terraform Enterprise. Any version requirements will be documented alongside the features that require them, if any.

### Quick start

Most secrets engines must be configured in advance before they can perform their functions. These steps are usually completed by an operator or configuration management tool.

1. Enable the Terraform Cloud secrets engine:

   ```shell-session
   $ vault secrets enable terraform
   Success! Enabled the terraform cloud secrets engine at: terraform/
   ```

   By default, the secrets engine will mount at the name of the engine. To enable the secrets engine at a different path, use the `-path` argument.
2. Configure Vault to connect and authenticate to Terraform Cloud:

   ```shell-session
   $ vault write terraform/config \
       token=Vhz7652ba4c-0f6e-8e75-5724-5e083d72cfe4
   Success! Data written to: terraform/config
   ```

   See Terraform Cloud's documentation on API tokens to determine the appropriate API token for use with the secret engine. In order to perform all operations, a User API token is recommended.
3. Configure a role that maps a name in Vault to a Terraform Cloud User. At this time the Terraform Cloud API does not allow dynamic user generation. As a result this secret engine creates dynamic API tokens for an existing user, and manages the lifecycle of that API token. You will need to know the User ID in order to generate User API tokens for that user. You can use the Terraform Cloud Account API to find the desired User ID.

   ```shell-session
   $ vault write terraform/role/my-role user_id=user-12345abcde
   Success! Data written to: terraform/role/my-role
   ```

### Usage

After the secrets engine is configured and a user/machine has a Vault token with the proper permission, it can generate credentials.

Generate a new credential by reading from the `/creds` endpoint with the name of the role:

```shell-session
$ vault read terraform/creds/my-role
Key                Value
---                -----
lease_id           terraform/creds/my-user/A_LEASE_ID_PdvmJjACTtKrY2I
lease_duration     180s
lease_renewable    true
token              TJFDSIFDSKFEKZX.FKFKA.akjlfdiouajlkdakadfiowe
token_id           at-123acbdfask
```

### Organization, team, and user roles

Terraform Cloud supports three distinct types of API tokens; Organizations, Teams, and Users. Each token type has distinct access levels and generation workflows. A given Vault role can manage any one of the three types at a time, however there are important differences to be aware of.

#### Organization and team roles

The Terraform Cloud API limits both Organization and Team roles to **one active token at any given time**. Generating a new Organization or Team API token by reading the credentials in Vault or otherwise generating them on [app.terraform.io](https://app.terraform.io/session) will effectively revoke **any** existing API token for that Organization or Team.

Due to this behavior, Organization and Team API tokens created by Vault will be stored and returned on future requests, until the credentials get rotated. This is to prevent unintentional revocation of tokens that are currently in-use.

Below is an example of creating a Vault role to manage an Organization API token and rotating the token:

```shell-session
$ vault write terraform/role/testing organization="${TF_ORGANIZATION}"
Success! Data written to: terraform/role/testing

$ vault write -f terraform/rotate-role/testing
Success! Data written to: terraform/rotate-role/testing
```

The API token is retrieved by reading the credentials for the role:

```
$ vault read terraform/creds/testing

Key             Value
---             -----
organization    enclaive-vault-testing
role            testing
token           <example token>
token_id        at-fqvtdTQ5kQWcjUfG
```

#### User roles

Traditionally, Vault secret engines create dynamic users and dynamic credentials along with them. At the time of writing, the Terraform Cloud API does not allow for creating dynamic users. Instead, the Terraform Cloud secret engine creates dynamic User API tokens by configuring a Vault role to manage an existing Terraform Cloud user. The lifecycle of these tokens is managed by Vault and will auto expire according to the configured TTL and max TTL of the Vault role.

Below is an example of creating a Vault role to manage manage User API tokens:

```shell-session
$ vault write terraform/role/user-testing user_id="${TF_USER_ID}"
Success! Data written to: terraform/role/user-testing
```

The API token is retrieved by reading the credentials for the role:

```
$ vault read terraform/creds/user-testing

Key             Value
---             -----
role            user-testing
token           <example token>
token_id        at-fqvtdTQ5kQWcjUfG
```

Please see the Terraform Cloud API Token documentation for more information.

### Tutorial

Refer to Terraform Cloud Secrets Engine for a step-by-step tutorial.

### API

The Terraform Cloud secrets engine has a full HTTP API. Please see the Terraform Cloud secrets engine API for more details.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.enclaive.cloud/vault/tutorials/cli/authentication/aws-azure-gcp-and-external-auth-methods/terraform.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
