Tests/Public/Update-SecretRotationAccountPassword.Tests.ps1
|
BeforeAll { Import-Module (Join-Path $PSScriptRoot '../../Posh-SecretRotation.psd1') -Force } Describe 'Update-SecretRotationAccountPassword' -Tag Unit { BeforeEach { Mock -ModuleName Posh-SecretRotation Write-SecretRotationLog {} Mock -ModuleName Posh-SecretRotation Export-SecretRotationShareFile {} $script:testConfig = [PSCustomObject]@{ targets = [PSCustomObject]@{ 't1' = [PSCustomObject]@{ backend = 'ActiveDirectory' passwordRepresentation = 'SecureString' entropy = 128 shamir = [PSCustomObject]@{ groupThreshold = 1 groups = @([PSCustomObject]@{ threshold = 3; count = 5 }) } backendConfig = [PSCustomObject]@{ forest = 'corp.local'; identity = 'svc1' } } } } Mock -ModuleName Posh-SecretRotation Read-SecretRotationConfigFile { $script:testConfig } $script:fakePassword = New-Object System.Security.SecureString Mock -ModuleName Posh-SecretRotation New-SecretSharingPassword { $script:fakePassword } $script:fakeShares = @([PSCustomObject]@{ Mnemonic = 'a b c' }, [PSCustomObject]@{ Mnemonic = 'd e f' }) Mock -ModuleName Posh-SecretRotation Split-SecretSharingSecret { $script:fakeShares } Mock -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword {} } Context 'happy path' { It 'generates a password at the target entropy, sets it on the backend, splits it, and returns the shares' { $result = Update-SecretRotationAccountPassword -Target 't1' -Confirm:$false Should -Invoke -ModuleName Posh-SecretRotation New-SecretSharingPassword -Times 1 -Exactly -ParameterFilter { $Entropy -eq 128 } Should -Invoke -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword -Times 1 -Exactly -ParameterFilter { $Backend -eq 'ActiveDirectory' -and $Identifier -eq 'svc1' } Should -Invoke -ModuleName Posh-SecretRotation Split-SecretSharingSecret -Times 1 -Exactly @($result).Count | Should -Be 2 } It 'merges -BackendParameter over the target backendConfig, caller wins' { Update-SecretRotationAccountPassword -Target 't1' -BackendParameter @{ identity = 'override-svc' } -Confirm:$false Should -Invoke -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword -Times 1 -Exactly -ParameterFilter { $Identifier -eq 'override-svc' } } It 'does not generate a password, call the backend, or split under -WhatIf' { Update-SecretRotationAccountPassword -Target 't1' -WhatIf Should -Invoke -ModuleName Posh-SecretRotation New-SecretSharingPassword -Times 0 -Exactly Should -Invoke -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword -Times 0 -Exactly Should -Invoke -ModuleName Posh-SecretRotation Split-SecretSharingSecret -Times 0 -Exactly } It 'exports one file per share when -OutputPath is given' { Update-SecretRotationAccountPassword -Target 't1' -OutputPath 'C:\fake\out' -Confirm:$false # Export-SecretRotationShareFile takes ValueFromPipeline, so piping the 2-element # $fakeShares array invokes the (mocked) function once per share, not once overall. Should -Invoke -ModuleName Posh-SecretRotation Export-SecretRotationShareFile -Times $script:fakeShares.Count -Exactly } It 'does not export share files when -OutputPath is omitted' { Update-SecretRotationAccountPassword -Target 't1' -Confirm:$false Should -Invoke -ModuleName Posh-SecretRotation Export-SecretRotationShareFile -Times 0 -Exactly } It 'throws when the resolved identity is empty' { $script:testConfig.targets.t1.backendConfig = [PSCustomObject]@{ forest = 'corp.local' } { Update-SecretRotationAccountPassword -Target 't1' -Confirm:$false } | Should -Throw '*identity*' Should -Invoke -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword -Times 0 -Exactly } } Context 'backend failure' { BeforeEach { Mock -ModuleName Posh-SecretRotation Set-SecretRotationBackendPassword { throw 'backend exploded' } } It 'throws and never calls Split-SecretSharingSecret when the backend call fails' { { Update-SecretRotationAccountPassword -Target 't1' -Confirm:$false } | Should -Throw '*backend exploded*' Should -Invoke -ModuleName Posh-SecretRotation Split-SecretSharingSecret -Times 0 -Exactly } } Context 'unknown target' { It 'throws (via Get-SecretRotationTargetConfig) rather than proceeding' { { Update-SecretRotationAccountPassword -Target 'does-not-exist' -Confirm:$false } | Should -Throw '*t1*' } } } |