"Keeping secrets as secret" is one of the most important things on every infrastructure. To protect and manage sensitive data, creating simple workflows is a good starting point. You can increase the protection level even further if you create and manage secrets in a way that you'll never see and touch.
Cloud and automation make that possible for you. On AWS, there are many ways to store sensitive data. Two main services are AWS Systems Manager Parameter Store and AWS Secrets Manager. Though these services are similar at first sight, there are a number of differences between them such as secret rotation functionality, cross-account access and costs.
Amazon ECS enables you to inject sensitive data into your containers by storing your sensitive data in both services. In this post we will take a look at how to store secrets on AWS Systems Manager Parameter Store vs AWS Secrets Manager and how to inject them into Amazon ECS tasks using Terraform.
Let's start with creating a randomized password using Terraform's random password generator, which is using a cryptographic random number generator. It is available in all versions of random provider following the v.2.2.0 and later versions.
Remember that, all attributes including generated passwords are stored as plain text in state files. So protect your state files!
resource "random_password" "database_password" {
length = 16
special = false
}
Create a secret on AWS Secrets Manager to store the generated password:
resource "aws_secretsmanager_secret" "database_password_secret" {
name = "/production/database/password/master"
}
resource "aws_secretsmanager_secret_version" "database_password_secret_version" {
secret_id = aws_secretsmanager_secret.database_password_secret.id
secret_string = random_password.database_password.result
}
Create an IAM policy to access stored secret from Amazon ECS task using ECS Task Execution Role:
resource "aws_iam_role_policy" "password_policy_secretsmanager" {
name = "password-policy-secretsmanager"
role = aws_iam_role.ecs_task_execution_role.id
policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"secretsmanager:GetSecretValue"
],
"Effect": "Allow",
"Resource": [
"${aws_secretsmanager_secret.database_password_secret.arn}"
]
}
]
}
EOF
}
You can use variables to pass secret ARN to your task template:
data "template_file" "task_template_secretsmanager" {
template = "${file("./templates/task.json.tpl")}"
vars = {
app_cpu = var.cpu
app_memory = var.memory
database_password = aws_secretsmanager_secret.database_password_secret.arn
}
}
Create task template as following ./templates/task.json.tpl
:
[
{
"name": "application",
"image": "service/latest",
"cpu": ${app_cpu},
"memory": ${app_memory},
"essential": true,
"secrets": [
{
"name": "PASSWORD",
"valueFrom": "${database_password}"
}
]
}
]
Create task definition that will use the task template that you just created:
resource "aws_ecs_task_definition" "task_definition_secretsmanager" {
family = "task-secretsmanager"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
requires_compatibilities = ["EC2"]
cpu = var.cpu
memory = var.memory
network_mode = "awsvpc"
container_definitions = data.template_file.task_template_secretsmanager.rendered
}
Create SSM parameter to store the generated password:
resource "aws_ssm_parameter" "database_password_parameter" {
name = "/production/database/password/master"
description = "Production environment database password"
type = "SecureString"
value = random_password.database_password.result
}
Create an IAM policy to access stored parameter from Amazon ECS task using ECS Task Execution Role,
Note that all users within the customer account have access to the default AWS managed key. If you use (or plan to use) customer managed CMK then you also need to give kms:Decrypt permission to ECS Task Execution Role. For more information check here.
resource "aws_iam_role_policy" "password_policy_parameterstore" {
name = "password-policy-parameterstore"
role = aws_iam_role.ecs_task_execution_role.id
policy = <<-EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ssm:GetParameters"
],
"Effect": "Allow",
"Resource": [
"${aws_ssm_parameter.database_password_parameter.arn}"
]
}
]
}
EOF
}
You can use variables to pass parameter store ARN to your task template:
data "template_file" "task_template_parameterstore" {
template = "${file("./templates/task.json.tpl")}"
vars = {
app_cpu = var.cpu
app_memory = var.memory
database_password = aws_ssm_parameter.database_password_parameter.arn
}
}
Create task template as following ./templates/task.json.tpl
:
[
{
"name": "application",
"image": "service/latest",
"cpu": ${app_cpu},
"memory": ${app_memory},
"essential": true,
"secrets": [
{
"name": "PASSWORD",
"valueFrom": "${database_password}"
}
]
}
]
Create task definition that will use the task template that you just created:
resource "aws_ecs_task_definition" "task_definition_parameterstore" {
family = "task-parameterstore"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
requires_compatibilities = ["EC2"]
cpu = var.cpu
memory = var.memory
network_mode = "awsvpc"
container_definitions = data.template_file.task_template_parameterstore.rendered
}
Check full source code example from:
Store secrets on Parameter Store vs AWS Secrets Manager and inject them.
www.github.com/sufleio/terraform-ecs-secretsLearn more about managing sensitive data:
Once a software developer now an AWS Certified Solutions Architect Professional, Gizem is always eager to take on professional challenges. Her meticulousness at her workings follows her passion for learning and sharing her knowledge with tech-savvy professionals and communities.
Subscribe to Our Newsletter
Our Service
Specialties
Copyright © 2018-2024 Sufle
We use cookies to offer you a better experience with personalized content.
Cookies are small files that are sent to and stored in your computer by the websites you visit. Next time you visit the site, your browser will read the cookie and relay the information back to the website or element that originally set the cookie.
Cookies allow us to recognize you automatically whenever you visit our site so that we can personalize your experience and provide you with better service.