From 0d742907924a30bee933f4d1309dd0f7995f941b Mon Sep 17 00:00:00 2001 From: Shawn Melton <11204251+wsmelton@users.noreply.github.com> Date: Thu, 18 Mar 2021 22:04:58 -0500 Subject: [PATCH] Disable-TssSecretCheckout - closes #119 --- .../secrets/Disable-SecretCheckout.ps1 | 107 ++++++++++++++++++ src/parts/CheckOutSecret.ps1 | 51 +++++---- src/parts/GetInvokeTssParams.ps1 | 8 +- .../Disable-TssSecretCheckout.Tests.ps1 | 53 +++++++++ 4 files changed, 190 insertions(+), 29 deletions(-) create mode 100644 src/functions/secrets/Disable-SecretCheckout.ps1 create mode 100644 tests/secrets/Disable-TssSecretCheckout.Tests.ps1 diff --git a/src/functions/secrets/Disable-SecretCheckout.ps1 b/src/functions/secrets/Disable-SecretCheckout.ps1 new file mode 100644 index 00000000..241a939f --- /dev/null +++ b/src/functions/secrets/Disable-SecretCheckout.ps1 @@ -0,0 +1,107 @@ +function Disable-SecretCheckout { + <# + .SYNOPSIS + Disables the Checkout setting for a Secret + + .DESCRIPTION + Disables the Checkout setting for a Secret + + .EXAMPLE + $session = New-TssSession -SecretServer https://alpha -Credential $ssCred + Disable-TssSecretCheckout -TssSession $session -Id 28 + + Disable Secret 28's Checkout When Viewed setting + + .EXAMPLE + $session = New-TssSession -SecretServer https://alpha -Credential $ssCred + Disable-TssSecretCheckout -TssSession $session -Id 42,43,45 + + Disable Checkout When Viewed setting on Secret IDs 42, 43, and 45 + + .LINK + https://thycotic-ps.github.io/thycotic.secretserver/commands/Disable-TssSecretCheckout + + .NOTES + Requires TssSession object returned by New-TssSession + #> + [CmdletBinding(SupportsShouldProcess)] + param ( + # TssSession object created by New-TssSession for auth + [Parameter(Mandatory,ValueFromPipeline,Position = 0)] + [TssSession] + $TssSession, + + # Secret Id + [Parameter(Mandatory,ValueFromPipelineByPropertyName)] + [Alias("SecretId")] + [int[]] + $Id, + + # Comment to provide for restricted secret (Require Comment is enabled) + [Parameter(ParameterSetName = 'restricted')] + [string] + $Comment, + + # Associated Ticket Number + [Parameter(ParameterSetName = 'restricted')] + [int] + $TicketNumber, + + #Associated Ticket System ID + [Parameter(ParameterSetName = 'restricted')] + [int] + $TicketSystemId + ) + begin { + $tssParams = $PSBoundParameters + $invokeParams = . $GetInvokeTssParams $TssSession + + $restrictedParamSet = . $ParameterSetParams 'Enable-TssSecretEmail' 'restricted' + $restrictedParams = @() + foreach ($r in $restrictedParamSet) { + if ($tssParams.ContainsKey($r)) { + $restrictedParams += $r + } + } + } + process { + Write-Verbose "Provided command parameters: $(. $GetInvocation $PSCmdlet.MyInvocation)" + if ($tssParams.ContainsKey('TssSession') -and $TssSession.IsValidSession()) { + . $CheckVersion $TssSession '10.9.000000' $PSCmdlet.MyInvocation + foreach ($secret in $Id) { + $uri = $TssSession.ApiUrl, 'secrets', $secret, 'security-checkout' -join '/' + $invokeParams.Uri = $uri + + # data object for Checkout Settings + $CheckoutBody = @{ + data = @{ + checkOutEnabled = $false + } + } + $invokeParams.Method = 'PATCH' + $invokeParams.Body = $CheckoutBody | ConvertTo-Json + + if ($PSCmdlet.ShouldProcess("SecretId: $secret", "Pre-check out secret for setting Checkout settings")) { + . $CheckOutSecret $TssSession $tssParams $secret + } + + if ($PSCmdlet.ShouldProcess("SecretId: $secret", "$($invokeParams.Method) $($invokeParams.Uri) with:`n$($invokeParams.Body)`n")) { + Write-Verbose "$($invokeParams.Method) $($invokeParams.Uri) with:`n$($invokeParams.Body)`n" + try { + $restResponse = Invoke-TssRestApi @invokeParams + } catch { + Write-Warning "Issue configuring [$secret] Checkout settings" + $err = $_ + . $ErrorHandling $err + } + + if (-not $restResponse.checkOutEnabled.value) { + Write-Verbose "Secret [$secret] Checkout disabled" + } + } + } + } else { + Write-Warning "No valid session found" + } + } +} \ No newline at end of file diff --git a/src/parts/CheckOutSecret.ps1 b/src/parts/CheckOutSecret.ps1 index ea5490ee..6945f7bc 100644 --- a/src/parts/CheckOutSecret.ps1 +++ b/src/parts/CheckOutSecret.ps1 @@ -30,32 +30,34 @@ begin { } process { - # secret view comment - $uri = $TssSession.ApiUrl, 'secret-access-requests', 'secrets', $SecretId, 'view-comment' -join '/' - $restrictedBody = @{} if ($FunctionParameters.ContainsKey('Comment')) { $restrictedBody.Add('comment', $FunctionParameters['Comment']) } if ($FunctionParameters.ContainsKey('TicketNumber')) { - $restrictedBody.Add('comment', $FunctionParameters['TicketNumber']) + $restrictedBody.Add('ticketNumber', $FunctionParameters['TicketNumber']) } if ($FunctionParameters.ContainsKey('TicketSystemId')) { - $restrictedBody.Add('comment', $FunctionParameters['TicketSystemId']) + $restrictedBody.Add('ticketSystemId', $FunctionParameters['TicketSystemId']) } - $invokeViewCommentParams.Uri = $uri - $invokeViewCommentParams.Body = $restrictedBody | ConvertTo-Json - $invokeViewCommentParams.Method = 'POST' + if ($restrictedBody.Count -gt 0) { + # secret view comment + $uri = $TssSession.ApiUrl, 'secret-access-requests', 'secrets', $SecretId, 'view-comment' -join '/' - if ($PSCmdlet.ShouldProcess("SecretId: $SecretId", "$($invokeViewCommentParams.Method) $uri with: `n$($invokeViewCommentParams.Body)`n")) { - Write-Verbose "$($invokeViewCommentParams.Method) $uri with:`n$($invokeViewCommentParams.Body)`n" - try { - $viewCommentResponse = Invoke-TssRestApi @invokeViewCommentParams - } catch { - Write-Warning "Issue doing pre-checkout of Secret [$SecretId]" - $err = $_ - . $ErrorHandling $err + $invokeViewCommentParams.Body = $restrictedBody | ConvertTo-Json + $invokeViewCommentParams.Uri = $uri + $invokeViewCommentParams.Method = 'POST' + + if ($PSCmdlet.ShouldProcess("SecretId: $SecretId", "$($invokeViewCommentParams.Method) $uri with: `n$($invokeViewCommentParams.Body)`n")) { + Write-Verbose "$($invokeViewCommentParams.Method) $uri with:`n$($invokeViewCommentParams.Body)`n" + try { + $viewCommentResponse = Invoke-TssRestApi @invokeViewCommentParams + } catch { + Write-Warning "Issue doing pre-checkout of Secret [$SecretId]" + $err = $_ + . $ErrorHandling $err + } } } @@ -64,16 +66,15 @@ process { $invokeCheckOutParams.Uri = $uri $invokeCheckOutParams.Method = 'POST' if ($PSCmdlet.ShouldProcess("SecretId: $SecretId", "$($invokeCheckOutParams.Method) $uri")) { - if ($viewCommentResponse) { - Write-Verbose "$($invokeCheckOutParams.Method) $uri" - try { - $checkOutResponse = Invoke-TssRestApi @invokeCheckOutParams - } catch { - Write-Warning "Issue doing pre-checkout of Secret [$SecretId]" - $err = $_ - . $ErrorHandling $err - } + Write-Verbose "$($invokeCheckOutParams.Method) $uri" + try { + $checkOutResponse = Invoke-TssRestApi @invokeCheckOutParams + } catch { + Write-Warning "Issue doing pre-checkout of Secret [$SecretId]" + $err = $_ + . $ErrorHandling $err } + if ($checkOutResponse) { Write-Verbose "Secret [$secretId] checked out successfully" } diff --git a/src/parts/GetInvokeTssParams.ps1 b/src/parts/GetInvokeTssParams.ps1 index 1c63d218..e35a1b32 100644 --- a/src/parts/GetInvokeTssParams.ps1 +++ b/src/parts/GetInvokeTssParams.ps1 @@ -11,14 +11,14 @@ param( ) process { - $invokeParams = @{} + $getInvokeParams = @{} switch ($TssSession.TokenType) { 'WindowsAuth' { - $invokeParams.UseDefaultCredentials = $true + $getInvokeParams.UseDefaultCredentials = $true } default { - $invokeParams.PersonalAccessToken = $TssSession.AccessToken + $getInvokeParams.PersonalAccessToken = $TssSession.AccessToken } } - return $invokeParams + return $getInvokeParams } \ No newline at end of file diff --git a/tests/secrets/Disable-TssSecretCheckout.Tests.ps1 b/tests/secrets/Disable-TssSecretCheckout.Tests.ps1 new file mode 100644 index 00000000..34971f18 --- /dev/null +++ b/tests/secrets/Disable-TssSecretCheckout.Tests.ps1 @@ -0,0 +1,53 @@ +BeforeDiscovery { + $commandName = Split-Path ($PSCommandPath.Replace('.Tests.ps1','')) -Leaf + . ([IO.Path]::Combine([string]$PSScriptRoot, '..', 'constants.ps1')) +} +Describe "$commandName verify parameters" { + BeforeDiscovery { + [object[]]$knownParameters = 'TssSession', 'Id', 'Comment', 'TicketNumber', 'TicketSystemId' + [object[]]$currentParams = ([Management.Automation.CommandMetaData]$ExecutionContext.SessionState.InvokeCommand.GetCommand($commandName,'Function')).Parameters.Keys + [object[]]$commandDetails = [System.Management.Automation.CommandInfo]$ExecutionContext.SessionState.InvokeCommand.GetCommand($commandName,'Function') + $unknownParameters = Compare-Object -ReferenceObject $knownParameters -DifferenceObject $currentParams -PassThru + } + Context "Verify parameters" -ForEach @{currentParams = $currentParams } { + It "$commandName should contain <_> parameter" -TestCases $knownParameters { + $_ -in $currentParams | Should -Be $true + } + It "$commandName should not contain parameter= <_>" -TestCases $unknownParameters { + $_ | Should -BeNullOrEmpty + } + } +} +Describe "$commandName functions" { + Context "Checking" { + BeforeAll { + $session = [pscustomobject]@{ + ApiVersion = 'api/v1' + Take = 2147483647 + SecretServer = 'http://alpha/' + ApiUrl = 'http://alpha/api/v1' + AccessToken = 'AgJf5YLFWtzw2UcBrM1s1KB2BGZ5Ufc4qLZ' + RefreshToken = '9oacYFZZ0YqgBNg0L7VNIF6-Z9ITE51Qplj' + TokenType = 'bearer' + ExpiresIn = 1199 + } + Mock -Verifiable -CommandName Get-TssVersion -MockWith { + return @{ + Version = '10.9.000033' + } + } + + $secretId = Get-Random -Maximum 60 + Mock -Verifiable -CommandName Invoke-TssRestApi -ParameterFilter { $Uri -eq "$($session.ApiUrl)/secrets/$secretId/security-checkout"; $Method -eq 'PATCH' } -MockWith { + return [pscustomobject]@{ + checkOutEnabled = @{fieldInputType = 'String'; sortOrder = ""; value = $false; label = 'Require Check Out'; name = ""; description = 'When enabled a user will need to checkout a Secret before they can access it. Checkout will prevent other users from accessing the Secret while it is checked out.' ; readOnly = ""; placeholder = ""; hidden = $false; hideOnView = ""; hasHistory = ""; isRequired = ""; readOnlyReason = ""; helpLink = ""} + } + } + $object = Disable-TssSecretCheckout -TssSession $session -Id $secretId + Assert-VerifiableMock + } + It "Should be empty" { + $object | Should -BeNullOrEmpty + } + } +} \ No newline at end of file