Password management on the command line
Tags: linux, security, tutorial
Published: 2021-02-27 21:52:24

[`pass`](https://www.passwordstore.org/) 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.

```bash
$ sudo apt install pass gpg xclip
```

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

```bash
$ gpg --full-generate-key
```

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](https://xkcd.com/936/). 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).

```bash
$ pass init the-email-address-you-used-for@your-gpg.key
```

## 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):

```bash
$ pass insert test-service/adam@example.com
```

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):

```bash
$ pass generate test-service/adam@example.com 16
```

### 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):

```bash
pass test-service/adam@example.com
```

To view that generated password _and copy it to the system clipboard_):

```bash
pass -c test-service/adam@example.com
```

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

```bash
$ pass ls
```

### Removing passwords

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

```bash
$ pass rm test-service/adam@example.com
```

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

```bash
$ pass rm -r test-service
```

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

```bash
$ pass ls
Password Store
└── aws
    ├── secret_key
    └── access_key
```

We could then set these in a `.env` file, and use `dotenv` to read those values when booting our application (as described [elsewhere](https://dev.to/rodreegez/bridgetown-and-environment-variables-1123)):

```bash
AWS_SECRET_KEY: $(pass aws/secret_key)
AWS_ACCESS_KEY: $(pass aws/access_key)
```

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
- [Pass on ArchWiki](https://wiki.archlinux.org/index.php/Pass)
- [GnuPG on ArchWiki](https://wiki.archlinux.org/index.php/GnuPG)
- [pass website](https://www.passwordstore.org/)
- [Managing secrets in Terraform](https://blog.gruntwork.io/a-comprehensive-guide-to-managing-secrets-in-your-terraform-code-1d586955ace1)