{"id":3235,"date":"2015-02-27T18:36:06","date_gmt":"2015-02-28T00:36:06","guid":{"rendered":"http:\/\/benincosa.com\/?p=3235"},"modified":"2015-02-27T18:36:06","modified_gmt":"2015-02-28T00:36:06","slug":"secrets-with-ansible-ansible-vault-and-gpg","status":"publish","type":"post","link":"https:\/\/benincosa.com\/?p=3235","title":{"rendered":"Secrets with Ansible: Ansible Vault and GPG"},"content":{"rendered":"<p>I was blown away last night at our Ansible PDX meetup by a great <a href=\"https:\/\/docs.google.com\/presentation\/d\/1dBHltWfhDuoQV6tg0DJ5RNiNRzQKx1ZUZ1IWFfLmCE4\/edit#slide=id.p\">presentation<\/a> by <a href=\"https:\/\/twitter.com\/AndrewLorente\">Andrew Lorente<\/a> about how to track secrets with your applications. \u00a0Andrew gave a method of how to do this that I wanted to write down so I know how to do it. \u00a0Andrew has his <a href=\"https:\/\/blog.andrewlorente.com\/p\/using-pgp-to-encrypt-the-ansible-vault\">own blog here<\/a> where he wrote about the solution. \u00a0I wanted to go over it a little more in details cause I want to make sure it sticks in my head! \u00a0(bonus: I also learned about the pbcopy command on Mac last night!) \u00a0The other thing is since I didn&#8217;t have any of this on my machine it helps someone get started who hasn&#8217;t done anything with GPG yet.<\/p>\n<p>His technique involves some pretty simple tools:<\/p>\n<ul>\n<li><a href=\"http:\/\/docs.ansible.com\/playbooks_vault.html\">Ansible Vault<\/a><\/li>\n<li>GPG \/ GPG-Agent<\/li>\n<\/ul>\n<h3>1. Generate an Ansible Vault Password<\/h3>\n<p>On my mac I run:<\/p>\n<pre class=\"lang:default decode:true\">brew install pwgen\r\nbrew install gpg\r\nbrew install gpg-agent<\/pre>\n<p>This gets me my tools! \u00a0Ok, so now I need to generate my pgp key.<\/p>\n<pre class=\"lang:default decode:true \">gpg --gen-key<\/pre>\n<p>Doing this I just accepted all the defaults.<\/p>\n<p>Now I generate a password for the vault.<\/p>\n<pre class=\"lang:default decode:true\">pwgen -cynC | head -1 | gpg -e -o vault_passphrase.gpg\r\nYou did not specify a user ID. (you may use \"-r\")\r\n\r\nCurrent recipients:\r\n\r\nEnter the user ID.  End with an empty line: vallard\r\n                                                    \r\nCurrent recipients:\r\n2048R\/BDF6142D 2015-02-27 \"Vallard Benincosa &lt;vallard@benincosa.com&gt;\"\r\n\r\nEnter the user ID.  End with an empty line:<\/pre>\n<p>Now that I have that I follow Andrew&#8217;s instructions and create a file called open_the_vault.sh with the contents being:<\/p>\n<pre class=\"lang:default decode:true \">#!\/bin\/sh\r\ngpg --batch --use-agent --decrypt vault_passphrase.gpg<\/pre>\n<p>Then make sure I can run this file as an executable<\/p>\n<pre class=\"lang:default decode:true \">chmod +x open_the_vault.sh<\/pre>\n<p>Add this to my ansible.cfg file<\/p>\n<pre class=\"lang:default decode:true\">[defaults]\r\nvault_password_file=open_the_vault.sh\r\nhostfile = .\/inventory\r\nhost_key_checking = false<\/pre>\n<h3>\u00a02. \u00a0Setup the GPG Agent<\/h3>\n<p>If you now run the command .\/open_the_vault.sh you&#8217;ll find that it says: &#8220;Hey, there&#8217;s no agent running!&#8221;. \u00a0There are a few ways we can start the agent. \u00a0You can create <a href=\"http:\/\/www.weinschenker.name\/2013-10-08\/use-gpgtools-for-ssh-logins-on-mac-os-x\/\">a LaunchAgent as shown here<\/a>, or you can just configure something in your own shell. \u00a0I went with my own shell method and basically <a href=\"http:\/\/sudoers.org\/2013\/11\/05\/gpg-agent.html\">followed this post<\/a>.<\/p>\n<p>Create ~\/.bash_gpg<\/p>\n<pre class=\"lang:default decode:true \">envfile=\"${HOME}\/.gnupg\/gpg-agent.env\"\r\n\r\nif test -f \"$envfile\" &amp;&amp; kill -0 $(grep GPG_AGENT_INFO \"$envfile\" | cut -d: -f 2) 2&gt;\/dev\/null; then\r\n    eval \"$(cat \"$envfile\")\"\r\nelse\r\n    eval \"$(gpg-agent --daemon --log-file=~\/.gpg\/gpg.log --write-env-file \"$envfile\")\"\r\nfi\r\nexport GPG_AGENT_INFO  # the env file does not contain the export statement\r\n<\/pre>\n<p>Append to ~\/.bashrc<\/p>\n<pre class=\"lang:default decode:true \">GPG_AGENT=$(which gpg-agent)\r\nGPG_TTY=`tty`\r\nexport GPG_TTY\r\n\r\nif [ -f ${GPG_AGENT} ]; then\r\n    . ~\/.bash_gpg\r\nfi<\/pre>\n<p>Create ~\/.gnupg\/gpg-agent.conf<\/p>\n<pre class=\"lang:default decode:true \">default-cache-ttl 600\r\npinentry-program \/usr\/local\/bin\/pinentry\r\nno-grab\r\nmax-cache-ttl 172800\r\n<\/pre>\n<p>Opening up a new shell, I should now be able to run \u00a0the .\/open_the_vault.sh command. \u00a0It will ask me for my password the first time, but if I run it again, it won&#8217;t ask me again. \u00a0Right now the default-cache-ttl is set to 600 or 10 minutes. \u00a0This can be increased if I want it open longer.<\/p>\n<h3>3. Encrypt the file<\/h3>\n<p>The file I will be encrypting is a main.yml file that contains all my variables. \u00a0Since it already exists I run the command<\/p>\n<pre class=\"lang:default decode:true\">ansible-vault encrypt roles\/openstack-controller\/vars\/main.yml\r\n<\/pre>\n<p>Now, if I look at this file roles\/openstack-controller\/vars\/main.yml you&#8217;ll see its just a bunch of random encypted numbers! \u00a0Awesome! \u00a0Now my environment variables and my password file can all be committed with git.<\/p>\n<p>Now obviously, if you look at the history of this project I&#8217;m working on, you&#8217;ll see the old unencrypted file, but that&#8217;s ok, I&#8217;ve changed the passwords now so its super secure! \u00a0From now on though, no more simple passwords and I&#8217;ll be using these methods to encrypt.<\/p>\n<h3>4. \u00a0Sharing Keys<\/h3>\n<p>Obviously this solution works great for one developer, but what if we have more developers? \u00a0They will also need to be able to run the key. \u00a0To do this, we just need to encrypt the file with all of our users. \u00a0We now decrypt the vault_passphrase.gpg with our open_the_vault.sh command. \u00a0We then get the output of our passphrase.<\/p>\n<pre class=\"lang:default decode:true \">.\/open_the_vault.sh &gt;unencypted_passphrase\r\n\r\n<\/pre>\n<p>Now, we encrypt it again with all of our users. \u00a0The new user will need to share his key with you so that you can encrypt it.<\/p>\n<pre class=\"lang:default decode:true \">cat unencypted_passphrase | gpg -e -o vault_passphrase.gpg<\/pre>\n<p>Test that it works by trying to edit the file<\/p>\n<pre class=\"lang:default decode:true \">ansible-vault edit roles\/openstack-controller\/vars\/main.yml<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was blown away last night at our Ansible PDX meetup by a great presentation by Andrew Lorente about how to track secrets with your applications. \u00a0Andrew gave a method of how to do this that I wanted to write down so I know how to do it. \u00a0Andrew has his own blog here where&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1013,606],"tags":[530,699,701,700],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3235"}],"collection":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3235"}],"version-history":[{"count":1,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3235\/revisions"}],"predecessor-version":[{"id":3236,"href":"https:\/\/benincosa.com\/index.php?rest_route=\/wp\/v2\/posts\/3235\/revisions\/3236"}],"wp:attachment":[{"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/benincosa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}