Skip to content

🌟 [Major]: Convert all secret names to and from base64 #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/functions/private/Base64/ConvertFrom-Base64.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function ConvertFrom-Base64 {
<#
.SYNOPSIS
Converts a Base64 encoded string to a string.

.DESCRIPTION
Converts a Base64 encoded string to a string.

.EXAMPLE
ConvertFrom-Base64 -Base64String 'VGhpc0lzQU5pY2VTdHJpbmc='
ThisIsANiceString

Converts the Base64 encoded string 'VGhpc0lzQU5pY2VTdHJpbmc=' to a string.
#>
[OutputType([string])]
[CmdletBinding()]
param(
# The Base64 encoded string to convert.
[Parameter(Mandatory = $true)]
[string] $Base64String
)

[System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64String))
}
23 changes: 23 additions & 0 deletions src/functions/private/Base64/ConvertTo-Base64.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function ConvertTo-Base64 {
<#
.SYNOPSIS
Converts a string to a Base64 encoded string.

.DESCRIPTION
Converts a string to a Base64 encoded string.

.EXAMPLE
ConvertTo-Base64 -String 'ThisIsANiceString'
VGhpc0lzQU5pY2VTdHJpbmc=

Converts the string 'ThisIsANiceString' to a Base64 encoded string.
#>
[OutputType([string])]
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string] $String
)

[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($String))
}
26 changes: 26 additions & 0 deletions src/functions/private/Base64/Test-Base64.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function Test-Base64 {
<#
.SYNOPSIS
Test if a string is a valid Base64 string.

.DESCRIPTION
Test if a string is a valid Base64 string.

.EXAMPLE
Test-Base64 -Base64String 'U29tZSBkYXRh'
True

Returns $true as the string is a valid Base64 string.
#>
[OutputType([bool])]
[CmdletBinding()]
param (
[string] $Base64String
)
try {
$null = [Convert]::FromBase64String($Base64String)
return $true
} catch {
return $false
}
}
35 changes: 35 additions & 0 deletions src/functions/private/Get-ContextInfo.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
function Get-ContextInfo {
<#
.SYNOPSIS
Retrieves all context info from the context vault.

.DESCRIPTION
Retrieves all context info from the context vault.

.EXAMPLE
Get-ContextInfo

Get all context info from the context vault.
#>
param()

$vaultName = $script:Config.VaultName
$secretPrefix = $script:Config.SecretPrefix

Write-Verbose "Retrieving all context info from [$vaultName]"

Get-SecretInfo -Vault $vaultName | Where-Object { ($_.Name).StartsWith($secretPrefix) } | ForEach-Object {
$name64 = $_.Name -replace "^$secretPrefix"
if (Test-Base64 -Base64String $name64) {
$name = ConvertFrom-Base64 -Base64String $name64
Write-Verbose " + $name ($name64)"
[pscustomobject]@{
Name64 = $name64
SecretName = $_.Name
Name = $name
Metadata = $_.Metadata
Type = $_.Type
}
}
}
}
28 changes: 11 additions & 17 deletions src/functions/public/Context/Get-Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,27 @@ filter Get-Context {
Write-Debug "[$commandName] - Start"
$null = Get-ContextVault
$vaultName = $script:Config.VaultName
$secretPrefix = $script:Config.SecretPrefix
$fullID = "$secretPrefix$ID"
$contextInfos = Get-ContextInfo
}

