Hey all
So we have had some discussions about how to store secrets/passwords when working with Processes:
Recently we came up with the following solution:
Using Docker Secrets (Blog | Docker) you can manage sensitive data: with the Secrets feature, which basically creates a in-memory volume that stores your secret(s): Manage sensitive data with Docker secrets | Docker Docs
How Docker manages secrets
When you add a secret to the swarm, Docker sends the secret to the swarm manager over a mutual TLS connection. The secret is stored in the Raft log, which is encrypted. The entire Raft log is replicated across the other managers, ensuring the same high availability guarantees for secrets as for the rest of the swarm management data.
Reference from: Manage sensitive data with Docker secrets | Docker Docs
So with this we created a Docker-Compose File that looks like:
version: '3.1'
services:
camunda:
build: .
environment:
JAVA_OPTS: -Djava.security.egd=file:/dev/./urandom -Duser.timezone=America/Montreal
MY_PASSWORD_FILE: /run/secrets/my_password
secrets:
- my_password
ports:
- "8080:8080"
secrets:
my_password:
file: my_password.json
Our Dockerfile looks like:
FROM camunda/camunda-bpm-platform:tomcat-7.7.0
# add custom configurations
COPY docker/camunda/conf/ conf
# Copy third-party Java libraries
COPY docker/camunda/lib/* lib
(you only really need line 1. The rest is use for adding additional configs (such as deployment-aware=false) and adding the Jsoup.jar)
Next, in the same folder as the dockerfile and docker-compose file we have our my_password.json
file.
which could look like this:
{
"someKey": "somePassword",
"someKey2": "somePassword2"
}
You can use .txt files or whatever format you like.
And of course DO NOT commit your password file into your GIT-repo/SCM. Use gitignore at the very least to omit the password file from commits.
When you run docker-compose up
, Camunda will be deployed, and a ‘Secrets’ volume will be created.
Now that we have Camunda running with the Secrets volume, we need to access it.
So during the process execution, we can run the following Javascript (nashorn) at any point to retrieve a password, all in-memory and without the use of process variables.
/**
* Load Passwords Json File and returns a specific password
*
* @param string passwordKey The json property key that the password is stored. Currently only single level json is supported.
* @param string passwordEnvName The Env Variable name that the JSON is stored in using Docker Secrets
* @return string The password. Assumes that all passwords are strings and therefore returns a string.
*/
function getPassword(passwordKey, passwordEnvName)
{
with (new JavaImporter(java.lang.System, java.nio.file))
{
var passwordPath = System.getenv(passwordEnvName)
var passwordFileBytes = Files.readAllBytes(Paths.get(passwordPath))
}
var String = Java.type('java.lang.String')
var passwordFileString = new String(passwordFileBytes)
var passwordJson = JSON.parse(passwordFileString)
var password = passwordJson[passwordKey]
return password.toString()
}
var myPassword = getPassword('someKey', 'MY_PASSWORD_FILE')
Of course you can modify this structure and the way you use Docker Secrets to just return single text files.
The Process could look like this if you were to save the password (which you should not) as a process variable:
Also take a look at the docs for info about Rotating your secrets: Manage sensitive data with Docker secrets | Docker Docs
Quick Start / Ready to Go:
Here is a dockerfile and docker-compose ready to be used:
Includes Jsoup
, deployment-aware=false
and the Docker Secrets configuration that is explained above.
Enjoy
As always if you end up using this, please share your experience and thoughts!