ps/Modules/Alkami.DevOps.Certificates/Public/Remove-Certificate.ps1

157 lines
7.5 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
function Remove-Certificate {
<#
.SYNOPSIS
Deletes a specified Certificate
.DESCRIPTION
This function helps locate a specific Certificate to delete based on where it is located and by a distinguishing characteristic.
Otherwise a Certificate object can be inputted into the function to delete as well.
For the function to work as intended, one of the three must be provided...
FriendlyName [string]
Thumbprint [string]
Certificate [object]
.PARAMETER <StoreLocation>
[string] Specifying the CurrentUser or LocalComputer when navigating Certificate locations
.PARAMETER <Store>
[string] Specifying the folder in which to search for a specific Certificate
.PARAMETER <FriendlyName>
[string] A descriptory text to distinguish different Certificates. Not always provided by the Certificate
.PARAMETER <Thumbprint>
[string] A specific code that singles out a Certificate
.PARAMETER <Certificate>
[object] This is an item (certificate) that has already been selected to run this function against
.EXAMPLE
Remove-Certificate -Store TrustedPublisher -FriendlyName 'Alkami Issued Token'
.EXAMPLE
Get-Item 'Cert:\LocalMachine\TrustedPublisher\E7EAC1F158CB26C5D2B061B9085D65F7CCC4ADAC' | Remove-Certificate
#>
[CmdletBinding(DefaultParameterSetName = 'Certificate', SupportsShouldProcess = $true)]
param (
[Parameter(Mandatory, ParameterSetName = "Certificate", ValueFromPipeline)]
[object]$Certificate,
[Parameter(ParameterSetName = "Thumbprint")]
[string]$Thumbprint,
[Parameter(ParameterSetName = "FriendlyName")]
[string]$FriendlyName,
[Parameter()]
[ValidateSet('CurrentUser','LocalMachine')]
[string]$StoreLocation = 'LocalMachine',
[Parameter()]
[ArgumentCompleter({
$possibleValues = @('My','TrustedPeople','CA','UserDS','Root','TrustedPublisher', 'AddressBook','Remote Desktop')
return $possibleValues | ForEach-Object { $_ } # Runs through the foreach loop while the user is tabbing through the different fields
})][string]$Store,
[Parameter()]
[switch]$Force
)
$logLead = Get-LogLeadName
# If the certificate is populated, and is not a string or is explicitly a certificate that data is used for input
if ($null -ne $Certificate ) {
$certType = $Certificate.GetType().Name
if ($certType -eq "String") {
Write-Error "$logLead : Certificate parameter was passed as an unrecognizable or unacceptable type: [$certType]. Exiting."
throw New-Object System.ArgumentException "Certificate parameter is expected to be a certificate object."
}
if ($certType -ne "X509Certificate2") {
Write-Warning "$logLead : Certificate is of type [$certType]. This is not explicitly an X509Certificate2, but it's not a string either. Proceeding."
}
$CertificatePSPath = $Certificate.PSPath
if (![string]::IsNullOrWhiteSpace($CertificatePSPath)) {
# Splitting the path to get the $Store and $StoreLocation
$pathSplits = $Certificate.PSParentPath -split '::'
if ($pathSplits[0] -eq "Microsoft.PowerShell.Security\Certificate") {
$CertLocationAndStore = $pathSplits[1] -split "\\"
# Overwriting user input with Certificate input for Store and StoreLocation
$CertStoreLocation = $CertLocationAndStore[0]
$CertStore = $CertLocationAndStore[1]
if (![string]::IsNullOrWhiteSpace($StoreLocation)) {
if ($CertStoreLocation -ne $StoreLocation) {
Write-Warning "$logLead : The Certificate's Store Location [$CertStoreLocation] does not match the inputted Store Location [$StoreLocation]"
Write-Warning "$logLead : Using the Certificate provided Store Location [$CertStoreLocation]"
$StoreLocation = $CertStoreLocation
}
if (![string]::IsNullOrWhiteSpace($Store)) {
if ($CertStore -ne $Store) {
Write-Warning "$logLead : The Certificate's Store [$CertStore] does not match the inputted Store [$Store]"
Write-Warning "$logLead : Using the Certificate provided Store [$CertStore]"
$Store = $CertStore
}
}
}
}
}
$Thumbprint = $Certificate.Thumbprint
}
$certBasePath = (Join-Path (Join-Path "cert:\" $StoreLocation) $Store)
# Testing to see if the $Store provided is an actual directory
if (!(Test-Path $certBasePath)) {
Write-Warning "$logLead : The specified store [$Store] does not exist on the store location [$StoreLocation]"
Write-Warning "$logLead : No work to do, stopping"
return
}
$certificates = @()
if (![string]::IsNullOrWhiteSpace($Thumbprint)) {
# Finding cert based on given Thumbprint
$certificates = @(Get-ChildItem $certBasePath -Recurse | Where-Object { $_.Thumbprint -eq $Thumbprint})
if (Test-IsCollectionNullOrEmpty $certificates) {
Write-Warning "$logLead : No certificate could be found with the thumbprint [$Thumbprint] in the specified store and location [$StoreLocation\$Store]"
Write-Warning "$logLead : No work to do, stopping"
return
}
} elseif(Test-StringIsNullOrWhiteSpace -value $FriendlyName) {
$foundCertificates = @(Get-ChildItem $certBasePath -Recurse | Where-Object { $_.FriendlyName -eq $FriendlyName })
Write-Warning "$logLead : Received no thumbprint, and an empty string for FriendlyName. This has resulted in inadvertent mass certificate removal in the past."
Write-Warning "$logLead : The following is the list of certificates which would be removed, along with their thumbprints."
Write-Warning "$logLead : If you truly intended to remove these certificates, call this function with each thumbprint explicitly:"
$foundCertificates
return
} else {
# Finding cert based on given FriendlyName
$certificates = @(Get-ChildItem $certBasePath -Recurse | Where-Object { $_.FriendlyName -eq $FriendlyName })
if (Test-IsCollectionNullOrEmpty $certificates) {
Write-Warning "$logLead : No certificate could be found with the friendly name [$FriendlyName] in the specified store and location [$StoreLocation\$Store]"
Write-Warning "$logLead : No work to do, stopping"
return
}
}
if ($Force -or $PSCmdlet.ShouldProcess("Do you want to delete [$($certificates.Count)] certificate(s) with thumbprint(s) [$($certificates.Thumbprint)] in store(s) [$($certificates.PSPath)]")) {
foreach ($cert in $certificates) {
# Checking to see if the Certificate has a Private Key
if ($cert.HasPrivateKey -eq $true) {
Write-Host "$logLead : Private Key Found"
# Removal of Certification and Private Key
Write-Host "$logLead : Removed $($Cert.PSPath) [$($cert.FriendlyName)] and corresponding Private Key"
Remove-Item -Path $Cert.PSPath -DeleteKey -Force
} else {
# If there is no private key, continue to delete the Certificate
Write-Host "$logLead : Private Key Not Found"
Write-Host "$logLead : Removing $($Cert.PSPath) $($cert.FriendlyName)"
Remove-Item -Path $Cert.PSPath -Force
}
}
}
}