Day-7-terraform

Mastering Secrets Management with Terraform and HashiCorp Vault

TLDR: This blog post provides a comprehensive guide on integrating Terraform with HashiCorp Vault for effective secrets management, covering installation, configuration, and practical examples.

In the world of DevOps, managing sensitive information such as passwords, API tokens, and certificates is crucial. This blog post is based on Day 7 of the Terraform Zero to Hero series, where we dive deep into the concept of secrets management using Terraform and HashiCorp Vault. Understanding how to implement secrets management is essential for any DevOps engineer, as it helps in securely handling sensitive data.

create EC2 instance
Search ->ec2 -> select instance (lots of cards → resource) -> launch instance
Name : vault
Os : ubuntu
AMI : V22.04 (free tire -> available for 750 hr/ year)
Instance type: t2.micro (free tire)
Key-pair : drop down (create a new key pair) -> name : aws_login -> type: RSA -> format : .pem - - - > create key pair (file downloaded-> aws_login.pem)
Configure storage : 8gb
----> launch instance
login to created ec2 and install package and vault
ssh -i aws_login.pem ubuntu@<created-instance-public-ip-add>
update package and install gpg: sudo apt update && sudo apt install gpg
Download the signing key to a new keyring : wget -O- https://apt.releases.hashicorp.com/gpg
Verify the key's fingerprint : gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint
Add the HashiCorp repo : echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt update
Finally, Install Vault : sudo apt install vault
start vault : vault server -dev -dev-listen-address="0.0.0.0:8200"
→env variable : export VAULT_ADDR=’http://0.0.0.0:8200’
→unseal key: —
→Root token: —
open a new tab and login to created instance
ssh -i aws_login.pem ubuntu@<created-instance-public-ip-add>
export VAULT_ADDR=’http://0.0.0.0:8200’
unable to open issue → http://<public ip address>:8200
Created instance -> security (tab) -> security group - > inbound rules - > edit inbound rules
Add rule ->type: custom tcp -> port: 8200-> source : any where - > save rule
refresh page → http://<public ip address>:8200 → now u can see vault UI
signin vault → create secret and enable AppRole method for Auth
signin vault → [Method: Token ,Token: paste root token] → root user
imp topic : secrets engines, Access, Policies
secrets engines (side bar)→ generic → KV -→ path: kv → enable engine
create secrete → path : test-secret → secret data [key: username , value: gokul ] → save
Access → enable new method → AppRole (~IAM role in AWS) →next —> enable method
now i want to autheticate Terraform using AppRole Mechanism
cant create any roles using UI , so we have to do it through terminal
→ create roles —>create policy → attach that policy → approle
run in terminal below command :

// create policy -> policy name: terraform , granting certain action to folder/path/mount points in secrets engines
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
// create AppRole -> token_policies=policy name(from above)
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
~ aws access and secret access key → generate Role ID and Secret ID with policy name -> terraform
Generate Role ID: vault read auth/approle/role/terraform/role-id
Generate Secret ID: vault write -f auth/approle/role/terraform/secret-id
// main.tf

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

provider "vault" {
  address = "http://<instance-public-ip>:8200"
  skip_child_token = true

  auth_login {
    path = "auth/approle/login"

    parameters = { 
      role_id = "<>"   // generated above step
      secret_id = "<>"  // generated above step
    }
  }
}

// to read data from vault  --> kv/test-secret
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" "my_instance" {
  ami           = "ami-053b0d53c279acc90"
  instance_type = "t2.micro"

  tags = {
    Secret = data.vault_kv_secret_v2.example.data["username"] // to get value(gokul) from key -> username
  }
}
terraform init
terraform plan
terraform apply

What is Secrets Management?

Secrets management refers to the processes and tools used to store, manage, and access sensitive information securely. Whether you are using Terraform, Ansible, CI/CD pipelines, or Kubernetes, implementing a robust secrets management strategy is vital. HashiCorp Vault is one of the most popular tools for this purpose, allowing integration with various platforms including Terraform.

Overview of HashiCorp Vault

HashiCorp Vault is a tool designed for securely accessing secrets. It supports various integrations and can be used with Terraform, Ansible, CI/CD tools, and Kubernetes. In this tutorial, we will focus on integrating Terraform with HashiCorp Vault to manage secrets effectively.

Setting Up the Environment

Creating a Linux Instance

To get started, we will create a Linux instance on AWS. For this demonstration, we will use Ubuntu 20.04. Here are the steps:

  1. Log in to your AWS console.

  2. Launch a new EC2 instance and select Ubuntu 20.04 as the operating system.

  3. Once the instance is running, note down the public IP address.

Installing HashiCorp Vault

After setting up the instance, we need to install HashiCorp Vault. Follow these steps:

  1. SSH into your EC2 instance using the command:
    ssh -i your-key.pem ubuntu@your-instance-ip

  2. Update the package manager and install GPG:

     sudo apt update
     sudo apt install -y gnupg software-properties-common
    
  3. Add the HashiCorp repository:

     wget -qO - https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
     echo "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
     sudo apt update
     sudo apt install vault
    
  4. Verify the installation by running:

     vault
    

Starting the Vault Server

HashiCorp Vault can run in two modes: development and production. For demonstration purposes, we will start the development server:

vault server -dev

This command will start the Vault server in development mode, which is suitable for testing and learning.

Configuring HashiCorp Vault

Enabling the Key-Value (KV) Secret Engine

  1. Access the Vault UI by navigating to http://your-instance-ip:8200 in your web browser.

  2. Use the root token provided in the terminal to log in.

  3. Enable the KV secret engine by executing the following command in the Vault CLI:

     vault secrets enable -path=kv kv
    
  4. Create a secret in the KV store:

     vault kv put kv/test-secret username=your-username password=your-password
    

Creating Access Policies and Roles

To allow Terraform to access the secrets, we need to create a policy and a role:

  1. Create a policy that grants access to the KV secrets:

     path "kv/*" {
       capabilities = ["read", "create", "update"]
     }
    
  2. Enable AppRole authentication:

     vault auth enable approle
    
  3. Create a role for Terraform:

     vault write auth/approle/role/terraform policies=terraform
    
  4. Retrieve the Role ID and Secret ID:

     vault read auth/approle/role/terraform
    

Integrating Terraform with HashiCorp Vault

Writing the Terraform Configuration

  1. Create a new directory for your Terraform project and navigate into it:

     mkdir terraform-vault-integration
     cd terraform-vault-integration
    
  2. Create a main.tf file and add the following configuration:

     provider "aws" {
       region = "us-east-1"
     }
    
     provider "vault" {
       address = "http://your-instance-ip:8200"
     }
    
     data "vault_kv_secret_v2" "example" {
       name = "test-secret"
       mount = "kv"
     }
    
     resource "aws_instance" "example" {
       ami           = "ami-0c55b159cbfafe1f0"
       instance_type = "t2.micro"
       tags = {
         Name = "MyInstance"
         Secret = data.vault_kv_secret_v2.example.data["password"]
       }
     }
    
  3. Initialize Terraform:

     terraform init
    
  4. Apply the configuration:

     terraform apply
    

Conclusion

In this blog post, we explored the integration of Terraform with HashiCorp Vault for effective secrets management. We covered the installation of Vault, configuration of the KV secret engine, and how to set up Terraform to retrieve secrets securely. This integration is crucial for managing sensitive information in a secure and efficient manner.

Feel free to experiment with different configurations and let us know your thoughts in the comments. Happy coding!