Skip to content

Instantly share code, notes, and snippets.

@scoutman57
Created November 7, 2017 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scoutman57/c775492b445f4ccdc4b80014216ea543 to your computer and use it in GitHub Desktop.
Save scoutman57/c775492b445f4ccdc4b80014216ea543 to your computer and use it in GitHub Desktop.
Storing CLI password in Keychain on Mac OS X

Secure CLI Passwords with Keychain Services on Mac OS X

Creating a Password

Dump a password into keychain. I'm using the creator/kind codes "asbl" for Ansible, but you can use any 4 character code. It's useful for doing lookups later.

$ security add-generic-password -a "root" -c "asbl" -C "asbl" -D "Ansible Vault" -s "ansible secrets" -w "secret123password456"

From man security:

-a account     Match account string
-c creator      Match creator (four-character code)
-C type         Match type (four-character code)
-D kind         Match kind string
-G value        Match value string (generic attribute)
-j comment      Match comment string
-l label        Match label string
-s service      Match service string

Note that the "service" shows up as the "where" field in keychain, label "shows" up as "name". Nice work on that UX consistency Apple.

Recalling a Password

You can pull out that password by matching on the params you supplied. Going by service name I could do:

$ security find-generic-password -s "ansible secrets" -w

The -w option causes only the password to be printed.

It's useful to know that you can specify any combination of parameters when extracting passwords and security will take the first match. That's useful if you have multiple gmail accounts. You can specify -s "GMail" on both and the -l "work" and -l "home" on another. When extracting you can get the work one by using security find-generic-password -l "work" -s "GMail".

A Note about Ansible

In the case of ansible we need to pass a file, so we can make a simple wrapper script that will "do the right thing" for us and then pass that as the vault-password-file option. Create a script called vault_from_keychain.sh and chmod +x it, the content should be:

#!/bin/sh
exec security find-generic-password -s "hipyard-ansible secrets" -w

Finally, you can use it in ansible as a command line argument:

$ ansible-playbook Hipyardweb.yml -i inventory/production/hosts -t use_secrets --use-password-file vault_from_keychain.sh

Using it

I have this in my mutt configuration files to store passwords settings (e.g. mutt)

…
set smtp_pass = `security find-generic-password …`
…

but you can also use it to pass data as a CLI parameter

$ someapp dosecurething -user="myusername" -password=`security find-generic-password…`

Warnings

When passing a password as a CLI parameter it will be visible in the process list. Be careful using this kind of thing in this fasion:

$ bundle exec ruby foo_server.rb --user=foobar --password=`security find-generic-password …`

As your password will appear if somebody runs ps aux |grep foo_server

Likewise, you're going to be asked by keychain to allow access to a password item. Once you've allowed a process in iterm to access that password "Always", you're going to allow any future processes to access that item too. Approve foo.rb and bar.rb will be able to read that item too. You probably want to store any truely secret passwords in a seperate keychain vault that isn't unlocked by default if you want it to be protected from malicious processes running under your user account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment