Public/Uninstall-ADCSGoat.ps1
|
function Uninstall-ADCSGoat { <# .SYNOPSIS Removes an ADCSGoat deployment, restoring pre-change state ACL-last. .DESCRIPTION Drives the teardown contract settled in ADCSGoat issue #30 from the state file written at deploy time. Restores, in order: clone cns are removed from the selected CA's certificateTemplates (and the attribute returned to its pre-change member set), clone template objects and their companion OID objects are deleted, and finally the Enrollment Services security descriptor is restored byte-for-byte — reversing the ESC5 CA-object grant last. Any failure before the ACL step aborts and leaves the grant in place, reporting what remains. Performs no legacy detection; it restores only what the state file records. .PARAMETER StatePath Where the deploy state file lives. Defaults to ADCSGoat.State.xml next to the module root. .PARAMETER Server The domain controller to write to. Defaults to the logon server. .PARAMETER SkipLowPrivUser Leaves the low privileged lab user and its PAW RDP access in place. .PARAMETER LowPrivUserName The low privileged lab user to remove. Defaults to 'user'. Letters, digits, '.', '_' and '-', up to 20 characters. The user and its PAW RDP access are removed only when its description carries the ADCSGoat marker. .PARAMETER PawComputerName The workstation whose Remote Desktop Users group the lab user is removed from. Found in AD when omitted: the one computer named '*-PAW'. With zero or several matches the group cleanup is skipped with a warning. .EXAMPLE Uninstall-ADCSGoat Removes the lab user, then tears down the deployment recorded in the default state file. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'State-driven restore; destructive steps ordered ACL-last so a failure never strands a partial access state.')] [CmdletBinding()] param ( [Parameter()] [ValidateNotNullOrEmpty()] [string]$StatePath, [Parameter()] [ValidateNotNullOrEmpty()] [string]$Server, [Parameter()] [switch]$SkipLowPrivUser, [Parameter()] [ValidatePattern('^[\w.-]{1,20}$')] [string]$LowPrivUserName = 'user', [Parameter()] [ValidateNotNullOrEmpty()] [string]$PawComputerName ) begin { if ([string]::IsNullOrEmpty($StatePath)) { $StatePath = Join-Path -Path $PSScriptRoot -ChildPath '..\ADCSGoat.State.xml' } $teardownParams = @{ StatePath = $StatePath } if ($PSBoundParameters.ContainsKey('Server')) { $teardownParams['Server'] = $Server } } process { if (-not $SkipLowPrivUser) { $userParams = @{} if ($PSBoundParameters.ContainsKey('Server')) { $userParams['Server'] = $Server } # An account ADCSGoat did not create keeps its RDP access too; Remove-AGLowPrivUser warns about it below. if (Test-AGLowPrivUserOwned -UserName $LowPrivUserName @userParams) { $serverPrefix = if ($Server) { "LDAP://$Server/" } else { 'LDAP://' } $rootDSE = New-Object System.DirectoryServices.DirectoryEntry("${serverPrefix}RootDSE") $netbiosName = Get-ADDomainNameFromNc -ConfigurationNC "$($rootDSE.configurationNamingContext)" @userParams # Group membership first: deleting the user first would leave an orphaned SID in the PAW group. try { if (-not $PSBoundParameters.ContainsKey('PawComputerName')) { $PawComputerName = Find-AGPawComputer @userParams } Set-AGRdpUserAccess -ComputerName $PawComputerName -Member "$netbiosName\$LowPrivUserName" -Ensure Absent } catch { Write-Warning "Could not remove $netbiosName\$LowPrivUserName from Remote Desktop Users on the PAW: $($_.Exception.Message)" } } $null = Remove-AGLowPrivUser -UserName $LowPrivUserName @userParams } Invoke-AGDeployTeardown @teardownParams } } |