Parameter Store

Problem

Most applications need some configuration. Some configuration can be passed as environment variables, but what about passwords and other secrets? Do you want them listed in the config file? These would then be visible to anyone who had access to your version control system. Any developer would also see all of them, including the production passwords. AWS introduced Parameter Store as part of Systems Manager. This allows us to store encrypted passwords and other secrets.

Setup

We’ll start with the same setup as the initial tutorial, just an ECS cluster.

Configuration

Here’s the configuration for this service:

services:
  - name: hello-world-test
    cluster: hello-world-cluster
    count: 1
    family: hello-world
    containers:
      - name: hello-world
        image: tutum/hello-world
        cpu: 128
        memory: 256
    config:
      - VAR1=value1
      - VAR2=value2
      - PASSWORD1:secure=password1
      - PASSWORD2:secure=password2

The new parameter here is config:

config

This is a list of values, so each begins with a dash. For an unencrypted value, it is in the form:

- VARIABLE=VALUE

For an encrypted value, you must add the secure flag:

- VARIABLE:secure=VALUE

In this format, the encrypted value will be encrypted with the default key. For better security, make a unique key for each app and specify it in this format:

- VARIABLE:secure:arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab=VALUE

For more information about creating keys, see AWS Key Management Service (KMS).

Managing Config Parameters

In addition to deploying your services, you can also manage your config with deployfish using the config subcommand.

To view your current config in AWS, run:

deploy config show hello-world-test

To save config to AWS, run:

deploy config write hello-world-test

Reading From The Environment

You might have noticed that so far this solution is still displaying passwords in the deployfish.yml file for all the developers to see. This is not a good security practice as we’ve mentioned. The best way to deal with this is to have the secret parameter values defined in an environment variable. You would then change the config section to be:

...
config:
  - VAR1=value1
  - VAR2=value2
  - PASSWORD1:secure=${env.PASSWORD1}
  - PASSWORD2:secure=${env.PASSWORD2}

To make this easier, deployfish allows you to pass an environment file on the command line:

deploy --env_file=config.env create hello-world-test

This file is expected to be in the format:

VARIABLE=VALUE
VARIABLE=VALUE

These variables will all be loaded into the environment, so available to read from the config parameters. You would typically use a different file for each service.

You can also specify this file in the service definition itself:

services:
  - name: hello-world-test
    cluster: hello-world-cluster
    count: 1
    family: hello-world
    env_file: config.env
    ...

Using Config Parameters

So now that we have all of these values loaded into the AWS Parameter Store, how do we use them? We’ve included a subcommand in deployfish called entrypoint. You would define this as your entrypoint in your Dockerfile:

ENTRYPOINT ["deploy", "entrypoint"]

You would have to install deployfish in your container for this to work.

With this as your entrypoint, you will need to set the command parameter of the container to be your original entrypoint:

...
containers:
  - name: hello-world
    image: tutum/hello-world
    cpu: 128
    memory: 256
    command: /usr/bin/supervisord
...

The entrypoint that is run will then be:

deploy entrypoint <command>

or in this case:

deploy entrypoint /usr/bin/supervisord

When this is run, your defined config parameters will be downloaded from AWS Parameter Store and defined locally as environment variables, which you will then access as you would any environment variable.

If you run your docker container locally, the entrypoint subcommand will simply call the command without downloading anything from AWS Parameter Store. You would then use locally defined environment variables to set the various parameter values.