Basic Vault setup was covered in a previous post. In this one, we are going to focus on integrating Vault with AWS ECS. The goal here is to allow services to access Vault on a dedicated service namespace.

Vault recently released new AppRole authentication geared towards machines and services. AppRole is a set of login credentials — that allows us to get a Vault Token with a pre-defined scope.


The AWS IAM Task Role lets you specify which containers have access to the AWS S3 bucket. It contains a pre-generated file with a Vault AppRole Role ID that allows you to sign in to Vault with a predefined scope.

Vault setup

Vault Role should include a Vault Policy with read-only access to the application namespace. In our case, we do not use the secret_id (bind_secret_id = false), and we use a CIDR block that can execute login.

Creating policy(my-policy.hcl)

path "secret/myapp" {
  capabilities = ["read", "list"]

Adding policy

vault write sys/policy/myapp-policy rules=@my-policy.hcl

Creating AppRole

vault write auth/approle/role/myapp bound_cidr_list= bind_secret_id=false policies=myapp-policy

Reading generated Role ID

vault read -format=json auth/approle/role/myapp/role-id

AWS setup

The AWS Task Role should have exclusive access to the AWS S3 bucket subfolder. That subfolder will contain the Vault AppRole Role ID required for Vault login.
The Task Role should be assigned to Task definition.

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Action": [
            "Resource": [

Application configuration

Now inside the running ECS task, we can reach the dedicated AWS S3 subfolder and get the role_id. We use it to log in and get a Vault token.

vault write auth/approle/login role_id=db02de05-fa39-4855-059b-67221c5c2f63

For convenience, we use envconsul to populate the subprocess with Vault data. It is injected as environment variables and handles token refreshing.


  address = ""
  renew = true
  token = {insert-vault-token}

Start app like

envconsul -config="./config.hcl" -secret="secret/myapp" ./

All those commands can be added to the Dockerfile and should be used as CMD. This gist wraps all of the above in one shell script. It uses Alpine as the base image.


FROM mhart/alpine-node:6.9.1
RUN apk add wget curl py-pip jq
ADD /opt
CMD ["", "yarn start"]