process {
try {
if (-not $PSBoundParameters.ContainsKey('ID')) {
Write-Verbose "Retrieving all contexts from [$vaultName]"
$contexts = Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$secretPrefix*" }
} elseif ([string]::IsNullOrEmpty($ID)) {
Write-Verbose "Return 0 contexts from [$vaultName]"
return
} elseif ($ID.Contains('*')) {
# If wildcards are used, we can use the -Name parameter to filter the results. Its using the -like operator internally in the module.
Write-Verbose "Retrieving contexts matching [$ID] from [$vaultName]"
$contexts = Get-SecretInfo -Vault $vaultName -Name $fullID
Write-Verbose "Retrieving contexts like [$ID] from [$vaultName]"
$contextInfos = $contextInfos | Where-Object { $_.Name -like $ID }
} else {
# Needs to use Where-Object in order to support special characters, like `[` and `]`.
Write-Verbose "Retrieving context [$ID] from [$vaultName]"
$contexts = Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -eq $fullID }
$contextInfos = $contextInfos | Where-Object { $_.Name -eq $ID }
}

Write-Verbose "Found [$($contexts.Count)] contexts in [$vaultName]"
$contexts | ForEach-Object {
Write-Verbose " - $($_.Name)"
$contextJson = $_ | Get-Secret -AsPlainText
Write-Verbose "Found [$($contextInfos.Count)] contexts in [$vaultName]"
$contextInfos | ForEach-Object {
$contextJson = Get-Secret -Name $_.SecretName -Vault $vaultName -AsPlainText
ConvertFrom-ContextJson -JsonString $contextJson
}
} catch {
Expand All @@ -77,9 +72,8 @@ Register-ArgumentCompleter -CommandName Get-Context -ParameterName ID -ScriptBlo
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$($script:Config.SecretPrefix)$wordToComplete*" } | ForEach-Object {
$Name = $_.Name -replace "^$($script:Config.SecretPrefix)"
[System.Management.Automation.CompletionResult]::new($Name, $Name, 'ParameterValue', $Name)
}
Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}

17 changes: 8 additions & 9 deletions src/functions/public/Context/Remove-Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ filter Remove-Context {
$commandName = $MyInvocation.MyCommand.Name
Write-Debug "[$commandName] - Start"
$null = Get-ContextVault
$vaultName = $script:Config.VaultName
$secretPrefix = $script:Config.SecretPrefix
$fullID = "$secretPrefix$ID"
}

process {
try {

if ($PSCmdlet.ShouldProcess($fullID, 'Remove secret')) {
Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -eq $fullID } | Remove-Secret
if ($PSCmdlet.ShouldProcess($ID, 'Remove secret')) {
Get-ContextInfo | Where-Object { $_.Name -eq $ID } | ForEach-Object {
Remove-Secret -Name $_.SecretName -Vault $script:Config.VaultName
}
}
} catch {
Write-Error $_
Expand All @@ -60,8 +59,8 @@ Register-ArgumentCompleter -CommandName Remove-Context -ParameterName ID -Script
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$($script:Config.SecretPrefix)$wordToComplete*" } | ForEach-Object {
$Name = $_.Name -replace "^$($script:Config.SecretPrefix)"
[System.Management.Automation.CompletionResult]::new($Name, $Name, 'ParameterValue', $Name)
}
Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}
10 changes: 10 additions & 0 deletions src/functions/public/Context/Rename-Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@
Write-Debug "[$commandName] - End"
}
}

Register-ArgumentCompleter -CommandName Rename-Context -ParameterName ID -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}
14 changes: 10 additions & 4 deletions src/functions/public/Context/Set-Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,32 @@ function Set-Context {
$null = Get-ContextVault
$vaultName = $script:Config.VaultName
$secretPrefix = $script:Config.SecretPrefix
$fullID = "$secretPrefix$ID"
}

process {
try {
$secret = ConvertTo-ContextJson -Context $Context -ID $fullID
$secret = ConvertTo-ContextJson -Context $Context -ID $ID
} catch {
Write-Error $_
throw 'Failed to convert context to JSON'
}

try {
$name64 = ConvertTo-Base64 -String $ID
} catch {
Write-Error $_
throw 'Failed to convert ID to Base64'
}

$param = @{
Name = $fullID
Name = "$secretPrefix$name64"
Secret = $secret
Vault = $vaultName
}
Write-Verbose ($param | ConvertTo-Json -Depth 5)

try {
if ($PSCmdlet.ShouldProcess($fullID, 'Set Secret')) {
if ($PSCmdlet.ShouldProcess($ID, 'Set Secret')) {
Set-Secret @param
}
} catch {
Expand Down
8 changes: 4 additions & 4 deletions src/functions/public/ContextSetting/Get-ContextSetting.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ Register-ArgumentCompleter -CommandName Get-ContextSetting -ParameterName ID -Sc
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$($script:Config.SecretPrefix)$wordToComplete*" } | ForEach-Object {
$Name = $_.Name -replace "^$($script:Config.SecretPrefix)"
[System.Management.Automation.CompletionResult]::new($Name, $Name, 'ParameterValue', $Name)
}
Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}

Register-ArgumentCompleter -CommandName Get-ContextSetting -ParameterName Name -ScriptBlock {
Expand Down
8 changes: 4 additions & 4 deletions src/functions/public/ContextSetting/Remove-ContextSetting.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ Register-ArgumentCompleter -CommandName Remove-ContextSetting -ParameterName ID
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$($script:Config.SecretPrefix)$wordToComplete*" } | ForEach-Object {
$Name = $_.Name -replace "^$($script:Config.SecretPrefix)"
[System.Management.Automation.CompletionResult]::new($Name, $Name, 'ParameterValue', $Name)
}
Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}

