# 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.