HashiCorp Vault Integration with Terraform - Day 10
HashiCorp Vault is a tool designed to securely store and access secrets. It provides a centralized place to manage sensitive data such as API keys, passwords, certificates, and encryption keys. Vault offers features such as encryption, access control, dynamic secrets, and audit logging to help organizations manage and secure their secrets effectively.
Steps to Install Vault on Ubuntu machine
https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-install
Security Group configuration
Configure the inbound rules of the EC2 instance to allow traffic on port 8200
Start the Vault development server
vault server -dev -dev-listen-address="0.0.0.0:8200"
Configure environment variables
Add the environment variables for both Vault address and token.
export VAULT_ADDR='ENTER YOUR VAULT ADDRESS'
export VAULT_TOKEN='ENTER YOUR VAULT TOKEN'
Check the Vault status
vault status
Sign in to Vault development server
<PUBLIC IP OF EC2 INSTANCE>:8200
Select the method as 'Token' and provide the Vault token to sign in to Vault.
Select 'Secrets Engines' from the left panel and click 'Enable new engine'.
To store a key-value pair, select 'KV' from the generic list and click 'Next'.
Enter a name for the path and click 'Enable Engine'.
After creating the path, click 'Create secret' on the next page.
Enter the path for the secret, store your key-value pair, and click 'Save'.
Once your key pair is stored, you will see it listed under 'Secrets Engine' as shown below.
To use these credentials from other resources like Terraform, you need to grant access to the external resource.
To create an 'AppRole', navigate to 'Authentication Methods' in the left panel and select 'AppRole' from the generic list.
Enable the AppRole authentication method.
Create vault policies via CLI. Policies in Vault control what a user can access.
Enable an AppRole role named "terraform", to configure some basic token options and to attach the previously defined "terraform" policy to all tokens that it creates when applications authenticate with the role.
Generate Role ID and Secret ID
vault read auth/approle/role/my-approle/role-id
vault write -f auth/approle/role/my-approle/secret-id
Reference: https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-policies
Use Vault in Terraform Configuration
Terraform configuration to provision an AWS EC2 instance and dynamically retrieve a secret from HashiCorp Vault to tag the instance during creation.
Function of the Terraform configuration:
The script configures the AWS provider (
provider "aws"
) to use theus-east-2
region and the Vault provider (provider "vault"
) to connect to the Vault server running on an EC2 instance with a public IP address (http://<PUBLIC IP OF EC2 INSTANCE>:8200
).It also sets
skip_child_token = true
, which skips creating child tokens for authentication.The
auth_login
block specifies the authentication method (approle
) and provides therole_id
andsecret_id
required for authentication.The
data "vault_kv_secret_v2" "example"
block retrieves a secret (kaizen-creds
) from the Vault server under thecreds
mount point.This secret can be accessed later in the configuration using
data.vault_kv_secret_v2.example.data["kaizen"]
.The
resource "aws_instance" "dev_instance"
block provisions an EC2 instance with the specified AMI (ami-0c20d88b0021158c6
) and instance type (t2.micro
).It also assigns tags to the instance, a tag called
secret
, which gets its value from the Vault secret retrieved earlier (data.vault_kv_secret_v2.example.data["kaizen"]
).
provider "aws" {
region = "us-east-2"
}
provider "vault" {
address = "http://<PUBLIC IP OF EC2 INSTANCE>:8200"
skip_child_token = true
auth_login {
path = "auth/approle/login"
parameters = {
role_id = "<ENTER YOUR ROLE ID>"
secret_id = "<ENTER YOUR SECRET ID>"
}
}
}
data "vault_kv_secret_v2" "example" {
mount = "creds"
name = "kaizen-creds"
}
resource "aws_instance" "dev_instance" {
ami = "ami-0c20d88b0021158c6"
instance_type = "t2.micro"
tags = {
secret = data.vault_kv_secret_v2.example.data["kaizen"]
}
}