Often I find myself needing to repeatedly access a service that is password protected. A good example would be trying to curl an end point that is behind basic auth, another is dealing with projects that expect global variables with access credentials in them. There are armies of bots out there, scraping Github, just waiting for someone to accidentally commit some credentials to a public repository. There have also been a short list of clients that for one reason or another required me to connect to the root account of some server using password based access. Oh, the things we do for our clients.

My solution to this problem is to never store any credential in a local configuration file. Since I do the majority of my work on OSX machines I've begun storing any credentials I need to access programmatically inside the Keychain. We can access the Keychain using the built in security utility.

Store a password in the Keychain

security add-generic-password -U -a <account_name> -s <service_name> -w <password>  

Retrieve a password from the Keychain

security find-generic-password -ga <account_name> -w  

The security command is very well documented here Security Man Page

As an example, we can see how I might handle a script that needs access to the Openstack API. This is what a generic Openstack RC file looks like.

export OS_USERNAME=username  
export OS_TENANT_NAME=projectName  
export OS_AUTH_URL=https://identityHost:portNumber/v2.0  
export OS_TENANT_ID=tenantIDString  
export OS_REGION_NAME=regionName  
export OS_CACERT=/path/to/cacertFile  
export OS_PASSWORD=password  

While most of that information is fairly benign, there is a password hanging out right there at the end. We can normally fix it by doing something like this.

echo "What is your password"  
read supersekret  
export OS_PASSWORD=$supersekret  

But If you are dealing with tons of Openstack tenants across several installations, good luck remembering them all without writing them down somewhere, and you stil have to provide the passowrd the first time you access the api in a particular shell.

So here is an example of the above script using the OSX Keychain instead. It is certanly more verbose, but with a little effort and a helper function or two can whittle this down to a trivial amount of ceremony each time you need to do it.


#get the password from the keychain
supersekret=$(security find-generic-password -ga ${os_account_name} -w)

#if the security command does not run sucessfully, prompt
if [ $? -gt 0 ]; then  
  echo "What is your password"
  read supersekret
  security add-generic-password -U -a ${os_account_name} -s    ${os_service_name} -w ${$supersekret}

export OS_PASSWORD=$supersekret  

Remember, play safe kids!