Register-ArgumentCompleter -CommandName Get-ContextSetting -ParameterName Name -ScriptBlock {
Expand Down
8 changes: 4 additions & 4 deletions src/functions/public/ContextSetting/Set-ContextSetting.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ Register-ArgumentCompleter -CommandName Get-ContextSetting -ParameterName ID -Sc
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter

Get-SecretInfo -Vault $vaultName | Where-Object { $_.Name -like "$($script:Config.SecretPrefix)$wordToComplete*" } | ForEach-Object {
$Name = $_.Name -replace "^$($script:Config.SecretPrefix)"
[System.Management.Automation.CompletionResult]::new($Name, $Name, 'ParameterValue', $Name)
}
Get-ContextInfo | Where-Object { $_.Name -like "$wordToComplete*" } |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
}
}
16 changes: 8 additions & 8 deletions tests/Context.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Describe 'Context' {
$result = Get-Context -ID 'TestID'
$result | Should -Not -BeNullOrEmpty
$result.Name | Should -Be 'TestName'
$result.ID | Should -Be 'Context:TestID'
$result.ID | Should -Be 'TestID'
}
It 'Set-Context -Context $Context - Context can hold a bigger object' {
$Context = @{
Expand All @@ -134,7 +134,7 @@ Describe 'Context' {
$result.Count | Should -Be 1
$result | Should -Not -BeNullOrEmpty
$result.AccessToken | Should -Be 'MySecret'
$result.ID | Should -Be 'Context:TestID2'
$result.ID | Should -Be 'TestID2'
}
It 'Set-Context -Context $Context - Context can be saved multiple times' {
$Context = @{
Expand All @@ -150,7 +150,7 @@ Describe 'Context' {
$result | Should -Not -BeNullOrEmpty
$result.AccessToken | Should -Be 'MySecret'
$result.RefreshToken | Should -Be 'MyRefreshedSecret'
$result.ID | Should -Be 'Context:TestID3'
$result.ID | Should -Be 'TestID3'
}
}

Expand Down Expand Up @@ -262,11 +262,11 @@ Describe 'Context' {
}

# Test to see if it can be run multiple times
Set-Context -Context $githubLoginContext -ID 'BigComplexObject'
Set-Context -Context $githubLoginContext -ID 'BigComplexObject'
Set-Context -Context $githubLoginContext -ID 'BigComplexObject'
Write-Verbose (Get-Secret -Name 'Context:BigComplexObject' -AsPlainText) -Verbose
$object = Get-Context -ID 'BigComplexObject'
Set-Context -Context $githubLoginContext -ID 'BigComplexObjectWith[specialchars]'
Set-Context -Context $githubLoginContext -ID 'BigComplexObjectWith[specialchars]'
Set-Context -Context $githubLoginContext -ID 'BigComplexObjectWith[specialchars]'
Write-Verbose (Get-Context -ID 'BigComplexObjectWith[specialchars]') -Verbose
$object = Get-Context -ID 'BigComplexObjectWith[specialchars]'
$object.ApiRateLimits.Remaining | Should -Be 4985
$object.AuthToken | Should -BeOfType [System.Security.SecureString]
$object.AuthToken | ConvertFrom-SecureString -AsPlainText | Should -Be 'ghp_12345ABCDE67890FGHIJ'
Expand Down