Skip to content

Instantly share code, notes, and snippets.

@soeirosantos
Last active July 2, 2021 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soeirosantos/1ac8478c917ea47bd092974c9a96c003 to your computer and use it in GitHub Desktop.
Save soeirosantos/1ac8478c917ea47bd092974c9a96c003 to your computer and use it in GitHub Desktop.

Terraform Version of HashiCorp Vault AWS Auth with Amazon EKS and IAM Roles for Service Accounts

This gist is the Terraform configuration for the previous tutorial on HashiCorp Vault AWS Auth with Amazon EKS and IAM Roles for Service Accounts.

This Terraform configuration replaces all the AWS and Vault CLI commands in the previous tutorial.

Before running the next steps make sure you have started Vault and ngrok locally. Take a look at the previous tutorial for more details.

Directory structure

When you copy this gist make sure the *_eks_*.tf files are in a folder called /eks, like so:

├── eks
│   ├── main.tf
│   ├── outputs.tf
│   ├── variables.tf
├── main.tf
├── outputs.tf
└── variables.tf

Try it

Apply the Terraform configuration

terraform init
terrafom apply

Test the Pod identity

VAULT_AUTH_ROLE_ARN=$(terraform output -raw iam_assumable_role_with_web_identity)
VAULT_AUTH_K8S_SERVICE_ACCOUNT=vault-auth


kubectl create sa $VAULT_AUTH_K8S_SERVICE_ACCOUNT
kubectl annotate sa $VAULT_AUTH_K8S_SERVICE_ACCOUNT eks.amazonaws.com/role-arn=$VAULT_AUTH_ROLE_ARN


kubectl run vault -it --rm --restart=Never \
    --serviceaccount $VAULT_AUTH_K8S_SERVICE_ACCOUNT \
    --image vault -- \
    vault login -address=http://2a7f0319443a.ngrok.io \
    -method=aws \
    role="dev-role-iam2"

Clean up

terraform destroy
provider "aws" {
region = var.region
}
module "basic_eks" {
source = "./eks"
}
data "aws_iam_policy_document" "vault_auth_policy" {
statement {
actions = [
"ec2:DescribeInstances",
"iam:GetInstanceProfile",
"iam:GetUser",
"iam:GetRole",
]
resources = ["*"]
}
}
resource "aws_iam_policy" "vault_auth_policy" {
name = "vault-auth-policy"
path = "/"
policy = data.aws_iam_policy_document.vault_auth_policy.json
}
resource "aws_iam_user" "vault_auth" {
name = "vault-auth"
}
resource "aws_iam_user_policy_attachment" "vault_auth_policy_attachment" {
user = aws_iam_user.vault_auth.name
policy_arn = aws_iam_policy.vault_auth_policy.arn
}
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_access_key
# should consider using pgp_key - will keep like this for the purpose of this example
resource "aws_iam_access_key" "vault_auth" {
user = aws_iam_user.vault_auth.name
}
resource "vault_auth_backend" "aws" {
type = "aws"
}
resource "vault_aws_auth_backend_client" "aws" {
backend = vault_auth_backend.aws.path
access_key = aws_iam_access_key.vault_auth.id
# WARNING - THIS SECRET WILL BE PLAIN TEXT IN THE STATE
secret_key = aws_iam_access_key.vault_auth.secret
}
data "aws_iam_policy_document" "iam_assumable_role_with_web_identity" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [module.basic_eks.oidc_provider_arn]
}
condition {
test = "StringEquals"
variable = "${replace(module.basic_eks.cluster_oidc_issuer_url, "https://", "")}:sub"
values = ["system:serviceaccount:${var.k8s_namespace}:${var.k8s_service_account}"]
}
effect = "Allow"
}
}
resource "aws_iam_role" "iam_assumable_role_with_web_identity" {
name = "vault-auth"
assume_role_policy = data.aws_iam_policy_document.iam_assumable_role_with_web_identity.json
}
resource "vault_aws_auth_backend_role" "aws_auth_role_with_web_identity" {
role = "aws-auth-role"
auth_type = "iam"
bound_iam_principal_arns = [aws_iam_role.iam_assumable_role_with_web_identity.arn]
token_period = 240
token_max_ttl = 2160
token_policies = ["my-application-policy"] # this is a fake policy
}
variable "region" {
default = "us-east-1"
}
variable "k8s_namespace" {
default = "default"
}
variable "k8s_service_account" {
default = "vault-auth"
}
output "cluster_name" {
value = module.basic_eks.cluster_name
}
output "iam_assumable_role_with_web_identity" {
value = aws_iam_role.iam_assumable_role_with_web_identity.arn
}
# This module is based on this: https://github.com/terraform-aws-modules/terraform-aws-eks/tree/v17.1.0/examples/basic
data "aws_eks_cluster" "cluster" {
name = module.eks.cluster_id
}
data "aws_eks_cluster_auth" "cluster" {
name = module.eks.cluster_id
}
provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = data.aws_eks_cluster_auth.cluster.token
load_config_file = false
}
locals {
cluster_name = random_pet.cluster_name.id
}
resource "random_pet" "cluster_name" {
prefix = "eks"
separator = "-"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 2.47"
name = "${local.cluster_name}-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1c", "us-east-1d"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
public_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "17.1.0"
cluster_name = local.cluster_name
cluster_version = "1.20"
subnets = module.vpc.private_subnets
vpc_id = module.vpc.vpc_id
enable_irsa = true
worker_groups = [
{
name = "worker-group-1"
instance_type = "t3.small"
asg_desired_capacity = 3
},
]
# map_roles = var.map_roles
# map_users = var.map_users
}
variable "region" {
default = "us-east-1"
}
output "cluster_name" {
value = local.cluster_name
}
output "cluster_oidc_issuer_url" {
value = module.eks.cluster_oidc_issuer_url
}
output "oidc_provider_arn" {
value = module.eks.oidc_provider_arn
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment