Public/Tests/Unprotect-ConfigValue.Tests.ps1
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Justification = 'Builds a value in the legacy 0.2.x format to test backward compatibility.')] param() BeforeAll { $env:TCS_CONFIG_ROOT = Join-Path -Path $TestDrive -ChildPath 'config' $env:TCS_SKIP_UPDATE_CHECK = '1' $env:TCS_TELEMETRY_OPTOUT = '1' $ModuleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent Import-Module -Name (Join-Path -Path $ModuleRoot -ChildPath 'tcs.core.psd1') -Force } AfterAll { Remove-Module -Name tcs.core -Force -ErrorAction SilentlyContinue } Describe 'Unprotect-ConfigValue' { It "Should decrypt to original value" { $original = "RoundTripTestValue" $encrypted = Protect-ConfigValue -Value $original $decrypted = Unprotect-ConfigValue -EncryptedValue $encrypted $decrypted | Should -Be $original } It "Should return a string" { $encrypted = Protect-ConfigValue -Value "TypeCheckValue" $result = Unprotect-ConfigValue -EncryptedValue $encrypted $result | Should -BeOfType [string] } } Describe 'Unprotect-ConfigValue format and platforms' { BeforeAll { $key = New-Object byte[] 32 [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($key) } It 'Round-trips unicode text' { $text = 'pässwörd-✓-日本' Unprotect-ConfigValue -EncryptedValue (Protect-ConfigValue -Value $text) | Should -BeExactly $text } It 'Round-trips with a supplied key' { Unprotect-ConfigValue -EncryptedValue (Protect-ConfigValue -Value 'k' -Key $key) -Key $key | Should -BeExactly 'k' } It 'Requires the key for key-protected values' { $protected = Protect-ConfigValue -Value 'k' -Key $key Unprotect-ConfigValue -EncryptedValue $protected -ErrorAction SilentlyContinue -ErrorVariable errs | Should -BeNullOrEmpty $errs[0].ToString() | Should -Match '-Key' } It 'Fails with the wrong key' { $other = New-Object byte[] 32 $protected = Protect-ConfigValue -Value 'k' -Key $key { Unprotect-ConfigValue -EncryptedValue $protected -Key $other -ErrorAction Stop } | Should -Throw } It 'Detects tampering' { $protected = Protect-ConfigValue -Value 'k' -Key $key $bytes = [Convert]::FromBase64String($protected.Split(':')[3]) $bytes[20] = $bytes[20] -bxor 1 $tampered = 'tcs:v1:aes-key:' + [Convert]::ToBase64String($bytes) { Unprotect-ConfigValue -EncryptedValue $tampered -Key $key -ErrorAction Stop } | Should -Throw } It 'Returns a SecureString with -AsSecureString' { $secure = Unprotect-ConfigValue -EncryptedValue (Protect-ConfigValue -Value 's') -AsSecureString $secure | Should -BeOfType [System.Security.SecureString] [System.Net.NetworkCredential]::new('', $secure).Password | Should -BeExactly 's' } It 'Still reads values written by tcs.core 0.2.x, with a warning' { $legacyKey = [System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($env:COMPUTERNAME + 'tcs.core')) $legacy = ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -String 'old' -AsPlainText -Force) -Key $legacyKey Unprotect-ConfigValue -EncryptedValue $legacy -Scope LocalMachine -WarningVariable warnings -WarningAction SilentlyContinue | Should -BeExactly 'old' $warnings.Count | Should -Be 1 } } |