Skip to content

Commit

Permalink
Merge branch 'update-testing-2' into 'main'
Browse files Browse the repository at this point in the history
Localize Warnings and Expand Testing

See merge request wmarshall/SecretManagement.Warden!18
  • Loading branch information
marshallwp committed Sep 25, 2024
2 parents 30e3ff9 + be96dbb commit 098be1f
Show file tree
Hide file tree
Showing 33 changed files with 881 additions and 78 deletions.
50 changes: 38 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# SecretManagement extension for BitWarden
[![PSScriptAnalyzer](https://github.com/marshallwp/SecretManagement.Warden/actions/workflows/powershell.yml/badge.svg)](https://github.com/marshallwp/SecretManagement.Warden/actions/workflows/powershell.yml)
[![Run Pester Tests](https://github.com/marshallwp/SecretManagement.Warden/actions/workflows/pester-tests.yml/badge.svg?branch=main)](https://github.com/marshallwp/SecretManagement.Warden/actions/workflows/pester-tests.yml)
[![PSGallery Downloads](https://img.shields.io/powershellgallery/dt/SecretManagement.Warden?label=PSGallery%20Downloads
)](https://www.powershellgallery.com/packages/SecretManagement.Warden)

[![PSGallery Downloads](https://img.shields.io/powershellgallery/dt/SecretManagement.Warden?label=PSGallery%20Downloads&labelColor=%23333a41&color=%2334cf58)](https://www.powershellgallery.com/packages/SecretManagement.Warden)

This module is an extension vault for the [Microsoft.PowerShell.SecretManagement](https://www.powershellgallery.com/packages/Microsoft.PowerShell.SecretManagement) module. It wraps around the official [Bitwarden CLI](https://github.com/bitwarden/clients/tree/master/apps/cli) to interface with Bitwarden and Vaultwarden instances. This module works over all supported PowerShell platforms on Windows, Linux, and macOS.

Expand All @@ -21,12 +20,20 @@ Download and Install
<table style="text-align: center;">
<tbody>
<tr>
<th colspan="2">PowerShell 7+ From:</th>
<th colspan="3">PowerShell 7+ From:</th>
</tr>
<tr>
<td>
<a href='https://www.microsoft.com/store/apps/9MZ1SNWT0N5D'>
<img src='https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png' alt='Get PowerShell from the Microsoft Store' width="142px" height="52px"/>
<img src='https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png'
alt='Get PowerShell from the Microsoft Store' width="142px" height="52px"/>
</a>
</td>
<td>
<a href='https://snapcraft.io/powershell'>
<img src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
height="52px"
alt='Get it from the Snap Store' />
</a>
</td>
<td>
Expand All @@ -39,33 +46,52 @@ Download and Install
<table>
<tbody>
<tr>
<th scope="row" colspan="6">The Latest version of the Bitwarden CLI From:</th>
<th scope="row" colspan="7">The Latest version of the Bitwarden CLI From:</th>
</tr>
<tr>
<td>
<a href="https://www.npmjs.com/package/@bitwarden/cli">
<img src="https://raw.githubusercontent.com/npm/logos/master/npm%20logo/npm-logo-red.svg" alt='Get Bitwarden CLI from NPM' height="30px"/>
<img src="https://raw.githubusercontent.com/npm/logos/master/npm%20logo/npm-logo-red.svg"
height="30px"
alt='Get it from npm'/>
</a>
</td>
<td>
<a href="https://scoop.sh/#/apps?q=&quot;bitwarden-cli&quot;">
<div style="font-size: 20px; color: black; background: #d7d4db">
<img src="https://avatars.githubusercontent.com/u/16618068?s=52" style='vertical-align: middle'/> Scoop
<img src="https://avatars.githubusercontent.com/u/16618068?s=52"
style='vertical-align: middle'
alt='Get it from Scoop'/> Scoop
</div>
</a>
</td>
<td>
<a href="https://community.chocolatey.org/packages/bitwarden-cli">
<img src="https://chocolatey.org/assets/images/global-shared/logo-square.svg" height="52px"/>
<img src="https://chocolatey.org/assets/images/global-shared/logo-square.svg"
height="52px"
alt='Get it from Chocolatey'/>
</a>
</td>
<td>
<a href="https://snapcraft.io/bw">
<img src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg" alt='Get Bitwarden CLI from the Snap Store' height="52px"/>
<img src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
height="52px"
alt='Get it from the Snap Store'/>
</a>
</td>
<td><a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/">winget</a><br>
<code>winget install -e Bitwarden.CLI --source winget</code>
<td>
<a href="https://winstall.app/apps/Bitwarden.CLI">
<img src="https://raw.githubusercontent.com/microsoft/winget-cli/refs/heads/master/.github/images/WindowsPackageManager_Assets/ICO/PNG/_48.png"
height="48px"
alt='Get it from winget'/> winget
</a>
</td>
<td>
<a href="https://formulae.brew.sh/formula/bitwarden-cli">
<img src="https://brew.sh/assets/img/homebrew.svg"
height="52px"
alt='Get it from Homebrew' />
</a>
</td>
<td>Direct Download<br>
<a href="https://vault.bitwarden.com/download/?app=cli&platform=windows">Windows</a> |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@{
ModuleVersion = '1.1.4'
ModuleVersion = '1.1.5'
RootModule = 'SecretManagement.Warden.Extension.psm1'
FunctionsToExport = @(
'Get-Secret',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,19 @@ Foreach($import in @($Classes + $Public + $Private))
# Export Public functions ($Public.BaseName) for WIP modules
# Set variables visible to the module and its functions only

# *Verify Existence of and Get CommandInfo for the Bitwarden CLI.
# ?If the path is specified by $env:BITWARDEN_CLI_PATH then use that. Else search for it in the current session. If neither exists throw an error.
if (!($env:BITWARDEN_CLI_PATH -and ($BitwardenCLI = Get-Command $env:BITWARDEN_CLI_PATH -CommandType Application -ErrorAction SilentlyContinue)) `
-and (!($BitwardenCLI = Get-Command -Name bw -CommandType Application -ErrorAction Ignore)))
{
if( $IsWindows ) { $platform = "windows" }
elseif ( $IsMacOS ) { $platform = "macos" }
else { $platform = "linux" }

Write-Error "No Bitwarden CLI found in your path, either specify `$env:BITWARDEN_CLI_PATH or put bw.exe in your path. If the CLI is not installed, you can install it using scoop, chocolatey, npm, snap, or winget. You can also download it directly from: https://vault.bitwarden.com/download/?app=cli&platform=$platform" -ErrorAction Stop
}

# *Perform version check ONCE during module import.
Test-CLIVersion -BitwardenCLI $BitwardenCLI -MinSupportedVersion '2022.8.0'

Export-ModuleMember -Function $Public.Basename
45 changes: 0 additions & 45 deletions SecretManagement.Warden.Extension/private/Invoke-BitwardenCLI.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,6 @@
# . '..\classes\BitwardenPasswordHistory.ps1'
# . '.\ConvertTo-BWEncoding.ps1'

#region Version Check
# *Version check is performed ONCE during module import.
[version]$MinSupportedVersion = '2022.8.0'
[version]$CurrentVersion
# check if we should use a specific bw.exe
if ( $env:BITWARDEN_CLI_PATH -and ($BitwardenCLI = Get-Command $env:BITWARDEN_CLI_PATH -CommandType Application -ErrorAction SilentlyContinue) ) {
$CurrentVersion = $BitwardenCLI.Version
# ?Query the CLI for version number if the file version would fail the test. Workaround for how the file version is not always the cli version.
if($CurrentVersion -lt $MinSupportedVersion) {
$CurrentVersion = .$env:BITWARDEN_CLI_PATH --version
}
}
elseif ( $BitwardenCLI = Get-Command -Name bw.exe -CommandType Application -ErrorAction Ignore ) {
# ?Scoop shims eliminate version numbers, so we ask scoop for the true version.
if( $BitwardenCLI.Version -eq '0.0.0.0' -and (Get-Command scoop -ErrorAction Ignore) ) {
$CurrentVersion = (scoop list bitwarden-cli 6> $null).Version ?? $BitwardenCLI.Version
}
# ?WinGet shims have the wrong version, and the winget cli has output that is difficult to parse reliably. Therefore, ask bw.exe what version it is.
elseif( $BitwardenCLI.Source -like "*\WinGet\Links\bw.exe" -or <# Machine Scope #>
$BitwardenCLI.Source -like "*\Winget\Packages\*\bw.exe" <# User Scope #> ) {
$CurrentVersion = .$BitwardenCLI.Source --version
}
else {
$CurrentVersion = $BitwardenCLI.Version
}
}
else {
if( $IsWindows ) { $platform = "windows" }
elseif ( $IsMacOS ) { $platform = "macos" }
else { $platform = "linux" }

Write-Error "No Bitwarden CLI found in your path, either specify `$env:BITWARDEN_CLI_PATH or put bw.exe in your path. If the CLI is not installed, you can install it using scoop, chocolatey, npm, snap, or winget. You can also download it directly from: https://vault.bitwarden.com/download/?app=cli&platform=$platform" -ErrorAction Stop
}

if ( $BitwardenCLI -and $CurrentVersion -lt $MinSupportedVersion ) {
Write-Warning "Your Bitwarden CLI is version $CurrentVersion and is out of date. Please upgrade to at least version $MinSupportedVersion."
}
elseif ( $BitwardenCLI -and $CurrentVersion -eq '2023.12.1') {
Write-Warning "Your Bitwarden CLI is version $CurrentVersion. This version of the CLI has a known issue affecting bw list, which is used to check if the vault is unlocked due to bug: https://github.com/bitwarden/clients/issues/2729. It is `e[3mstrongly`e[23m recommended you move to another version. Otherwise you will need to constantly logout and login again."
}
elseif ( $BitwardenCLI -and $CurrentVersion -in ('2024.6.1','2024.7.0','2024.7.1')) {
Write-Warning "Your Bitwarden CLI is version $CurrentVersion. Versions 2024.6.1 — 2024.7.1 of the CLI have a known issue with the unlock command due to bug: https://github.com/bitwarden/clients/issues/9919. It is `e[3mstrongly`e[23m recommended that you move to another version."
}
#endregion Version Check

$__Commands = @{
login = '--apikey --check --raw --method --code --sso --help'
logout = '--help'
Expand Down
110 changes: 110 additions & 0 deletions SecretManagement.Warden.Extension/private/Test-CLIVersion.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<#
.SYNOPSIS
Checks Bitwarden CLI version against blacklist.
.DESCRIPTION
Long description
.EXAMPLE
An example
.NOTES
General notes
#>
function Test-CLIVersion {
[CmdletBinding()]
Param(
# CommandInfo of the Bitwarden CLI. Returned from Get-Command or dehydrated from Import-CliXml.
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({
if($_.PSTypeNames -match '^(?:Deserialized\.)?System\.Management\.Automation\.CommandInfo$')
{ return $true }
else { throw "Cannot convert the `"$_`" value of type `"$iptType`" to type `"System.Management.Automation.ApplicationInfo`"." }
})]
[PSObject]$BitwardenCLI,
# Minimum Supported Version of the Bitwarden CLI.
[ValidateNotNullOrEmpty()]
[Version]$MinSupportedVersion = '2022.8.0'
)

#region Get CLI Version
# Get the Version number from file metadata if possible.
[Version]$CurrentVersion = $BitwardenCLI.Version

# ?Find the version elsewhere if the file version would fail the test. Workaround for how the file version is not always the cli version.
if( $CurrentVersion -lt $MinSupportedVersion ) {
# Handle the various shims
# ?The Brew CLI is rather fast so we use it to get version number
$HomebrewPrefix = $env:HOMEBREW_PREFIX ?? "/home/linuxbrew/.linuxbrew"
if ( $BitwardenCLI.Source -eq "$HomebrewPrefix/bin/bw" -and (Get-Command brew -ErrorAction Ignore))
{
$CurrentVersion = ((brew list bitwarden-cli --versions) -split ' ')[1]
}
# ?The Chocolatey CLI is very slow, so we prefer querying bw directly if needed.
# if ( $BitwardenCLI.Source -eq (Join-Path $env:ProgramData "chocolatey" "bin" "bw.exe") `
# -and (Get-Command choco -ErrorAction Ignore))
# {
# $CurrentVersion = (choco info bitwarden-cli --local-only --limit-output).Split("|")[1]
# }
# ?npm creates a ps1 shim that is stripped of all version info. The CLI is fast though.
elseif ( $BitwardenCLI.Name -eq "bw.ps1" -and (Get-Command npm -ErrorAction Ignore)) {
$CurrentVersion = (npm view -g @bitwarden/cli version)
}
# ?Scoop shims eliminate version numbers, so we ask scoop for the true version.
elseif( $BitwardenCLI.Source -like "*\scoop\shims\bw.exe" -and (Get-Command scoop -ErrorAction Ignore)) {
$CurrentVersion = (scoop list bitwarden-cli 6> $null).Version ?? $CurrentVersion
}
# ?Getting the version from snap is very fast, so ask it for that.
elseif( $BitwardenCLI.Source -like "*/snapd/snap/bin/bw" -and (Get-Command snap -ErrorAction Ignore) ) {
# Query snap for a list containing only the bw command.
$snapVerChk = snap list bw
# Get the position of the Version Header and treat that as the startPos
$startPos = ($snapVerChk | Select-String Version).Matches[0].Index
# Get the position of the first space after startPos on line 2
$endPos = $snapVerChk[1].Substring($startPos).IndexOf(' ')
# The version is the text between the startPos and endPos on line 2.
$CurrentVersion = $snapVerChk[1].Substring($startPos, $endPos) ?? $CurrentVersion
}
# ?WinGet shims have the wrong version, and the winget CLI is slow. Disabled in favor of querying bw.exe instead.
# elseif( $BitwardenCLI.Source -like "*\WinGet\Links\bw.exe" -or <# Machine Scope #>
# $BitwardenCLI.Source -like "*\Winget\Packages\*\bw.exe" <# User Scope #>) {
# $wingetVerChk = winget list --id Bitwarden.CLI
# $startPos = ($wingetVerChk | Select-String Version).Matches[0].Index
# $endPos = ($wingetVerChk | Where-Object {![String]::IsNullOrWhiteSpace($_) -and $_.Length -gt $startPos})[2].Substring($startPos).IndexOf(' ')
# $CurrentVersion = $snapVerChk[1].Substring($startPos, $endPos) ?? $CurrentVersion
# }
# ?If all other methods fail, ask bw.exe what version it is. This is a surprisingly slow process.
else {
$CurrentVersion = (.$BitwardenCLI --version) ?? $CurrentVersion
}
}
#endregion Get CLI Version


#region Version Warnings
# Default Warning Message templates. Will be used if a localized variant cannot be found in the localization subdirectory.
#culture="en-US"
$Warnings = DATA {@{
WarnOutdated = "Your bitwarden-cli is version {0} and is out of date. Please upgrade to at least version {1}."
WarnSpecificVersion = "Your bitwarden-cli is version {0}. This version of the CLI has a known issue affecting [{1}], which is used by [{2}]."
WarnVersionRange = "Your bitwarden-cli is version {0}. Versions {1} – {2} of the CLI have a known issue affecting [{3}], which is used by [{4}]."
See = "See: {0}."
StrongAction = "It is `e[3mstrongly`e[23m recommended that you move to another version."
}}
Import-LocalizedData -BindingVariable Warnings -BaseDirectory (Join-Path $PSScriptRoot "localization") -ErrorAction Ignore

if ( $CurrentVersion -lt $MinSupportedVersion ) {
Write-Warning ($Warnings.WarnOutdated -f $CurrentVersion, $MinSupportedVersion)
}
elseif ( $CurrentVersion -ge '2023.12.0' -and $CurrentVersion -le '2023.12.1' ) {
$warn = "{0} {1} {2}" -f ($Warnings.WarnVersionRange -f $CurrentVersion, '2023.12.0', '2023.12.1', 'bw list', 'Test-SecretVault'),
($Warnings.See -f 'https://github.com/bitwarden/clients/issues/7126'),
$Warnings.StrongAction
Write-Warning $warn
}
elseif ( $CurrentVersion -ge '2024.6.1' -and $CurrentVersion -le '2024.7.1' ) {
$warn = "{0} {1} {2}" -f ($Warnings.WarnVersionRange -f $CurrentVersion, '2024.6.1', '2024.7.1', 'bw unlock', 'Unlock-SecretVault'),
($Warnings.See -f 'https://github.com/bitwarden/clients/issues/9919'),
$Warnings.StrongAction
Write-Warning $warn
}
#endregion Version Warnings
}
19 changes: 19 additions & 0 deletions SecretManagement.Warden.Extension/private/localization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# README

Directory serving as the BaseDirectory for using [`Import-LocalizedData`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-localizeddata) in private functions. As such, directory layout and filenames are goverened by the requirements of that function

In short: all directory names should either be a language code or a language-country code, i.e., `de` (German) or `ar-SA` (Saudi Arabian Arabic). Within each directory, localizations for a particular file are stored in `.psd1` of the same name.

## Example Directory Layout

```
└── Test-Function.ps1
└── localization
├── de
│ └── Test-Function.psd1
└── ar-SA
└── Test-Function.psd1
```

## See Also
For more details, refer to PowerShell documentation, specifically [about_Script_Internationalization](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_script_internationalization) and [Import-LocalizedData](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-localizeddata).
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Czech
@{
WarnOutdated = "Váš bitwarden-cli má verzi {0} a je zastaralý. Upgradujte prosím alespoň na verzi {1}."
WarnSpecificVersion = "Váš bitwarden-cli je verze {0}. Tato verze CLI má známý problém, který ovlivňuje [{1}], které používá [{2}]."
WarnVersionRange = "Váš bitwarden-cli je verze {0}. Verze {1} - {2} CLI má známý problém, který ovlivňuje [{3}], které používá [{4}]."
See = "Viz: {0}."
StrongAction = "`e[3mDůrazně`e[23m doporučujeme přejít na jinou verzi."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# German
@{
WarnOutdated = "Ihr bitwarden-cli hat die Version {0} und ist veraltet. Bitte aktualisieren Sie mindestens auf Version {1}."
WarnSpecificVersion = "Ihr bitwarden-cli hat die Version {0}. Diese Version der CLI hat ein bekanntes Problem, das [{1}] betrifft, das von [{2}] verwendet wird."
WarnVersionRange = "Ihr bitwarden-cli hat die Version {0}. Die Versionen {0} - {1} der CLI haben ein bekanntes Problem, das [{2}] betrifft, das von [{3}] verwendet wird."
See = "Siehe: {0}."
StrongAction = "Es wird `e[3mdringend`e[23m empfohlen, zu einer anderen Version zu wechseln."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Greek
@{
WarnOutdated = "Το bitwarden-cli σας έχει την έκδοση {0} και είναι ξεπερασμένο. Παρακαλούμε αναβαθμίστε τουλάχιστον στην έκδοση {1}."
WarnSpecificVersion = "Το bitwarden-cli σας έχει την έκδοση {0}. Αυτή η έκδοση του CLI έχει ένα γνωστό πρόβλημα που επηρεάζει το [{1}], το οποίο χρησιμοποιείται από το [{2}]."
WarnVersionRange = "Το bitwarden-cli σας έχει την έκδοση {0}. Οι εκδόσεις {0} - {1} του CLI έχουν ένα γνωστό πρόβλημα που επηρεάζει το [{2}], το οποίο χρησιμοποιείται από το [{3}]."
See = "Βλέπε: {0}."
StrongAction = "Συνιστάται `e[3mέντονα`e[23m η μετάβαση σε άλλη έκδοση."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Spanish
@{
WarnOutdated = "Su bitwarden-cli es la versión {0} y está desactualizada. Por favor, actualice al menos a la versión {1}."
WarnSpecificVersion = "Su bitwarden-cli es la versión {0}. Esta versión de la CLI tiene un problema conocido que afecta a [{1}], que es utilizado por [{2}]."
WarnVersionRange = "Su bitwarden-cli es la versión {0}. Las versiones {0} - {1} del CLI tienen un problema conocido que afecta a [{2}], que es utilizado por [{3}]."
See = "Mira: {0}."
StrongAction = "Se recomienda `e[3mencarecidamente`e[23m pasar a otra versión."
}
Loading

0 comments on commit 098be1f

Please sign in to comment.