Terraform + AWS SecretManager: Reading secret from an EC2 instance using IAM role, policy and instance policy profile

Natarajan Santhosh
2 min readFeb 20, 2020

I was working on problem where a jmeter performance test run required a shared secret

Using terraform data aws_secret_manager is not recommended(when writing this article) since it stores the secret in plain text insider terraform state files(*.tfstate)

My approach was to use the AWS secret manager.

Step 1: add your secret to AWS SecretManager either via aws console or aws cli.

click on store secret and provide a secret name e.g prod/lti/token. take a note of secret’s ARN

Step 2: create an IAM role with ec2 as the principal

resource "aws_iam_role" "test_iam_role" {
name = "test_iam_role"

assume_role_policy
= <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF

tags = {
tag-key = "test"
}
}

Step 3: create an IAM role policy and link it to above IAM role. resource value should be value of secret’s ARN from Step 1.

resource "aws_iam_role_policy" "test_secretmanager_policy" {
name = "test_secretmanager_policy"
role = "${aws_iam_role.test_iam_role.id}"

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-west-2:12346789:secret:prod/lti/token-S5mRZB"
}]
}
EOF
}

Step 4: create an IAM instance profile and link to IAM role created on Step 2

resource "aws_iam_instance_profile" "test_instance_profile" {
name = "test_instance_profile"
role
= "${aws_iam_role.test_iam_role.name}"
}

Step 4: link above instance profile to the aws instance.(link a valid key pair so that you can ssh into ec2 instance)

resource "aws_instance" "web" {
ami = "ami-04590e7389a6e577c"
instance_type
= "t3a.medium"
key_name = aws_key_pair.dev_key.key_name
iam_instance_profile = "${aws_iam_instance_profile.test_instance_profile.name}"
}

Step 5: run the terraform apply

terraform apply

Step 6: ssh in the ec2 instance

ssh -i "~/ssh_private_key" ec2-user@ec2-1x0-2x7-19x-1x9.us-west-2.compute.amazonaws.com

Step 7: run the aws cli to get_secret_value

$ aws secretsmanager --output text get-secret-value --secret-id prod/lti/token --query SecretString --region us-west-2

to extract the token secret value from json response. I’m using jq here

$ sudo yum -y install jq
$ export LTI_TOKEN_SECRET=$(aws secretsmanager --output text get-secret-value --secret-id prod/lti/token --query SecretString --region us-west-2| jq -r '.LTI_TOKEN_SECRET'

Thanks for reading \o/

--

--