DEV Community

Adam Rogers
Adam Rogers

Posted on

Password management on the command line

pass is a command line password manager for Linux that embodies the UNIX philosophy. It's like 1Password, but it lives in your terminal. This comes with some drawbacks, certainly, but is also very powerful.

Here we'll get pass installed and then explore a couple reasons why you might like a Command Line Interface (CLI) to your password manager.

Installation

I'm using Ubuntu 18.04 (I know), but these instructions should work for any apt based distribution, and should be easily adaptable to your *nix of choice.

First, we'll make sure we have pass itself, gpg which comes with Ubuntu by default and will be used to encrypt our passwords, and also xclip, which we'll use to copy passwords to the system clipboard.

$ sudo apt install pass gpg xclip
Enter fullscreen mode Exit fullscreen mode

Getting started

Before we can use pass, we'll need a generate a GPG keypair. To do that, we'll kick off the keypair generation wizard like so:

$ gpg --full-generate-key
Enter fullscreen mode Exit fullscreen mode

Choose the default kind of key (RSA), and default keysize (3072). Set the expiry to 0 (doesn't expire). Confirm these options with y.

Next, it will ask you to create a user ID to associate with this key. First you'll be asked your name - I can't help you answer that. Next, you'll be asked for your email address - this is kinda like the "username" for your GPG key. Finally you'll be asked if you'd like to supply a comment - you can skip this by just hitting enter or give your job title if you're very important. Choose O to confirm your information.

Next, you'll be asked to enter a passphrase. This should be 8+ characters long. You'll need to remember it, but it should be secure. Think of something appropriate, enter it, then enter it again to confirm.

GPG will now generate a random key. Wiggle your mouse around and mash the keyboard to generate entropy while it does this. I have no idea how it does this or if this is a joke, but this is security we're talking about here, so get mashing.

Initialize pass:

Now we get to start using pass. First we create the initial password store, passing it our GPG key ID (which is the email address we used above).

$ pass init the-email-address-you-used-for@your-gpg.key
Enter fullscreen mode Exit fullscreen mode

Using pass

pass stores passwords in a hierarchical directory structure. This structure is somewhat arbitrary, but basically follows the structure service-name/username. If you have multiple accounts on the same service, you might nest those accounts under a parent folder, e.g. aws/development/adam@example.com and aws/production/adam@example.com - each of these paths will lead to a different password.

Adding passwords

Add a new service and set the password (you'll be asked to type the password and then type again to confirm):

$ pass insert test-service/adam@example.com
Enter fullscreen mode Exit fullscreen mode

If you don't know the password already (i.e. you're signing up for a new service), you can generate a random password instead of making one up yourself (where 16 is the length you want the password to be):

$ pass generate test-service/adam@example.com 16
Enter fullscreen mode Exit fullscreen mode

Viewing passwords

To view the password you just generated, or indeed any password in the vault, simply pass pass the path to the value you'd like to retrieve (you'll be asked to enter your GPG password from earlier):

pass test-service/adam@example.com
Enter fullscreen mode Exit fullscreen mode

To view that generated password and copy it to the system clipboard):

pass -c test-service/adam@example.com
Enter fullscreen mode Exit fullscreen mode

To list all available accounts (but not their passwords):

$ pass ls
Enter fullscreen mode Exit fullscreen mode

Removing passwords

To remove a password (you'll be asked to confirm deletion):

$ pass rm test-service/adam@example.com
Enter fullscreen mode Exit fullscreen mode

Remove all passwords in a given directory (you'll be asked to confirm deletion):

$ pass rm -r test-service
Enter fullscreen mode Exit fullscreen mode

...and because pass follows the UNIX philosophy, you can find instructions for loads more knobs and whistles with man pass.

Really using pass

So far, so good. You're a l33t hacker and now use a CLI password manager. Your passwords are stored locally and you can only get to them from your terminal. Congratulations, you just made your life just a little more difficult.

Or did you?

Here's the thing. pass doesn't have to store passwords. It can store any string at the end of those paths. And those paths don't have to map one-to-one with a username and password combination.

Use pass to store secure API keys

One of the most interesting uses of a CLI password manager is that it can integrate with your shell. That means if we can use pass in our bash scripts. This gets really useful when we combine that with e.g. loading ENV VARs for our projects.

Say we had the following passwords set:

$ pass ls
Password Store
└── aws
    ├── secret_key
    └── access_key
Enter fullscreen mode Exit fullscreen mode

We could then set these in a .env file, and use dotenv to read those values when booting our application (as described elsewhere):

AWS_SECRET_KEY: $(pass aws/secret_key)
AWS_ACCESS_KEY: $(pass aws/access_key)
Enter fullscreen mode Exit fullscreen mode

When we boot our app, the $() syntax will get expanded out, pass will be called, and our secret_key and access_key will be interpolated in place. Very cool. We can check this file into source control and no one will know what our AWS credentials actually are.

If we have multiple credentials for the same service, we could separate them out however we like - pass doesn't care. We could have aws/staging/access_key and aws/production/access_key (maybe don't store prod access keys locally though), or aws/staging/client_a/access_key and aws/staging/client_b/access_key. Whatever works for you.

Conclusion

We've only just scratched the surface of what one can do when your credentials are managed on the command line. Next up I'd like to figure out how to get credentials shared between machines / teams through git, ensuring only those with approved GPG keys can access the secrets held within. And you'll be surprised at how flexible having your passwords can be in practice, once you get your head around it.

I still use a regular password manager for regular passwords, but for credentials like API keys and tokens, pass is quickly becoming a handy tool.

References

Top comments (2)

Collapse
 
richardyule profile image
Richard Yule

If you use 1Password as your general password manager have you tried their "op" command-line tool? Interested to know if it offers enough to be an alternative to pass.

Collapse
 
rodreegez profile image
Adam Rogers

Hey, Richard, judging from your bio I’d say you probably know the answer to this better than I would!

I’ve not tried op as I’m not a 1Password user myself, but I’m sure you’d be able to achieve the same result?

One thing I did like about pass was that keys can be arbitrarily nested in a directory-like structure, which means you can have several keys/tokens/passwords under a given path, which can allow for storing more complex credentials than just a username and password, e.g. a database connection string made up of username, password, host, port, database and schema, all stored under e.g. aws/rds/production/ - not sure why or of that’d ever be handy, but thought it was an interesting facet of the model.