Terraform Cloud and Vault dynamic credentials

Terraform Cloud and Vault dynamic credentials

Using static, long-term credentials to access AWS Cloud through Terraform Cloud is not considered a best practice. Instead, let’s explore a better solution: leveraging short-lived, dynamic credentials for enhanced security.

What we have:

Currently, the Terraform Cloud Workspace is configured using an Access Key and a Secret Access Key.

You can use HCP Terraform’s native OpenID Connect integration with Vault to get dynamic credentials for the Vault provider in your HCP Terraform runs. Configuring the integration requires the following steps:

  1. Configure Vault: Set up a trust configuration between Vault and HCP Terraform. Then, you must create Vault roles and policies for your HCP Terraform workspaces.
  2. Configure AWS secrets engine: Enable and configure AWS secrets engine.
  3. Configure HCP Terraform: Add environment variables to the HCP Terraform workspaces where you want to use Dynamic Credentials.

Once you complete the setup, HCP Terraform automatically authenticates to Vault during each run. The Vault provider authentication is valid for the length of the plan or apply. Vault does not revoke authentication until the run is complete.

Configure Vault

Export variables to access Vault Dedicated:

export VAULT_TOKEN=hvs.***

export VAULT_ADDR=https://vault-cluster-public-vault-***.z1.hashicorp.cloud:8200

export VAULT_NAMESPACE=admin

Enable the JWT Auth Backend

Run the following command to enable the JWT auth backend in Vault:

vault auth enable jwt

Configure Trust with HCP Terraform

You must configure Vault to trust HCP Terraform’s identity tokens and verify them using HCP Terraform’s public key. The following command configures the jwt auth backend in Vault to trust HCP Terraform as an OIDC identity provider:

vault write auth/jwt/config \
    oidc_discovery_url="https://app.terraform.io" \
    bound_issuer="https://app.terraform.io"

The oidc_discovery_url and bound_issuer should both be the root address of HCP Terraform, including the scheme and without a trailing slash.

Create a Vault Policy

You must create a Vault policy that controls what paths and secrets your HCP Terraform workspace can access in Vault. Create a file called tfc-policy.hcl with the following content:

# Allow tokens to query themselves
path "auth/token/lookup-self" {
  capabilities = ["read"]
}

# Allow tokens to renew themselves
path "auth/token/renew-self" {
    capabilities = ["update"]
}

# Allow tokens to revoke themselves
path "auth/token/revoke-self" {
    capabilities = ["update"]
}

# Configure the actual secrets the token should have access to
path "secret/*" {
  capabilities = ["read"]
}

#It is needed to access our role created below
path "aws/creds/my-role" {
  capabilities = ["read"]
}

Then, create the policy in Vault:

vault policy write tfc-policy tfc-policy.hcl

Create a JWT Auth Role

Create a Vault role that HCP Terraform can use when authenticating to Vault.

Vault offers a lot of flexibility in determining how to map roles and permissions in Vault to workspaces in HCP Terraform. You can have one role for each workspace, one role for a group of workspaces, or one role for all workspaces in an organization. You can also configure different roles for the plan and apply phases of a run.

Note: If you set your user_claim to be per workspace, then Vault ties the entity it creates to that workspace’s name. If you rename the workspace tied to your user_claim, Vault will create an additional identity object. To avoid this, update the alias name in Vault to your new workspace name before you update it in HCP Terraform.

The following example creates a role called tfc-role. The role is mapped to a single workspace and HCP Terraform can use it for both plan and apply runs.

Create a file called vault-jwt-auth-role.json with the following content:

{
  "policies": ["tfc-policy"],
  "bound_audiences": ["vault.workload.identity"],
  "bound_claims_type": "glob",
  "bound_claims": {
    "sub":
"organization:VovandosDevelopment:project:Main_Development:workspace:hcp-terraform-ec2:run_phase:*"
  },
  "user_claim": "terraform_full_workspace",
  "role_type": "jwt",
  "token_ttl": "20m"
}

Then run the following command to create a role named tfc-role with this configuration in Vault:

vault write auth/jwt/role/tfc-role @vault-jwt-auth-role.json

Token TTLs

We recommend setting token_ttl to a relatively short value. HCP Terraform can renew the token periodically until the plan or apply is complete, then revoke it to prevent it from being used further.

Configure AWS secrets engine

The AWS secrets engine generates AWS access credentials dynamically based on IAM policies. 

Setup

1. Enable the AWS secrets engine:

$ vault secrets enable aws
Success! Enabled the aws secrets engine at: aws/

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 the credentials that Vault uses to communicate with AWS to generate the IAM credentials:

vault write aws/config/root \
    access_key=*** \
    secret_key=*** \
    region=us-west-2

Internally, Vault will connect to AWS using these credentials which were created previously in AWS:

Configure HCP Terraform

Workspace variables should be updated from static AWS access keys, as demonstrated earlier in the post, to specific environment variables.

When a Workspace Run is initiated, Terraform Cloud interacts with Vault, which then generates temporary credentials valid for the duration of the current Run.

Conclusion

By integrating Terraform Cloud with Vault to generate short-lived, dynamic credentials, you significantly enhance the security and flexibility of your infrastructure workflows. This approach eliminates the risks associated with static, long-term access keys while ensuring that your Terraform runs are both secure and efficient.

Dynamic credentials not only align with best practices but also simplify credential management, reducing the likelihood of unauthorized access or credential leakage. Adopting this setup helps create a more robust and automated infrastructure-as-code pipeline, empowering teams to focus on innovation instead of security gaps.

vovando Avatar

Leave a Reply

Your email address will not be published. Required fields are marked *