
SHHHH! It’s a secret! If you are using Bitwarden to store your secrets you are awesome since I am doing the same as it is my favorite vault for personal use. My main use case is for the browser plugin but with the CLI I’ve been using it in my powershell and python scripts. In this article I will cover a function I created to retrieve secrets from Bitwarden and pass them in Powershell.
In upcoming articles I will show how to use it in Python, Azure DevOps or Jenkins depending on demand for increased security and automation.
If you ONLY want to use Bitwarden as your vault the function outlined in this article will help you. Retrieving is a little redundant since you can easily copy your Bitwarden secrets to the Powershell vault and call it a day but this is the baseline for establishing connectivity with Bitwarden so that you can use other features like saving outputs from Powershell directly into Bitwarden and other features from the CLI that you’d want to automate.
When working with secrets it is HIGHLY recommended to create a separate vault and a separate account with restricted access to read only the secrets that will be used in scripts. It is a common practice for security teams to create group based access to DevOps personnel so we can only see and use the necessary secrets in the scripts.
If you have a single script you want to run with secrets there are a few steps to do before running the script:
I. Add Bitwarden Creds to the Powershell Secret Vault
The Bitwarden API login is the preferred method for automating tasks. This login looks for environment variables to be set which is a common practice on Dev environments specially in Linux. We can set the environment variables in clear text but to increase security a bit I will be using the Powershell Secret Management to store the credentials for the environment variables and then clearing them so that they are not stored in memory but only stored in the Powershell vault. The Powershell vault can be locked with another password or scoped to only the profile or all users for further protection.
I created the secrets for the API login and added the dev account’s master password to unlock the Bitwarden vault.
Set-Secret -Name BWPass -Secret ##xx$$!!AAbbCCDd
Set-Secret -Name BWAPIClient -Secret ##xx$$!!AAbbCCDd
Set-Secret -Name BWAPIClientSecret -Secret ##xx$$!!AAbbCCDd
II. Environment Variables for API Login
Now I can set the environment variables by getting the secrets from the Powershell vault.
$env:BW_CLIENTID = Get-Secret -Vault vName -Name BWAPIClient -AsPlainText
$env:BW_CLIENTSECRET = Get-Secret -Vault vName -Name BWAPIClientSec -AsPlainText
$env:BW_PASSWORD = Get-Secret -Vault vName -Name BWPass -AsPlainText
You are storing this information in memory for the session. I do not recommend leaving the creds on the environment variables. The environment variables are protected by your user profile but in the event of a breach they can be retrieved easily. Also this is the reason why you create a separate vault and use an account with restricted access. At the end of the script I will be clearing these values.
III. Powershell / CLI Trickery
Login
The first step is to login using the API key which looks for the environment variables we set in the previous step
[void](Invoke-Command -ScriptBlock {bw login --apikey})
I am using void to suppress the output of that command, when the command runs it will look for the env variables. If you take out void you will see the prompt that you are logged in.
Unlock Bitwarden’s vault
The next step is to unlock the vault and here’s where you need the password, you could also use a text file with the password but again, not a good practice to have text files with passwords so might as well use environment variables since they only last for the session. I am storing the output of the command so that I can extract the session key.
$unlockSesh = Invoke-Command -ScriptBlock {bw unlock --passwordenv BW_PASSWORD}
If you run this command and look at the variable you will see the following:

String manipulation
Now I have to manipulate the variable so that I can isolate the line with the session key and extract it which I accomplished in 2 steps:
$pwline = $unlockSesh | Select -Last 4 | Select -First 1
This line grabs the first line out of the last 4 lines.

I still have the prompt character (>) and info I don’t want so to isolate the session key I can split the string by using the double quotes as my delimiter. Then I can select the second value which is 1 since the count starts at zero. Zero would be anything before the double quotes.
$seshkey = $pwline.Split('"')[1]
The result of this string is the session key!

III. Getting Bitwarden secrets with the session key.
Now that I have the session key isolated in the variable called $seshkey I can use it to pull secrets, store them in variables and use them in my scripts.
$powershellsecret = Invoke-Command -ScriptBlock {bw get password TestingAzDo --session $seshkey}
Again, we are wrapping the Bitwarden CLI into powershell by saving the output as a variable that we can then take and use for our scripts.

Link to function
Feel free to use the function and can be downloaded or pulled from here: https://github.com/mdf-ido/sharetocare/blob/main/powershell/BitwardenFN.ps1
Wrap Up (Part I)
With this in your scripts you will be able to run scripts and retrieve passwords from Bitwarden. I highly recommend that you rotate your API Keys constantly, create a separate vault with ONLY the secrets you want to use in scripts and create a separate user account with access to the separate vault so you can use it in your scripts.
In upcoming articles I will share a function I wrote to make it easier to use and also will share how to use it in Azure DevOps for increased security.