Skip to content

Commit f3f765d

Browse files
authored
Add a Bitwarden package (raycast#214)
* Add Bitwarden package, image, and `Log In` command The `password-managers` package category has been added, because I didn't see another category that felt appropriate. Logging in authenticates with the Bitwarden server and saves a session token to the user's default keychain. This enables the `Log In` script command to also unlock a user's vault. For more information on the Bitwarden CLI's authentication pattern, see: https://bitwarden.com/help/article/cli/#session-management * `Log In` script is `silent`, prettier documentation * Add `Vault Status` script * Add `Lock Vault` script * Explicitly `unset` variables containing session tokens This might improve the overall security of the package. If it doesn't, it certainly doesn't hurt ¯\_(ツ)_/¯ * Add `Unlock` script * Add `Log Out` script * Better variable names and clearer spacing * Add `Search Vault Items` script * Add `Copy First Password` script * Add `README.md`, supporting images * Align script names with image names and documentation * Provide a better error message if dependencies are missing * Rename 'Copy First Password' command to 'Copy First Matching Password' * Allow copying of a first matching password when multiple items are found The `bw get item` command errors if the search query returns multiple items. This change enables the intended behavior of copying the password of the first matching item to the clipboard, by using `jq` to limit the search results to the first item instead of the Bitwarden CLI. Also explicitly `unset`s the `$password` value after is has been copied. * Improve authentication and session token documentation * Actually say what the `Log In` command does * Omit hidden fields in search results by default Vault items may contain hidden fields. The package should assume that these fields contain sensitive data, and should treat them like passwords. * Update screenshot to match new command name * Ignore useless `type` property of fields * Use the long form of command args where possible
1 parent cc1f40d commit f3f765d

16 files changed

+503
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Bitwarden Package
2+
3+
A package of script commands to interact with a [Bitwarden](https://bitwarden.com/) vault, wrapping the [Bitwarden CLI](https://bitwarden.com/help/article/cli/).
4+
5+
## Dependencies
6+
7+
All commands in this package require the [Bitwarden CLI](https://bitwarden.com/help/article/cli/). The _Vault Status_, _Search Vault Items_, and _Copy First Matching Password_ commands also require the [`jq` utility](https://stedolan.github.io/jq/). Install both via homebrew:
8+
9+
```sh
10+
$ brew install bitwarden-cli jq
11+
```
12+
13+
Additional installation options are available in the tools' respective documentation.
14+
15+
## Command Usage
16+
17+
### Log In
18+
19+
<img src="./images/log-in.png">
20+
21+
This command executes in `silent` mode, and both authenticates and unlocks a Bitwarden vault.
22+
23+
This is the only template command in the package. **If you use multifactor authentication to log in to Bitwarden, be sure to set the value of the `MFA_METHOD` variable.** The [values available to use](https://bitwarden.com/help/article/cli/#enums) are:
24+
25+
| MFA Method | Value |
26+
|-------------------|:-----:|
27+
| Authenticator App | 0 |
28+
| Email | 1 |
29+
| Yubikey | 3 |
30+
31+
If you _do not_ use multifactor authentication to access your Bitwarden vault, leave this variable set to `""`, and optionally remove the MFA Code argument (or leave it blank when logging in). Enabling multifactor authentication is encouraged.
32+
33+
### Log Out
34+
35+
<img src="./images/log-out.png">
36+
37+
This command executes in `silent` mode, and deauthenticates the authenticated Bitwarden vault.
38+
39+
### Lock Vault
40+
41+
<img src="./images/lock-vault.png">
42+
43+
This command executes in `silent` mode, and locks the authenticated Bitwarden vault without deauthenticating.
44+
45+
### Unlock Vault
46+
47+
<img src="./images/unlock-vault.png">
48+
49+
This command executes in `silent` mode, and unlocks the authenticated Bitwarden vault.
50+
51+
### Vault Status
52+
53+
<img src="./images/vault-status.png">
54+
55+
This dashboard command will show the current authentication and/or lock state of the Bitwarden vault. It automatically updates every five minutes. The possible states are `unauthenticated`, `locked`, and `unlocked`.
56+
57+
### Search Vault Items
58+
59+
<img src="./images/search-vault-items.png">
60+
61+
This command executes in `fullOutput` mode, searches **items** in the unlocked Bitwarden vault, and prints all search results in the following format:
62+
63+
```json
64+
{
65+
"name": "Service Name",
66+
"username": "username",
67+
// optional password
68+
"password": "password",
69+
"uris": [
70+
"https://www.example.com",
71+
"https://www.another-example.com"
72+
],
73+
"lastUpdated": "2020-11-29T20:39:56.509Z",
74+
"notes": "Notes appear here",
75+
"fields": [
76+
{
77+
"name": "Custom Field Name 1",
78+
"value": "Custom Field Value 1",
79+
"type": 0
80+
},
81+
// Optional hidden field
82+
{
83+
"name": "Custom Field Name 2",
84+
"value": "Custom Field Value 2",
85+
"type": 1
86+
}
87+
]
88+
}
89+
```
90+
> The `"type"` property of `fields` objects are not included in the actual output. They are displayed here to illustrate that the first field is not a hidden field, but the second field is.
91+
92+
Passwords and hidden fields are omitted by default. Pass `y` as the value of the `Include Passwords?` argument to include them. You can modify the above format using the `output_format` variable.
93+
94+
### Copy First Matching Password
95+
96+
<img src="./images/copy-first-matching-password.png">
97+
98+
This command executes in `silent` mode, searches the unlocked Bitwarden vault, and copies the password associated with the first search result to the clipboard.
99+
100+
## About Authentication
101+
102+
Vaults are separately authenticated and locked. All unlocked vaults are authenticated, but not all authenticated vaults are unlocked. The included _Log In_ command will both authenticate **and** unlock the authenticated vault, but you do not need to log out in order to secure your vault. Simply using the _Lock_ command will do so, and you can then use _Unlock_ later before searching again.
103+
104+
> For more information on session management, see the [Bitwarden CLI documentation](https://bitwarden.com/help/article/cli/#session-management).
105+
106+
### Session Tokens
107+
108+
The Bitwarden CLI uses a session token system to maintain the Lock/Unlock state of an authenticated vault, and this package utilizes the macOS keychain to store and maintain these session tokens. Running the _Lock_ and _Log Out_ commands in this package will invalidate any existing session tokens and remove them from the keychain. Conversely, running the _Log In_ and _Unlock_ commands will create a new session token and store it in the keychain accordingly, overwriting any existing session token that may exist.
109+
110+
#### Session Token Manipulation
111+
112+
> Manipulating your session token directly, via either the command line or the Keychain Access UI is discouraged. See below for troubleshooting if you choose to do so anyway.
113+
114+
Tokens are stored in the macOS keychain under the user's account and the `raycast-bitwarden` service. When the vault is both authenticated and unlocked, you can retrieve your session token via the command line with:
115+
116+
```sh
117+
$ security find-generic-password -a ${USER} -s raycast-bitwarden
118+
```
119+
120+
You can manually remove your session token with:
121+
122+
```sh
123+
$ security delete-generic-password -a ${USER} -s raycast-bitwarden
124+
```
125+
126+
> **IMPORTANT:**<br/>
127+
>Removing your session token will only prevent this package from interacting with your vault. The Bitwarden vault itself will remain unlocked, and accessible via the Bitwarden CLI by including the `--session {{ token }}` argument when executing commands.
128+
129+
New session tokens can only be created using the Bitwarden CLI. Creating a new session token will invalidate any tokens created previously. To create a new session token, use [the `bw login` command](https://bitwarden.com/help/article/cli/#logging-in) if not already authenticated, otherwise use [the `bw unlock` command](https://bitwarden.com/help/article/cli/#locking). To restore access to the vault via this package after creating a new session token, run:
130+
131+
```sh
132+
security add-generic-password -U -a ${USER} -s raycast-bitwarden -w {{ token }}
133+
```
134+
135+
### Troubleshooting
136+
137+
If you use the Bitwarden CLI and/or `security` command in your command line, or the Keychain Access UI to manipulate your session token (and therefore your vault's lock status, from the perspective of this package), you may encounter errors using package commands. In the event that the _Vault Status_ command does not align with the CLI status' output, try running the _Log Out_ command, or:
138+
139+
```sh
140+
$ bw logout && security delete-generic-password -a ${USER} -s raycast-bitwarden
141+
```
142+
143+
This will invalidate any existing session tokens and remove them from your keychain. You may then create a new session token, and store it accordingly, using the _Log In_ command.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
3+
# Dependencies:
4+
# 1. The Bitwarden CLI: https://bitwarden.com/help/article/cli/
5+
# 2. The `jq` utility: https://stedolan.github.io/jq/
6+
#
7+
# Install via homebrew: `brew install bitwarden-cli jq`
8+
9+
# Required parameters:
10+
# @raycast.schemaVersion 1
11+
# @raycast.title Copy First Matching Password
12+
# @raycast.mode silent
13+
#
14+
# Optional parameters:
15+
# @raycast.packageName Bitwarden
16+
# @raycast.icon images/bitwarden.png
17+
# @raycast.argument1 { "type": "text", "placeholder": "Query" }
18+
#
19+
# Documentation
20+
# @raycast.author Phil Salant
21+
# @raycast.authorURL https://github.com/PSalant726
22+
# @raycast.description Search all items in a Bitwarden vault, and copy the password of the first search result to the clipboard.
23+
24+
if ! command -v bw &> /dev/null; then
25+
echo "The Bitwarden CLI is not installed."
26+
exit 1
27+
elif ! command -v jq &> /dev/null; then
28+
echo "The jq utility is not installed."
29+
exit 1
30+
fi
31+
32+
token=$(security find-generic-password -a ${USER} -s raycast-bitwarden -w 2> /dev/null)
33+
token_status=$?
34+
35+
session=""
36+
if [ $token_status -eq 0 ]; then
37+
session="--session $token"
38+
fi
39+
40+
bw unlock --check $session > /dev/null 2>&1
41+
unlocked_status=$?
42+
43+
if [ $unlocked_status -ne 0 ]; then
44+
echo "Vault is locked!"
45+
exit 1
46+
fi
47+
48+
item=$(bw list items --search $1 $session 2> /dev/null | jq ".[0] | { name: .name, password: .login.password }")
49+
name=$(echo $item | jq ".name")
50+
password=$(echo $item | jq --raw-output ".password")
51+
52+
if [[ -z $name || -z $password ]]; then
53+
echo "The query '$1' did not return a password."
54+
exit 1
55+
fi
56+
57+
echo $password | pbcopy
58+
unset $password
59+
echo "Copied the password for '$name' to the clipboard."
60+
exit 0
12.9 KB
Loading
460 KB
Loading
436 KB
Loading
449 KB
Loading
435 KB
Loading
459 KB
Loading
448 KB
Loading
439 KB
Loading

0 commit comments

Comments
 (0)