param ( [Parameter(ParameterSetName='One',Mandatory=$true)][switch]$zip, [Parameter(ParameterSetName='One')][switch]$gpg ) # get the date/time for the back filename $dateTime = get-date -format ("yyyyMMdd-HHmmss") $env:Path += ";$PSScriptRoot\lib;$PSScriptRoot\lib\gpg\bin" bw config server https://bitwarden.johnhgaunt.com if ($sessionKey -eq $null) { $username = Read-Host "Please enter your bitwarden email" $password = Read-Host -assecurestring "Please enter your bitwarden password" $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)) $code = Read-Host "Please enter your 2fa code (hit enter if not used)" if ($code -eq "") { $sessionKey = $(bw login $username $password --raw) } else { $sessionKey = $(bw login $username $password --method 0 --code $code --raw) } } Write-Host "Exporting vault to both CSV and JSON files." Write-Verbose "Exporting vault to CSV." bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.csv" --format csv --session $sessionKey # just writing a new line Write-Host " " Write-Verbose "Exporting vault to JSON." bw export $password --output "$PSScriptRoot\Bitwarden User $username Export $dateTime.json" --format json --session $sessionKey # just writing a new line Write-Host " " Write-Host "Looking for Organizations..." $organizations = $(ConvertFrom-Json $(bw list organizations --session $sessionKey)) Write-Host "Found $(($organizations | measure).count) Organiztaions." $organizations | foreach { Write-Host "Exporting organization $($_.name) vault to both CSV and JSON files." Write-Verbose "Exporting organization vault to CSV." bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.csv" --format csv --session $sessionKey # just writing a new line Write-Host " " Write-Verbose "Exporting organization vault to JSON." bw export $password --organizationid $_.id --output "$PSScriptRoot\Bitwarden Organization $($_.name) Export $dateTime.json" --format json --session $sessionKey # just writing a new line Write-Host " " } Write-Host "Looking for items with attachments..." $itemsWithAttachments = $((ConvertFrom-Json $(bw list items --session $sessionKey)) | Where-Object attachments) Write-Host "Found $(($itemsWithAttachments | measure).count) items with attachments." Write-Host "Downloading attachments..." $itemsWithAttachments | foreach { Write-Verbose "Working on item $($_.name) ($($_.id))." $folder="$PSScriptRoot\attachments\$($_.name)" $itemID=$_.id $_.attachments | foreach { Write-Verbose "Downloading attachment ($($_.id)) with name $($_.fileName) to $folder." bw get attachment $_.id --itemid $itemID --output "$folder\$($_.fileName)" --session $sessionKey # just writing a new line Write-Host " " sleep -Milliseconds 500 } } $zipFilename = "Bitwarden Backup $dateTime.zip" if ($zip) { Write-Host "Zipping the backup together..." Compress-Archive -Path $PSScriptRoot\*.csv, $PSScriptRoot*.json, $PSScriptRoot\attachments -DestinationPath "$PSScriptRoot\$zipFilename" if ($gpg) { Write-Host "Encrypting the backup zip with your bitwarden password..." gpg.exe --symmetric --cipher-algo AES256 --digest-algo SHA512 --output "$PSScriptRoot\$zipFilename.gpg" "$PSScriptRoot\$zipFilename" } } Remove-Variable -Name * -ErrorAction SilentlyContinue bw logout