Bitwarden CLI

Posted by Ryan Himmelwright on Fri, Dec 10, 2021
Tags shell, security, homelab, devops
Linville Falls Trail, NC

I have used Bitwarden for a couple of years now, but I surprisingly haven’t utilized the CLI tool for anything. Recently, I was coding a script that needed to store an API auth token to an environment variable, but I didn’t want the token to be stored in plaintext. So, I setup and used the Bitwarden CLI for the first time to solve my problem!

CLI Install

To install the CLI tool (bw), go to the CLI Documentation page. There is a native executable for each major OS, that you can download and install.

Linux

In Linux, I first installed it using node. After installing npm on my Fedora machine, I was able to install bw using the command:

npm install -g @bitwarden/cli

To instead use the prebuilt Linux executable (which I tried later), first download the executable package and unzip it. Next, give the bw file executable permissions (chmod +x bw). Lastly, move or link the bw file to a location in your $PATH variable (ex: sudo ln -s /home/Ryan/Builds/bw /usr/bin/bw).

Mac

I also tested this out on my Mac. Here, I used the install method that I always try use when on macOS: Homebrew:

brew install bitwarden-cli

Login and Sync

With bw installed, you must first login with your account:

☁  ~  bw login email@provider.com
? Master password: [hidden]

Despite what the docs say, you don’t need to provide your password as part of the bw login command. If it is omitted, bw will simply prompt you for the password, which is what I recommend doing, so that you don’t have your password stored in the shell history 😉.

After logging in, you should be greeted with a similar message:

You are logged in!

To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:
$ export BW_SESSION="WbiVLHrBEb2ktU7xVB4h1y40DhgFwV+vJ/lBw6EFk23wCxhUWsMTasXlXI3OEBS6xwaG638MepXdS7u1+FysNg=="
> $env:BW_SESSION="WbiVLHrBEb2ktU7xVB4h1y40DhgFwV+vJ/lBw6EFk23wCxhUWsMTasXlXI3OEBS6xwaG638MepXdS7u1+FysNg=="

You can also pass the session key to any command with the `--session` option. ex:
$ bw list items --session WbiVLHrBEb2ktU7xVB4h1y40DhgFwV+vJ/lBw6EFk23wCxhUWsMTasXlXI3OEBS6xwaG638MepXdS7u1+FysNg==

The message provides the option of exporting the Bitwarden session token as an environment variable, or appending it to your bw commands using the --session flag. You don’t have to include the session token when using bw, but it will make it much less annoying to work with. If the token is not defined or included, it will prompt for your password with each command.

Also, it’s probably a good idea to run a bw sync after logging in, just to make sure everything is up to date.

Getting a Value

Now that we are logged in, lets work on grabbing some data from our vault. The bw list command is used to list out contents from the password vault. This requires an object to be specified, which can be items, folders, collections, org-collections, org-members, and organizations.

Flags, like --search can be used to help narrow down the wall of results you get. For example, I can use --search to narrow down the results to the specific ‘post-test’ object I want.

☁  ~  bw list items --search post-test
[{"object":"item","id":"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa","organizationId":null,"folderId":null,"type":1,"reprompt":0,"name":"post-test","notes":null,"favorite":false,"login":{"username":"ryan","password":"terrible-password","totp":null,"passwordRevisionDate":null},"collectionIds":[],"revisionDate":"2021-11-30T11:44:25.846Z"}]

Use in Automation

Once we have found an object we want, we can use it’s id to reference it directly, instead of searching.

☁  ~  bw get item aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
[{"object":"item","id":"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa","organizationId":null,"folderId":null,"type":1,"reprompt":0,"name":"post-test","notes":null,"favorite":false,"login":{"username":"ryan","password":"terrible-password","totp":null,"passwordRevisionDate":null},"collectionIds":[],"revisionDate":"2021-11-30T11:44:25.846Z"}]

Knowing the id is helpful when setting up automation. Additionally, the object data is returned as json, so it is easy enough to parse.

As an example, if we were writing a script and wanted to use Bitwarden to supply my post-test password, we could grab it with this one-liner combining jq to grab the value ("terrible-password") from the json output:

☁  ~  bw get item 937b567a-a8a4-4ede-9fc1-adf000c17a4b |jq '.login | .password'
"terrible-password"

Conclusion

I’ve used bw once or twice at this point for automation scripts, and it has worked great! One of the reasons I choose Bitwarden when I last switched password managers was because it also had a CLI client. I’m glad to have finally used it!

Next Post:
Prev Post:

Pantheon Desktop on Fedora 35 Obsidian Basics