Encryption of secrets in source code (AESCrypt + Ansible)
The more I automate, the more I have to answer the question of how to manage my secrets. Secrets that frequently come up include:
- SSH key pairs
- SSL private keys
- Credentials for external resources, such as databases and SaaS integrations
Before cloud, when server resources were not ephemeral, these could be managed manually when the server was created. In cloud environments, servers are created and destroyed automatically and from minute to minute, which leaves the question about how to manage secrets.
The OpenStack community is working on one solution called Barbican. I’ve been looking at more local solutions to secret management that accommodates storage in a code repository alongside the application code that will be deployed. Some benefits to a local solution include:
- No additional systems to maintain
- Secrets can be versioned
- Infrastructure as code
Most of my automation efforts recently are centered on Ansible. One Ansible specific solution is Vault. The drawback to building secrets in to Ansible Vault is lock in to Ansible. In the future I may want to leverage other orchestration tools, such as puppet, chef or salt.
openssl
One option that works well for *nix only workloads is openssl. OpenSSL is widely used and available by default on virtually every Linux system.
Using openssl is straight forward:
openssl enc -aes-256-cbc -salt -in server.key -out server.key.aes -pass pass:secret openssl enc -d -aes-256-cbc -in server.key.aes -out server.key -pass pass:secret |
AESCrypt
I ended up choosing AESCrypt as my solution. Some key reasons for this choice include native binaries for Windows, Linux and Mac. AES encryption is very strong. The decryption key can be provided to ansible as a variable or handled manually on resulting servers.
Using AESCrypt is very simple. Below is a simple session on Windows.
C:\Users\Daniel Watrous\Documents\work\aescrypt>ls -la total 204 drw-rw-rw- 2 Daniel Watrous 2 0 0 2015-06-30 16:06 . drw-rw-rw- 73 Daniel Watrous 2 0 49152 2015-06-30 16:04 .. -rwxrwxrwx 1 Daniel Watrous 2 0 155136 2015-06-30 16:05 aescrypt.exe -rw-rw-rw- 1 Daniel Watrous 2 0 896 2015-06-30 16:06 mykey.txt C:\Users\Daniel Watrous\Documents\work\aescrypt>cat mykey.txt -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5 1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh 3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2 pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= -----END RSA PRIVATE KEY----- C:\Users\Daniel Watrous\Documents\work\aescrypt>aescrypt -e -p secret mykey.txt C:\Users\Daniel Watrous\Documents\work\aescrypt>ls -la total 208 drw-rw-rw- 2 Daniel Watrous 2 0 0 2015-06-30 16:07 . drw-rw-rw- 73 Daniel Watrous 2 0 49152 2015-06-30 16:04 .. -rwxrwxrwx 1 Daniel Watrous 2 0 155136 2015-06-30 16:05 aescrypt.exe -rw-rw-rw- 1 Daniel Watrous 2 0 896 2015-06-30 16:06 mykey.txt -rw-rw-rw- 1 Daniel Watrous 2 0 1188 2015-06-30 16:07 mykey.txt.aes C:\Users\Daniel Watrous\Documents\work\aescrypt>cat mykey.txt.aes AES☻ ↑CREATED_BY aescrypt 3.10 ? <↨%8±d>áFo♥p♠xÿ~ C:\Users\Daniel Watrous\Documents\work\aescrypt>rm mykey.txt C:\Users\Daniel Watrous\Documents\work\aescrypt>aescrypt.exe -d -p secret mykey.txt.aes C:\Users\Daniel Watrous\Documents\work\aescrypt>cat mykey.txt -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUp wmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ5 1s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQABAoGAFijko56+qGyN8M0RVyaRAXz++xTqHBLh 3tx4VgMtrQ+WEgCjhoTwo23KMBAuJGSYnRmoBZM3lMfTKevIkAidPExvYCdm5dYq3XToLkkLv5L2 pIIVOFMDG+KESnAFV7l2c+cnzRMW0+b6f8mR1CJzZuxVLL6Q02fvLi55/mbSYxECQQDeAw6fiIQX GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJrmfPwIGm63il AkEAxCL5HQb2bQr4ByorcMWm/hEP2MZzROV73yF41hPsRC9m66KrheO9HPTJuo3/9s5p+sqGxOlF L0NDt4SkosjgGwJAFklyR1uZ/wPJjj611cdBcztlPdqoxssQGnh85BzCj/u3WqBpE2vjvyyvyI5k X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= -----END RSA PRIVATE KEY----- |
Automation
It should be obvious from the above example that at some point the decryption still requires a password and that password should NOT be stored in the code repository. The decrypted files should also be ignored (not added to revision control). In other words, only commit the encrypted files.
The encryption password needs to be stored somewhere. One option is to keep it in your head. Another might be to keep it in lastpass or some other password manager, but be sure to keep it out of the repository where you have the encrypted secrets.
The password can be provided when calling the Ansible playbook.