Over the last few days, I've been doing a whole lot of work with Docker Swarm, AWS, and Spring boot. To give a little bit of context, I ended up using the Standard AWS docker template, and a Dynamo Db instance to host the data. Of course, this lead me to the age-old problem; how do I store my secrets securely and NOT within my app. And so, I thought I'd give Docker Secrets a go!
I guess the first thing I should answer is the most obvious; what are secrets? Well, a Secret is a passcode, a password, or a key of some sort that is needed to access a data store or some form of precious item. It's a super bad idea to store this within your application (just search Github), and so some form of solution is required to load your secrets in at run time. A load of stuff has been written about Secrets, and what you should use and do and blah blah bah. In this blog however, I'm going take a look at my experience with Dockers home grown solution; Docker Secrets and using it with Spring boot.
You can find out a whole lot about Docker Secrets from their official website, but the brief overview is this: you create a secret, which is a key-value affair, from either a file or some form of input stream, and this is stored securely within the master node(s) of your Docker Swarm. From here, you can give a Secret to a Docker Service, where in the Containers for the Service, a new root folder will be added called "/run/secrets", where your Secrets will be loaded in file format. These files are your Secrets, where the name is the secret name, and the contents of the file is the actual Secret value. Simple enough, and means pretty much every programming language can access them.
So, back to my own experience. Overall, it was super simple to set up and get working. I have small Springboot application which needs to connect to a Dynamo Db instance. This means on startup of the application I need the accesskey and passkey to get into the database. I'm not going to store this in application, nor am I going to put it in a Docker Container / Image, as these will be hosted externally, and could be gotten hold of by some dastardly fiend.
So, using the @PostConstract annotation, I wrote a little method that looked for the default Docker Secrets folder, and loaded all the files found there into a HashMap, where the file names the keys, and the contents the values. From here, I could take the Hashmap and store them as properties in the application for use during other configuration steps. See, simple! Once I was confident the code worked, I went ahead and extracted it into a small micro-library which wraps all this up. It's not very feature complete, so pull requests welcome!
First off, I thought this was going to a much bigger pain to apply Secrets to my project. I'm confident that the Secrets are safe, and I know that as I add more masters and nodes I don't have to re-add the Secrets to each box; they should just propagate around the network. Also, if I need to update a secret, I know I can without having to go to each environment to update them. It just makes things super simple.
If you've got any feedback or suggestions, contact me in the usual ways!Cheers, Harry