Password based authentications are very common. However storing and securing passwords is an hassle. There are already too many offline and online only services, which does this work for you. Others are more feature-rich and offer lot of other features. If you work in an offline (or air-gap, disconnected from internet, etc) environment, you can use a simple open source utility called pass. It can be used to store each password as a separate file with gpg encryption. It is CLI based, but there are GUI extensions available and has a lot of support in the community.
Also with git, you can choose to sync the encrypted passwords with internal source repos as well, so that you can get all benefits of gitops as well.
Install and Setup Pass
Installing it is as simple as asking your package manager to do it. Official instructions are covered here. In our case, since we are running on RHEL 8, we can use yum install
. However for some reason it did not worked on my machine, so I had to download tarball and use make
to do the needful:
[cloud_user@96dd25ebf51c pass]$ curl -o password-store.tar.xz https://git.zx2c4.com/password-store/snapshot/password-store-1.7.3.tar.xz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 63416 0 63416 0 0 31503 0 --:--:-- 0:00:02 --:--:-- 31503 [cloud_user@96dd25ebf51c pass]$ ls password-store.tar.xz [cloud_user@96dd25ebf51c pass]$ tar -xf password-store.tar.xz [cloud_user@96dd25ebf51c pass]$ ls password-store-1.7.3 password-store.tar.xz [cloud_user@96dd25ebf51c pass]$ cd password-store-1.7.3/ [cloud_user@96dd25ebf51c password-store-1.7.3]$ sudo make install 'man/pass.1' -> '/usr/share/man/man1/pass.1' 'src/completion/pass.bash-completion' -> '/usr/share/bash-completion/completions/pass' 'src/completion/pass.zsh-completion' -> '/usr/share/zsh/site-functions/_pass' 'src/completion/pass.fish-completion' -> '/usr/share/fish/vendor_completions.d/pass.fish' install: creating directory '/usr/lib/password-store' install: creating directory '/usr/lib/password-store/extensions' 'src/.pass' -> '/usr/bin/pass' [cloud_user@96dd25ebf51c password-store-1.7.3]$ pass version ============================================ = pass: the standard unix password manager = = = = v1.7.3 = = = = Jason A. Donenfeld = = Jason@zx2c4.com = = = = http://www.passwordstore.org/ = ============================================
Once its successfully installed, you can run pass version
and see output like above.
Once its installed, you need to install gpg key with command gpg2 --gen-key
. One of the last steps of the GPG creation process is to set your password. Be sure to use a strong password. This will be your master password to unlock your pass
datastore.
Once our secret key is created, we can list it with gpg2 --list-secret-keys
:
[cloud_user@96dd25ebf51c password-store-1.7.3]$ gpg2 --list-secret-keys gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: next trustdb check due at 2023-04-05 /home/cloud_user/.gnupg/pubring.kbx ----------------------------------- sec rsa2048 2021-04-05 [SC] [expires: 2023-04-05] 6CCF8F4F446016C52C95B7C6DF9371597185A7AD uid [ultimate] cloud_user <cloud_user@nonexistentmail.com> ssb rsa2048 2021-04-05 [E] [expires: 2023-04-05]
Notice the line starting with sec
for secret key. We can see that our key is of rsa-2048 type and has a validity of 2 yrs from now.
With our KeyId, we can initialize password store now:
[cloud_user@96dd25ebf51c pass]$ pass init 6CCF8F4F446016C52C95B7C6DF9371597185A7AD mkdir: created directory '/home/cloud_user/.password-store/' Password store initialized for 6CCF8F4F446016C52C95B7C6DF9371597185A7AD
Multiple GPG keys can be specified, for using pass in a team setting, and different folders can have different GPG keys, by using -p
.
Generate, Save, Add, Fetch, List, Remove Passwords with Pass
Generate and Save passwords
We can generate new passwords with pass generate
command:
# generate password with length of 16 characters [cloud_user@96dd25ebf51c pass]$ pass generate internet/random-site-1.com 16 mkdir: created directory '/home/cloud_user/.password-store/internet' The generated password for internet/random-site-1.com is: =fz~\t<~]zXgHjbM # generate password without special characters and with length of 16 characters # if password already exists, it would be overwritten [cloud_user@96dd25ebf51c pass]$ pass generate --no-symbols internet/random-site-1.com 16 An entry already exists for internet/random-site-1.com. Overwrite it? [y/N] y The generated password for internet/random-site-1.com is: 0Z2oOS8GPvKAxo6a # generate password without special characters, 16-character length and copy to clipboard # this would need supporting utilities like xclip to be installed [cloud_user@96dd25ebf51c pass]$ pass generate --no-symbols --clip internet/random-site-2.com 16 /usr/bin/pass: line 160: xclip: command not found Error: Could not copy data to the clipboard # generate qrcode as password [cloud_user@96dd25ebf51c pass]$ pass generate --no-symbols --qrcode business/event-management/cust1.com mkdir: created directory '/home/cloud_user/.password-store/business' mkdir: created directory '/home/cloud_user/.password-store/business/event-management' █████████████████████████████ █████████████████████████████ ████ ▄▄▄▄▄ █▀▄█ ▀█ ▄▄▄▄▄ ████ ████ █ █ █▀ █ ▀█ █ █ ████ ████ █▄▄▄█ █▀▀ ▀█ █▄▄▄█ ████ ████▄▄▄▄▄▄▄█▄█ █▄█▄▄▄▄▄▄▄████ ████▄▄ ▄ ▀▄▄▄▄▀▀▄▄▀ █▄▀▄▀████ ████ ███▀▄ █ ▀▄▄ ▄▀▀▀▀ ▀████ ███████▄█▄▄█▀█ ▄█▀█▀▄▀ ▀████ ████ ▄▄▄▄▄ █▄▀▄ ▄▀██▀ ▀▄█████ ████ █ █ █ ▄▄▄█ ▄▀███▀█████ ████ █▄▄▄█ █ █▀▄▄▀▄█▀▄▀██████ ████▄▄▄▄▄▄▄█▄▄██▄▄█▄█▄█▄█████ █████████████████████████████ █████████████████████████████
We can store hierarchy of password files as essentially every password is a separate file. So we can store passwords for multiple applications at once and separate them via hierarchy.
Add existing passwords
We can existing passwords with pass insert
command:
[cloud_user@96dd25ebf51c pass]$ pass insert business/event-management/cust2.com Enter password for business/event-management/cust2.com: Retype password for business/event-management/cust2.com: [cloud_user@96dd25ebf51c pass]$
By default, it wont show the password being typed for security reasons. If we need to see the password, that is being entered, we can use --echo
:
[cloud_user@96dd25ebf51c pass]$ pass insert --echo business/event-management/cust3.com Enter password for business/event-management/cust3.com: it echoes! [cloud_user@96dd25ebf51c pass]$
We can use --multiline
to enter password of multiple lines and --help
to see more options.
List Passwords from store
To list passwords, you need to install tree
utility. Once done, you can list all passwords in store with pass
command:
[cloud_user@96dd25ebf51c pass]$ pass Password Store ├── business │ └── event-management │ ├── cust1.com │ ├── cust2.com │ └── cust3.com └── internet ├── random-site-1.com └── random-site-2.com
Fetch Passwords
To fetch a specific password, supply its full path to pass. It will ask you to verify your credentials in a separate prompt. Once provided, it will decrypt and show passsword:
[cloud_user@96dd25ebf51c pass]$ pass internet/random-site-2.com 2bhIqR8PYZv5Pvzj [cloud_user@96dd25ebf51c pass]$
If you do not want to echo on command line, use --copy
or -c
.
Remove Passwords
To remove a password, supply its full path to pass rm
:
# removes passsword [cloud_user@96dd25ebf51c pass]$ pass rm internet/random-site-2.com Are you sure you would like to delete internet/random-site-2.com? [y/N] y removed '/home/cloud_user/.password-store/internet/random-site-2.com.gpg' # verify its removed [cloud_user@96dd25ebf51c pass]$ pass Password Store ├── business │ └── event-management │ ├── cust1.com │ ├── cust2.com │ └── cust3.com └── internet └── random-site-1.com
Integration with Git
You can sync passwords to an private git repo with Pass as well. If the password store is a git repository, since each manipulation creates a git commit, you can synchronize the password store using pass git push
and pass git pull
, which call git-push
or git-pull
on the store. More details on git operations here.
Extensions for Pass
In order to faciliate the large variety of uses users come up with, pass
supports extensions. Extensions installed to /usr/lib/password-store/extensions
(this is distribution specific path) are always enabled. Extensions installed to ~/.password-store/.extensions/COMMAND.bash
are enabled if the PASSWORD_STORE_ENABLE_EXTENSIONS
environment variable is true
. There are extensions of every kind, GUI extensions, browser extensions, migration specific extensions, etc. You can find more details on official page.