This module is an extension vault for the Microsoft.PowerShell.SecretManagement module. It wraps around the official Bitwarden CLI to interface with Bitwarden and Vaultwarden instances. This module works over all supported PowerShell platforms on Windows, Linux, and macOS.
Supported Commands:
Get-Secret
, Get-SecretInfo
, Remove-Secret
, Set-Secret
, Test-SecretVault
, Unlock-SecretVault
Unsupported Commands:
Set-SecretInfo
NOTE: This is not an official Bitwarden project.
Download and Install
PowerShell 7+ From: | ||
---|---|---|
Multiplatform Install Instructions |
The Latest version of the Bitwarden CLI From: | ||||||
---|---|---|---|---|---|---|
Scoop
|
winget | Direct Download Windows | macOS | Linux |
After installing the bitwarden-cli, use native config commands to configure it as needed. In particular, if you run a self-hosted instance of Bitwarden/Vaultwarden you need to specify the URL to that via:
bw config server "https://your.bw.domain.com"
Lastly, the SecretManagement
module can only handle unlock operations, not login operations. As such you will need to login before you can utilize this extension.
This Module is designed for unattended usage and expects you to implement login via API Key environmental variables. If setup this way, the SecretManagement.Warden
extension will use these credentials to silently resolve any "You are not logged in" errors. NOTE: While this means you will effectively always be logged in, you will still need to unlock the vault with your password every session to gain access to secrets.
This is also useful for troubleshooting, as it allows you to assume the user is logged in and that if Test-SecretVault
returns false
it's because the vault is either locked or inaccessible.
To configure automatic API Key usage follow the steps below:
- Retrieve your personal API Key. (See Get your personal API key for more details than the brief below).
- Open the web vault on your Bitwarden/Vaultwarden instance and login.
- Select the profile icon and click Account Settings from the dropdown.
- Under the Account Settings menu, select the Security page and Keys tab.
- Click the View API Key button at the bottom.
- Permanently set the required environmental variables through the GUI via Advanced System Properties or run the following PowerShell commands.
[Environment]::SetEnvironmentVariable("BW_CLIENTID",'MyClientID',"User") [Environment]::SetEnvironmentVariable("BW_CLIENTSECRET",'SuperSecret',"User")
Check that everything is setup correctly by running the command: bw login --check
If the cli tells you that you are logged in everything is working. If not, try the following troubleshooting steps.
- Open a PowerShell session.
- Run
bw login --apikey
. If an error about the server is returned, you likely made a typo when specifying the server URL. Fix this by re-runningbw config server "https://your.bw.domain.com"
- Run
gci env:BW_CLIENT*
. This should return at least two entries: BW_CLIENTID and BW_CLIENTSECRET. If either are missing, go through the steps detailed in Utilize API Key for Login again.
If running interactively you can run bw login
to bring up a login prompt. Unlike API Keys, this will only last a single session.
While the prompt is the only secure way to use bw login
directly, you can automate it to run insecurely via bw login [email] [password] --method <method> --code <code>
as described here.
REMEMBER:
- All commands you run will be saved to session history. While this is cleared every time you close the terminal, it is still preferable to avoid adding secrets to it in the first place.
- All commands that do not contain the words:
password
,asplaintext
,token
,apikey
, orsecret
will be saved into the PSReadLine History file.
- This one can be really bad as the file is stored unencrypted long-term and
bw login
does not contain any exclusion words.- Not an issue when using the
SecretManagement
module or extensions as all public commands include the word "secret" in them and all private commands are run in a isolated session that does not store history.
This module has been published to the PowerShell Gallery. To install it and its PowerShell dependencies from there run:
Install-PSResource -Name SecretManagement.Warden
# OR
Install-Module -Name SecretManagement.Warden
Alternatively, manually install its Microsoft.PowerShell.SecretManagement dependency then download the latest release (Do not clone the repo; code is only signed during the release process). Open the downloaded file, open the only directory therein, and extract the contents of that subdirectory to the directory:
$HOME\Documents\PowerShell\Modules\SecretManagement.Warden
(Windows)$HOME/.local/share/powershell/Modules/SecretManagement.Warden
(Linux or Mac)
Then Register the vault with SecretManagement as usual, e.g. Register-SecretVault -Name "warden" -ModuleName "SecretManagement.Warden"
If you wish to use any non-default configurations, put them in a hashtable and pass that to Register-SecretVault
with the -VaultParameters
parameter. Optionally, you can set it as the default vault by also providing the -DefaultVault
parameter, though this is assumed if you've never registered another vault.
When registering the vault you can include a HashTable of vault parameters to configure client behavior. These are passed to implementing functions as $AdditionalParameters
.
Example:
$VaultParameters = @{
ExportObjectsToSecureNotesAs = "CliXml"
MaximumObjectDepth = 4
ResyncCacheIfOlderThan = New-TimeSpan -Hours 2
}
Register-SecretVault -Name "warden" -ModuleName SecretManagement.Warden -VaultParameters $VaultParameters
Name | Description | Type | Possible Values | Default |
---|---|---|---|---|
ExportObjectsToSecureNotesAs | Changes what PowerShell HashTables are converted into so they can be stored as a Secure Note in the vault. Defaults to JSON for interoperability with other languages. However, CliXml has superior type support and can be used to store an exact copy of the hashtable, including custom typing, in the vault. See Export-Clixml for details. |
String | CliXml, JSON | JSON |
MaximumObjectDepth | Specifies how many levels of contained objects are included in the CliXml/JSON representation. | Int32 | 1–100 | 2 |
OrganizationID | If specified, the vault will only work with the subset of secrets owned by the vault Organization with this ID.† You can retrieve these values via bw list organizations . |
Guid | Any Guid | none |
ResyncCacheIfOlderThan | A TimeSpan object indicating the amount of time that is allowed to pass before the local cache is considered expired. After expiry, the vault will be synced before running any further commands. | TimeSpan | Any TimeSpan | New-TimeSpan -Hours 3 |
† While you cannot specify the OrganizationID on a per query basis, you can register multiple vaults with different OrganizationIDs and specify those when running the query, which has much the same effect.
The Bitwarden CLI always writes data directly to the vault, however it always retrieves data from a cache. That cache is automatically refreshed every time you login, but must be manually refreshed otherwise. Within this module you can force a sync by running Test-SecretVault
. Otherwise sync is governed by the ResyncCacheIfOlderThan
setting.
As a last resort you can call the Bitwarden CLI directly to force the sync with bw sync
.
When you first register a vault using this extension, commands like Test-SecretVault
or Get-Secret
may report that it is unable to run on the registered vault. This error message is incorrect, in actuality the vault is just locked. To resolve the issue, run Unlock-SecretVault
. Future output from Test-SecretVault
should correctly notify you that the vault is locked.
Unlock-SecretVault
will stall if you specified an invalid URL when configuring the location of the server.
Special Thanks to @TylerLeonhardt for publishing a baseline for this module extension. Please check out his LastPass Extention
Special thanks to @realslacker for his excellent bitwarden cli wrapper. A stripped down and heavily modified version of it was utilized to replace Invoke-bwcmd
.