Terraform Secrets Management: Day 6

Securing Infrastructure: Exploring Terraform Secrets Management

Terraform Secrets Management: Day 6

Introduction

As technology shifts towards cloud and Infrastructure as Code (IaC), protecting data is the main priority of any environment. Various types of sensitive information like passwords, API keys, and service certificates are essential for running Terraform. Thus, the need for a robust secret management solution is critical. Managing secrets in Terraform entails securely handling such sensitive data.

Importance of Secrets in Terraform Provisioning

Secrets are essential in providing secure access to cloud providers.

Secrets help in setting up authentication through API keys, OAuth tokens, SSL

Secrets are required to access sensitive information like database, customer personal information, account statements etc.

Secrets are necessary for setting up network components.

Secrets are essential for integrating terraform and providing authentication and authorization to respective services with any of the cloud like AWS, Azure, Google Cloud etc. These credentials are in the form of access keys and secrets.

Way of Managing Secrets

  1. Encrypting passwords or keys in config files to add extra security to sensitive data.

  2. Using third-party software like Hashicorp Vault and AWS Secrets managers.

  3. Using environment variables wherever possible.

  4. Using secure remote backend.

  5. Encrypt files with KMS, PGP or SOPS.

  6. Using Terraform variable to define variables within your configuration files or in separate variable files.

  7. Regular monitoring or auditing of the usage of secrets to detect any unauthorized access.

  8. Masking sensitive values.

Setting up Hashicorp Vault on AWS

Creating the S3 Bucket for Vault Storage

To begin, we'll establish an S3 bucket to serve as storage for our Vault instance:

    1. Access the S3 console through the AWS management console.

      1. Click on the "Create bucket" button.

      2. Provide a name for the bucket, leaving other settings unchanged.

      3. Keep note of the bucket's ARN for future reference.

      4. Retrieve the bucket ARN by selecting the bucket and navigating to Permissions → Bucket Policy.

Set up IAM roles and Policies

Create IAM Policy fo full access to S3 bucket

  1. Go to the AWS Management Console and open the IAM (Identity and Access Management) service.

  2. In the IAM dashboard, click on "Policies" in the left sidebar.

  3. Click on the "Create policy" button.

  4. Select "JSON" as the policy editor.

     {
         "Version": "2012-10-17",
         "Statement": [
             {
                 "Effect": "Allow",
                 "Action": [
                     "s3:*"
                 ],
                 "Resource": "*"
             }
         ]
     }
    
  5. Select the review policy button.

  6. Give any name to the policy and click on Create policy" button to create the policy.

Create IAM Role

  1. Navigate to the "Roles" section in the side menu.

  2. Click on the "Create role" button.

  3. Choose "EC2" as the use case for this role.

  4. Attach the previously created policy to the role.

  5. Proceed to the next steps by clicking "Next" until you reach the Review step.

  6. Provide a name and description for the role.

  7. Finally, click on the "Create role" button to finish the process.

`Create IAM User

  1. Navigate to the "Users" section in the side tab.

  2. Click on "Add user."

  3. Provide a name for the user.

  4. Select "Programmatic access" for the access type.

  5. Click "Next: Permissions."

  6. Attach the S3 policy from the previous section to the user.

  7. Proceed by clicking "Next" until you reach the Review step.

  8. Review the information and then click "Create user."

  9. On the next screen, save or download the user credentials.

  10. Next, create another policy that will allow this IAM user to authenticate with the AWS SDK while using Vault. Navigate to the "Permissions" tab and click on "Add Permissions."

  11. Select "Add existing policies directly."

  12. Click "Create policy."

  13. In the JSON tab, input the following policy definition

  14. Click "Review Policy."

  15. Provide your policy with a name and description.

  16. Finally, click "Create policy."

  17. Attach this policy to the new user you just created.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "iam:GetInstanceProfile",
                "iam:GetUser",
                "iam:GetRole"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "<USER_ARN>"
            ]
        }
    ]
}

Setting up the ec2 instance

  1. Go to the EC2 console from the AWS management console.

  2. Select "Instances" from the tab on the right side.

  3. Click on "Launch Instance."

  4. Choose the AWS Linux 2 AMI (the topmost option).

  5. Select an instance class. For this tutorial, we will use a nano size instance.

  6. Click "Next: Configure Instance Details."

  7. Under IAM role, select the IAM role created in the previous step.

  8. Click "Next: Add Storage."

  9. The defaults are suitable. Proceed by clicking "Next: Add Tags."

  10. Provide your instance with a Name tag so you can identify it after launch.

  11. Click "Next: Configure Security Group."

  12. Create a new security group and add a new TCP rule with port range 8200. source as "My IP."

  13. Click Review and Launch instance with new Key pair and Click on Launch button.

Installing Vault

  1. Install gpg
sudo apt update && sudo apt install gpg
  1. 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
    
  2. Verify the key's fingerprint.

     gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint
    
  3. 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 tee /etc/apt/sources.list.d/hashicorp.list
  1. Install Vault

     sudo apt install vault
    
  2. Start Vault

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

Setting Access for User using Approle

  1. Click on Approle > next > Enable Method.

  2. Configure AppRole.

Configure Terraform to read from Vault

Launch vault using public IP of EC2 instance where we have created vault with password as token.

Configuration of Approle via CLI

  1. Enable vault approle
vault auth enable approle
  1. Create a Policy for terraform
vault policy write terraform - <<EOF
path "*" {
  capabilities = ["list", "read"]
}
path "kv/data/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}
EOF
  1. Create approle

     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
    
    1. Generate roleId

       vault read auth/approle/role/terraform/role-id
      
    2. Generate Secret ID

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

      Now, secret id and role id are displayed on screen.

    3. Use below script in main.tf in visual studio

    4.  provider "aws" {
         region = "us-east-1"
       }
      
       provider "vault" {
         address = "<>:8200"
         skip_child_token = true
      
         auth_login {
           path = "auth/approle/login"
      
           parameters = {
             role_id = "" #From above steps
             secret_id = "" #From above steps
           }
         }
       }
      
       data "vault_kv_secret_v2" "example" {
         mount = "kv" 
         name  = "test-secret" 
       }
      
       resource "aws_instance" "my_instance" {
         ami           = "ami-053b0d53c279acc90"
         instance_type = "t2.micro"
       }