Background

  • I want to setup AWS dynamic secrets in Vault so that I can get credentials to my Terraform state stored in an S3 backend.

Walkthrough

There is a choice between iam  and ec2 , I need iam .

The iam  method is the recommended approach as it is more flexible and aligns with best practices to perform access control and authentication.

The below steps would be following the documentation from: https://developer.hashicorp.com/vault/docs/secrets/aws


Steps
1

Create an AWS user that has AdministratorAccess.

This user will be used by Vault in its AWS auth method configuration.

I created a user called vault-admin that is in my admins  group.

2

Enable the AWS dynamic secrets engine

vault secrets enable aws
3

Add the configuration for the vault-admin.

vault write aws/config/root \
    access_key=... \
    secret_key=... \
    region=us-east-1
4

Create the S3 bucket.

  • Enable bucket versioning for easy rollback and previous state saves.
  • Block public access.
5

Create the DynamoDB table.

  • The table partition key must be called LockID (string).
6

Construct a S3/dynamoDB policy for a role to create on the AWS secrets engine.

Example policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::tenzin-io"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::tenzin-io/*"
    },
	{
      "Effect": "Allow",
      "Action": [
        "dynamodb:DescribeTable",
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:DeleteItem"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/mytable"
    }
  ]
}
7

Write the role into vault.

My IAM policy for terraform role
# vault write aws/roles/terraform \
  credential_type=iam_user \
  policy_document=-<<eof
> {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::tenzin-io"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
      "Resource": "arn:aws:s3:::tenzin-io/*"
    },
        {
      "Effect": "Allow",
      "Action": [
        "dynamodb:DescribeTable",
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:DeleteItem"
      ],
      "Resource": "arn:aws:dynamodb:*:*:table/tenzin-io"
    }
  ]
}
> eof
8

Read the dynamic credentials for the new role.

vault read aws/creds/terraform
Key                Value
---                -----
lease_id           aws/creds/terraform/...
lease_duration     768h
lease_renewable    true
access_key         ...
secret_key         ...
security_token     <nil>
9

Update the Terraform file to use the new backend and migrate the state.

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

terraform {
  backend "s3" {
    bucket = "tenzin-io"
    key = "terraform/my_terraform.state"
    dynamodb_table = "tenzin-io"
    region = "us-east-1"
  }
}

10

My terraform state file!

11

Terraform plan and apply works with the S3 and dynamoDB backend.

# terraform plan
data.vault_generic_secret.k8s_secret: Reading...
data.vault_generic_secret.k8s_secret: Read complete after 0s [id=secret/homelab-k8s-cluster]
helm_release.nginx: Refreshing state... [id=my-nginx]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
  • No labels