--- layout: docs page_title: HCP Terraform secrets engine description: >- Dynamically generate HCP Terraform API tokens with the HCP Terraform secrets engine plugin. --- > [!IMPORTANT] > **Documentation Update:** Product documentation, which were located in this repository under `/website`, are now located in [`hashicorp/web-unified-docs`](https://github.com/hashicorp/web-unified-docs), colocated with all other product documentation. Contributions to this content should be done in the `web-unified-docs` repo, and not this one. Changes made to `/website` content in this repo will not be reflected on the developer.hashicorp.com website. # HCP Terraform secrets engine The HCP Terraform secrets engine for Vault generates [HCP Terraform](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 HCP Terraform secrets engine: ```shell-session $ vault secrets enable terraform Success! Enabled the terraform 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 HCP Terraform: ```shell-session $ vault write terraform/config \ token=Vhz7652ba4c-0f6e-8e75-5724-5e083d72cfe4 Success! Data written to: terraform/config ``` See [HCP Terraform's documentation on API tokens](/terraform/cloud-docs/users-teams-organizations/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 HCP Terraform user. At this time the HCP Terraform 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 HCP Terraform [Account API](/terraform/cloud-docs/api-docs/account) to find the desired User ID. ```shell-session $ vault write terraform/role/my-role user_id=user-12345abcde credential_type=user 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, legacy team, team, and user roles HCP Terraform supports four distinct types of API tokens; Organizations, Teams, Legacy Team Tokens and Users. Each token type has distinct access levels and generation workflows. A given Vault role can manage any one of the supported types at a time, however there are important differences to be aware of. ### Organization roles Generating a new Organization 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. Due to this behavior, Organization 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}" credential_type=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 hashicorp-vault-testing role testing 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 HCP Terraform API does not allow for creating dynamic users. Instead, the HCP Terraform secret engine creates dynamic User API tokens by configuring a Vault role to manage an existing HCP Terraform 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 token_id at-fqvtdTQ5kQWcjUfG ``` ### Team roles The HCP Terraform secret engine creates dynamic Team API tokens by configuring a Vault role to manage an existing HCP Terraform Team. The lifecycle of these tokens is managed by Vault and/or HCP Terraform. Generally, Vault aims to manage tokens in external APIs with revoke actions taken according to `ttl` and `max_ttl` settings. In addition to that behavior, using the `max_ttl` Vault will set an `ExpiredAt` date in HCP Terraform which will ensure the token expires at the Max TTL time. This prevents Team tokens living past their `max_ttl` if Vault is unable to revoke the token. Omitting the `max_ttl` value will default to Vault's system `max_ttl`. In HCP Terraform, team tokens cannot have matching descriptions. In order to avoid collisions, the secret engine generates a random string as a suffix to the description. It is highly recommended you set an additional description. Below is an example of creating a Vault role to manage manage Team API tokens: ```shell-session $ vault write terraform/role/team-testing team_id="${TF_TEAM_ID}" credential_type=team description="testing token" ttl=200 max_ttl=600 Success! Data written to: terraform/role/team-testing ``` The API token is retrieved by reading the credentials for the role: ```shell-session $ vault read terraform/creds/team-testing Key Value --- ----- lease_id terraform/creds/team-testing/4oNxB4X0x77IrP51lBMJBiJi lease_duration 3m20s lease_renewable true description testing token(74) expired_at 2025-05-01T20:10:55Z token token_id at-GDMeMTvn3NhUernt ``` ### Legacy team roles (Deprecated) The HCP Terraform API limits Legacy Team roles to **one active token at any given time**. Generating a new Legacy 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 Team. Due to this behavior, Legacy 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 a Legacy Team API token and rotating the token: ```shell-session $ vault write terraform/role/legacy-team team_id="${TF_TEAM_ID}" credential_type=team_legacy Success! Data written to: terraform/role/legacy-team $ vault write -f terraform/rotate-role/legacy-team Success! Data written to: terraform/rotate-role/legacy-team ``` The API token is retrieved by reading the credentials for the role: ```shell-session $ vault read terraform/creds/legacy-team Key Value --- ----- organization n/a role legacy-team team_id team- token token_id at-fqvtdTQ5kQWcjUfG ```