Manage secrets wth Vault Agent with Amazon Elastic Container Service
This tutorial covers the configuration required to allow an Amazon Elastic Container Service (ECS) task definition to retrieve a secret from HashiCorp Vault. You will configure an ECS task definition with sidecar container for Vault Agent that authenticates to Vault with the AWS Identity & Access Management (IAM) authentication method. The Vault Agent sidecar writes the secrets to a shared Amazon EFS volume for the application container to use.
The tutorial uses HashiCorp Cloud Platform (HCP) Vault, Amazon ECS on AWS Fargate and Amazon EFS volumes. However, you can adjust the configurations to work with any external Vault cluster outside of an Amazon ECS cluster and Amazon ECS on Amazon EC2.
First, you'll use Terraform to set up infrastructure in us-east-1
and configure the
ECS task to authenticate to Vault. Your ECS task (called product-api
) will
use the AWS IAM auth method to authenticate to Vault using its task role.
Then, the task retrieves a database username and password managed by the Vault database
secrets engine. Finally, Vault Agent writes the database username and password to a
shared volume for the application to use. Vault will need access
to the database to configure secrets.
Note
The Vault Agent on Amazon ECS container image and Terraform modules in this tutorial are created for demonstration purposes and not intended for production use! They can help you build your own secure container image to run Vault Agent on Amazon ECS.
Prerequisites
The following prerequisites are required:
Your AWS credentials configured locally. Copy the credentials and set them as environmnent variables in your terminal.
Export the access key value.
Export the secret access key value.
Export the session token value.
Access to HashiCorp Cloud Platform via a service principal and key. Copy the credentials and set them as environmnent variables in your terminal.
Export the client ID.
Export the client secret.
Clone vault-guides repository
Clone the demo assets from the hashicorp/vault-guides GitHub repository to perform the steps described in this tutorial.
This repository contains supporting content for all of the Vault tutorials. The content specific to this tutorial can be found within a sub-directory.
Be sure to set your working directory to the vault-guides/identity/vault-agent-ecs
folder.
The working directory should contain the provided Terraform configurations:
Set up infrastructure
Before you can deploy an example service to Amazon ECS, you need to create the following:
- Amazon ECS cluster using AWS Fargate
- A database (Amazon ECS service) and load balancer endpoint
- HCP Vault Dedicated cluster
- An application load balancer
- Amazon EFS volume (for storing secrets rendered from Vault Agent)
You'll create these resources with Terraform.
Change your directory to the
infrastructure/
folder, which contains the initial setup.Verify that you are in the correct directory before proceeding.
Initialize Terraform.
After Terraform is initialized, you can verify that it will create the resources with
terraform plan
.You should note resources listed in the output.
Deploy the resources with
terraform apply
.Confirm the run by entering
yes
. Once you confirm, Terraform may take 15 minutes or more to complete the deployment.Note
You may get an error that Terraform failed to find a routing table. This error results from a race condition with the peering connection to the HashiCorp Virtual Network (HVN). Re-run Terraform with
terraform apply
to resolve the error.If the deployment succeeds, Terraform outputs a set of resource IDs, endpoints, and secrets.
Check that Terraform successfully deployed the database (called
product-db
) to your Amazon ECS cluster (calledlearn
). The ECS service should have a running count of 1.Return your directory to the
vault-guides/identity/vault-agent-ecs/
folder for the next step.
Set up Vault authentication methods and secrets engines
You deployed your infrastructure, including an Amazon ECS and HCP Vault Dedicated cluster. However, you need to configure Vault with authentication methods and secrets engines in order for it to dynamically manage credentials.
Configure AWS IAM authentication method for ECS task role
An Amazon ECS task needs to authenticate to Vault before it can read secrets from Vault. Rather than copy and paste a Vault token into an ECS task definition, you can use the Amazon ECS task's IAM role to authenticate to Vault. Configure Vault's AWS IAM authentication method with the task IAM role.
All Vault configurations exist in the vault/
directory, which you'll apply with
Terraform.
Examine vault/iam.tf
, which references a local module in the
modules/vault-task/iam
directory.
12345
Review the module under modules/vault-task/iam
. The file modules/vault-task/iam/iam.tf
defines a list of allowed AWS policies and the task IAM role.
You'll find three main policies:
vault-agent
: allows the task to use the AWS IAM auth methodecs-task
: allows the task to create logs and deploy to the clusterefs-access-point
: allows the task to access an EFS access point. You created this using the Terraform underinfrastructure/
.
1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
Terraform will create a new IAM role and attach these policies. You will use this IAM role for your task definition.
1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031323334353637
After creating the IAM role, you can bind it as a principal to Vault's AWS IAM auth method.
Examine the file vault/auth.tf
. It sets up the AWS auth backend.
Then, it configures the auth backend with a Vault role that uses
the iam
authentication type and attaches to the task IAM role.
You also attach a Vault policy so the role can read secrets.
1 2 3 4 5 6 7 8 9 101112
Note
The configuration sets resolve_aws_unique_ids
to false
because we use HCP Vault Dedicated. Vault Dedicated requires
cross-account access.
When you attach the task IAM role to the Vault role, you allow an AWS entity using the role to authenticate to Vault.
Set up database secrets engine
Your database (product-db
) has a administrative username and password.
However, you don't want your application (product-api
) using the admin credentials.
You set up the database secrets engine in Vault to
dynamically generate
a username and password for the application.
Examine the file vault/database.tf
. It sets up the database secrets engine
for PostgreSQL at the path learn/database
and configures a database
connection using the root username and password.
1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031323334353637383940
Terraform will create a Vault role. The Vault role issues a database
username and password for one week (default_ttl
). Terraform also adds a Vault
policy to allow the product-api
to read the database credentials.
Important
When you define the role in a production deployment, you must create user creation_statements, revocation_statements, renew_statements, and rotation_statements which are valid for the database you've configured. If you do not specify statements appropriate to creating, revoking, or rotating users, Vault inserts generic statements which can be unsuitable for your deployment.
Configure Vault with Terraform
Create the Vault role, policy, authentication method, and database secrets engine with Terraform.
Verify that you are in the
vault-guides/identity/vault-agent-ecs/
folder for the next step.Set Terraform environment variables to pass the product database connection information and EFS access point ARN. The configuration needs these values in order to configure the database secrets engine and set up the IAM role for the task. Terraform will retrieve inputs from environment variable prefixed with
TF_VAR_
.Set the
VAULT_ADDR
,VAULT_TOKEN
, andVAULT_NAMESPACE
environment variables so you can connect to Vault Dedicated.Note
You set the Vault namespace to
admin
because Vault Dedicated uses Vault namespaces.Change your directory to the
vault/
folder, which contains the Vault configuration.Verify that you are in the correct directory before proceeding.
Initialize Terraform.
After Terraform is initialized, you can verify that it will create the resources with
terraform plan
.You should note resources listed in the output.
Deploy the resources with
terraform apply
.Confirm the run by entering
yes
.If the deploy was successful, you should observe output at the end with a Vault role name, Vault database credentials path, and task IAM role ARN.
Check that Terraform successfully configure Vault by retrieving a database username and password from the database secrets engine.
Return your directory to the
vault-guides/identity/vault-agent-ecs/
folder for the next step.
Deploy example application to ECS cluster
You deployed your infrastructure, configured Vault's database secrets engine to rotate database usernames and password, and created an authentication method to allow an IAM role to authenticate to Vault.
You can now use the IAM role, assign it to your ECS service, and inject a Vault
agent sidecar container to get database credentials for the application (product-api
).
Configure Vault Agent sidecar for an ECS service with Terraform
An Amazon ECS task needs to authenticate to Vault before it can read secrets from Vault. Vault Agent can help you authenticate to Vault and write the database credentials to a file. The application uses the credentials from the file. This pattern ensures that you do not have to make changes to your application to authenticate to Vault.
All ECS task definitions and service configurations exist in the application/
directory, which you'll apply with Terraform.
Examine application/product.tf
, which references a module under modules/vault-task/ecs
.
The module accepts an input variable with a
Vault Agent template. You pass the
database credentials path in Vault, database address, and products-api
port to the
template. You also need to configure the application to read the database configuration
from the /config
directory on the task's shared EFS volume.
1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930313233343536373839404142434445464748495051
Examine application/templates/conf.json
. The product-api
application reads
the configuration from this file in order to connect to the database,
set up ports, and explose metrics. Vault Agent will template the
database username and password based on the Vault database credentials path
passed through Terraform.
1234567
Examine the Terraform resource for aws_ecs_task_definition
in
modules/vault-task/ecs/task.tf
. This submodule takes an application's
container definition and adds a container
definition for a custom Vault Agent container image.
Note
The Vault Agent on Amazon ECS container image are created for demonstration purposes and not intended for production use! You can refer to the container build file as a reference for building your own.
It sets the task_role_arn
to the
IAM role you created previously in the vault/
configuration. The IAM role
allows the task to authenticate to Vault.
1 2 3 4 5 6 7 8 9 10
The aws_ecs_task_definition
resource also defines an EFS volume
configuration using the EFS file system ID and access point ID
you set up with the infrastructure/
configuration. The EFS access point
will securely store the database connection string rendered by Vault Agent.
1 2 3 4 5 6 7 8 9 101112131415161718
The module allows you to append your own volumes to the ECS task definition. However, it defines the Vault Agent's EFS volume configuration by default.
You will also find that container_definitions
for aws_ecs_task_definition
resource appends your task's container definition with a separate one for Vault Agent.
The task definition will start the Vault Agent container. Vault Agent authenticates
to Vault using its task IAM role and generates a file containing the secrets.
You must set the following environment variables for the example Vault Agent container:
VAULT_ROLE
: Name of the Vault role attached to the AWS IAM auth method. In this case, it useslearn-product-api
.TARGET_FILE_NAME
: Name of the rendered file. The container reads the template from the/vault-agent
directory and writes it to the/config
directory.VAULT_AGENT_TEMPLATE
: Base-64 encoded contents of a Vault Agent template. This allows Vault Agent to write the credentials to file compatible with the application.VAULT_AGENT_EXIT_AFTER_AUTH
: Exit the Vault Agent after rendering the template. Sinceproduct-api
uses dynamic database credentials, you set this tofalse
. This allows the Vault Agent to continuously run as a sidecar and check for credentials rotation.VAULT_ADDR
: Allows the Vault Agent to connect to Vault Dedicated. The Terraform configuration sets it as a global constant to append to the container definition's environment variables.VAULT_NAMESPACE
: Sets the Vault namespace for the Vault Agent to retrieve credentials. The Terraform configuration sets it as a global constant to append to the container definition's environment variables.
1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
Note
If you have static credentials, you can configure VAULT_AGENT_EXIT_AFTER_AUTH
to true
.
The agent will write the credentials to the file and exit with status 0.
After the Vault Agent starts, it writes an application configuration file with
the database connection string to the EFS volume. The application container (product-api
)
starts and reads the database connection string from the volume.
Deploy the ECS service with Terraform
You will use Terraform to create the ECS service (product-api
) with the Vault Agent
sidecar.
Verify that you are in the
vault-guides/identity/vault-agent-ecs/
folder for the next step.Set Terraform environment variables to pass the Vault address and namespace to the task definition. Terraform will retrieve inputs from environment variable prefixed with
TF_VAR_
.Set Terraform environment variables to pass the EFS file system ID, access point IDs, IAM role, and database path to the ECS task definition.
Set Terraform environment variables to pass the subnet information, ECS and database security groups, and target group. The ECS service for
product-api
uses these variables to connect the application to the load balancer.Change your directory to the
application/
folder, which contains the ECS service configuration forproduct-api
.Verify that you are in the correct directory before proceeding.
Initialize Terraform.
After Terraform is initialized, you can verify that it will create the resources with
terraform plan
.You should note resources listed in the output.
Deploy the resources with
terraform apply
.Confirm the run by entering
yes
. Terraform may take 5 minutes or more to finish deployment.If the deployment succeeds, you should observe output at the end with a Vault role name, Vault database credentials path, and task IAM role ARN.
Return your directory to the
vault-guides/identity/vault-agent-ecs/
folder for the next step.Check that Terraform successfully deployed the application (called
product-api
) to your Amazon ECS cluster (namedlearn
). The ECS service should have a running count of 1.You can test the
product-api
by getting information about coffees from its API endpoint. The response should include JSON metadata about coffees.A succesfully response indicates that the
product-api
authenticated to theproduct-db
using the dynamic credentials retrieved by Vault Agent!
Clean up
You can remove all resources by running a clean-up script. Verify that you
are in the vault-guides/identity/vault-agent-ecs/
folder for
the next step.
Run the cleanup.sh
, which will automatically destroy all
resources and revoke the leases for database credentials from Vault.
It may take more than 15 minutes to remove all resources.
Next steps
In this tutorial, you injected Vault Agent as a sidecar for an Amazon ECS task and retrieved PostgreSQL database credentials dynamically from Vault Dedicated. To learn more about the Vault features introduced in this tutorial, refer to the following tutorials.