Summon + Docker
Docker works best when you follow the 12-factor suggestion of storing your config in the environment. Your images are then immutable artifacts that you can move through environments. This works great for public config (DNS names, database ports, log levels, etc), but what about sensitive config (database passwords, API tokens, etc)? You can bake credentials into your images, but now you have to lock down your images and rotation is difficult. You can repurpose tools like consul or etcd to serve secrets, but they are not meant for passing around secrets.
Using Summon with Docker means that the secrets your application needs are declared
in secrets.yml
and can be checked into source control right next to your Dockerfile.
Since Summon has pluggable providers, you aren’t locked into any one solution for
managing your secrets.
Summon makes it easy to inject secrets as environment variables into your Docker
containers by taking advantage of Docker’s --env-file
argument. This is done
on-demand by using the variable @SUMMONENVFILE
in the arguments of the process
you are running with Summon. This variable points to a memory-mapped file containing
the variables and values from secrets.yml in VAR=VAL format.
$ summon -p keyring.py -D env=dev docker run --env-file @SUMMONENVFILE deployer
Checking credentials
Deploying application
Example
Let’s say we have a deploy script that needs to access our application servers on AWS and pull the latest version of our code. It should record the outcome of the deployment to a datastore. To deploy, then, we need AWS keys and a MongoDB password.
1. Clone the Summon repository
This example is stored in the Summon repository in the examples
folder. To get
started, we’ll need to clone the Summon repository and navigate to the example folder.
$ git clone https://github.com/cyberark/summon.git
$ cd summon/examples/docker/
There are 3 key files in this directory.
secrets.yml
This is the file that Summon will read, and it contains a mapping of environment
variables to the name of secrets we want to fetch. Secrets are dependencies so
we should be able to track them in source control. $env
is a variable that we
will supply at runtime with Summon’s -D
flag. This means that we can use one
secrets.yml
file for all environments, swapping out $env
as needed.
deploy.py
A stubbed-out deploy script. It checks that you have the proper credentials before attempting a deploy.
Dockerfile
Inherits from the offical Python Docker image and runs the deploy script.
2. Build and run the container
Note: Install Docker if you don’t already have it on your system.
Now we can build a Docker image and run our deploy script inside it.
$ docker build -t deployer .
...
$ docker run deployer
Checking credentials
AWS_ACCESS_KEY_ID not available!
AWS_SECRET_ACCESS_KEY not available!
MONGODB_PASSWORD not available!
Our deploy script is checking for available credentials. None are available, so it doesn’t run the deploy.
3. Install Summon and the keyring provider
Install Summon following the instructions in the README.
We’ll use the keyring provider for this tutorial since it is cross-platform and doesn’t require communication with a secrets server. Install it following its README instructions.
4. Run the container with Summon
We want to provide our credentials to the container with Summon. Since we’re using the keychain provider, we’ll put those secrets in our keychain. The keychain provider is extensible and supports many keyring implementations out of the box. We’ll use the OSX keychain for this example - modify the commands depending on the keychain you use.
Remember the $env
variable in our secrets.yml
? We’ll use ‘dev’ for this tutorial,
since we’d probably not use the keyring provider in production. Load the secrets into
your keychain. We’ll use “summon” as the service name.
$ security add-generic-password -s "summon" -a "dev/aws_access_key_id" -w "AKIAIOSFODNN7EXAMPLE"
$ security add-generic-password -s "summon" -a "dev/aws_secret_access_key" -w "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
$ security add-generic-password -s "summon" -a "dev/mongodb_password" -w "blom0ey4hOj3We"
Now we can run Docker with Summon to provide our credentials.
$ summon -p keyring.py -D env=dev docker run --env-file @SUMMONENVFILE deployer
Checking credentials
Deploying application
Summon parsed secrets.yml
, used the keychain provider to fetch values from our
keychain and made them available to Docker as @SUMMONENVFILE
. Neat huh?
You can also view the value of @SUMMONENVFILE
by simply cat
ing it.
$ summon -p keyring.py -D env=dev cat @SUMMONENVFILE
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
MONGODB_PASSWORD=blom0ey4hOj3We
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
We hope Summon makes it easier for you to work with Docker and secrets. If you have an idea for a new feature or notice a problem, please don’t hesitate to open an issue or pull request on GitHub.