Terraform & HashiCorp Vault Integration: Seamless Secrets Management
Tags: terraform, security, devops, secret
Published: 2024-03-23 04:00:00

**what is Hashicorp vault.?**

Imagine HashiCorp Vault as a secure digital vault for all your sensitive information like passwords, API keys, and encryption certificates. It acts like a central location to store, access, and manage these secrets. Here's why it's useful:

- **Strong Security**: Vault encrypts your secrets and controls access with different permission levels. This minimizes the risk of unauthorized access and keeps your sensitive information safe.

- **Centralized Management**: No more scattered secrets! Vault keeps everything in one place, making it easier to control and audit who can access what.

- It can store various secrets, from database credentials to cloud API keys. Vault also integrates with different tools and platforms you might already be using.

Overall, using Vault helps organizations improve security, simplify secret management, and streamline access control for critical information. While Vault has a free open-source version with limited features, most businesses opt for the paid edition with additional functionalities like advanced auditing and disaster recovery

-1-. In today's demo, we will explore Terraform Vault integration with a real example and troubleshooting. Let's get started!

-2-. Launch one EC2 instance with basic configuration and access it.

-3-. Then update your machine and install GPG as well.

`sudo apt update && sudo apt install gpg`

-4-. Then download the signing key to a new keyring.

`wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg`

-5-. Then verify the key's fingerprint.

`gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint`

-6-. Clone the Vault repository from GitHub.

```
mkdir -p $GOPATH/src/github.com/hashicorp && cd $_
git clone https://github.com/hashicorp/vault.git
cd vault
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gasrjbiwm9c75hxnn6fs.png)

-7-. Then install Vault.

`snap install vault`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8t0rx5uu15dwnocejk2.png)

-8-. To start Vault, you can use the following command:

`vault server -dev -dev-listen-address="0.0.0.0:8200"`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ehlf4feipjv3ge7wt1t.png)

-9-. You may need to set the following environment variables. To do so, create a duplicate session and copy the command, then paste it into the new session.

`export VAULT_ADDR='http://0.0.0.0:8200'`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isg276qczyug9ct1bvro.png)

-10- Then go to your EC2 instance's security group and open port 8200 to access the Vault UI.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42swuab876a6w6c6ybdu.png)

-11-. And then copy the public IP and paste it into your browser's address bar followed by port 8200. You will see the login page appear.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vqaf72zo7y5dn8a51kw.png)

-12-. For logging in as root, select 'Token' as the default method. Copy the token from your server when you start Vault; it will be displayed to you. After that, you will see the dashboard.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cy4p3aonx975pqczpmkf.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmgt1yidd0bz0bbvrti5.png)

-13-. Then, in this demo, we will store the secret as 'Key & value'. To do so, click on 'Secret Engines', then select 'KV' which stands for 'Key/value', and click on 'Next'.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwe9nfbhzcyr8pzg161s.png)

-14-. Next, on the following window, provide a path and click 'Next' to proceed, where you will notice that no credentials are created or stored.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynovk7biy0kar8mdayn7.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnfworo9hj9bij1mkwp3.png)

-15-. Now, click on 'Create Secret' and input your secret. I will use 'Username & password' as an example.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufmvcklerhvf99hfgpt0.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brlbam3x6iqycm0tt8xd.png)

-16-. Then, to access these credentials in Terraform, you need to assign policies or roles similar to IAM. Click on 'Policies', then click on 'Enable New Method', and select 'App Role' as the authentication method. This is similar to IAM. Enable the role. Using this App Role, I will authenticate Terraform or whichever tool you are using.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/avpvhm17rrovw8dsb01x.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/svjn92osoyaomhztkzac.png)

-17-. Then, create a duplicate session of your machine and run the following command on it.

-18-. Because HashiCorp Vault does not support the creation of users in the UI, go to the console and create a user. It's very easy. Before creating the role, we need to create a policy for that role. This policy enables Terraform to access the 'kv' and 'secret' folders in Vault.

```
vault policy write terraform - <<EOF
path "*" {
  capabilities = ["list", "read"]
}

path "secrets/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "kv/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "secret/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "auth/token/create" {
capabilities = ["create", "read", "update", "list"]
}
EOF
```

-19-. Now, create a role.

```
vault write auth/approle/role/terraform \
    secret_id_ttl=10m \
    token_num_uses=10 \
    token_ttl=20m \
    token_max_ttl=30m \
    secret_id_num_uses=40 \
    token_policies=terraform
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rqbal2tv9sa7096h1j4.png)

-20-. Similar to AWS, in Vault, we have Role ID and Secret ID. This is sensitive information, so do not share it with anyone.

```
vault read auth/approle/role/terraform/role-id

vault write -f auth/approle/role/terraform/secret-id
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wrjlwvhhznobynv5on0s.png)


-21-. Now that we are done with Vault, the next step is to write down the Terraform project and check whether Terraform is able to read the secret from Vault.

```
#main.tf

provider "aws" {
  region = "us-east-1"
}

provider "vault" {
  address = "http://<your-ip_address>:8200"
  skip_child_token = true

  auth_login {
    path = "auth/approle/login"

    parameters = {
      role_id = "<your-role_id>"
      secret_id = "<your-secret_id>"
    }
  }
}

data "vault_kv_secret_v2" "example" {
  mount = "kv" // change it according to your mount
  name  = "test-secret" // change it according to your secret
}
```

-22-. Then, to check if Terraform is able to retrieve the credentials from Vault, run the 'terraform init' and 'terraform apply' commands.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m5s05dfyit15if9ies7q.png)

-23-. Now, let's add the block to create an EC2 instance and apply it again. You will see that in the EC2 tag, our password will be taken.

```
#main.tf

provider "aws" {
  region = "us-east-1"
}

provider "vault" {
  address = "http://<your-ip_address>:8200"
  skip_child_token = true

  auth_login {
    path = "auth/approle/login"

    parameters = {
      role_id = "<your-role_id>"
      secret_id = "<your-secret_id>"
    }
  }
}

data "vault_kv_secret_v2" "example" {
  mount = "kv" // change it according to your mount
  name  = "test-secret" // change it according to your secret
}

resource "aws_instance" "example" {
  ami = "ami-0c7217cdde317cfec"
  instance_type = "t2.micro"

  tags = {
    secret = data.vault_kv_secret_v2.example.data["username"]
  }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7ghn712sg8r7fbi6sd7.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8d3e6now55x2o9azw0jn.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bk2fpy92u4t3j8hhqzzk.png)

-24-. If you encounter the following error while running 'terraform apply' command, then run it again to recreate 'role-id' and 'secret-id' with the same command as mentioned in step no. 20. After that, paste the new credentials into the code. This will solve your problem.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2wqq9w0fuksap8g1kh8f.png)