UserCertificates.psm1
#region Get-ActiveDirectoryObjectCertificate function Get-ActiveDirectoryObjectCertificate { <# .Synopsis Get the user certificates from Active Directory .DESCRIPTION Get the certificates saved on a user object in X509 format .EXAMPLE Get-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local Get the certificates on the cpolydorou@lab.local Active Directory object #> #region Parameters [CmdletBinding(DefaultParameterSetName='Parameter Set DN', PositionalBinding=$false)] Param ( # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set DN')] [string[]] $DistinguishedName, # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set UPN')] [string[]] $UserPrincipalName, # The SamAccountName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set SAM')] [string[]] $SamAccountName ) #endregion #region Begin Begin { #region Directory Searcher setup $root = New-Object System.DirectoryServices.DirectoryEntry $searcher = New-Object System.DirectoryServices.DirectorySearcher $searcher.SearchRoot = $root $searcher.SearchScope = "Subtree" $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $searcher.PropertiesToLoad.Add("sAMAccountName") | Out-Null $searcher.PropertiesToLoad.Add("userPrincipalName") | Out-Null $searcher.PropertiesToLoad.Add("userCertificate") | Out-Null #endregion } #endregion #region Process Process { #region DistinguishedName if($DistinguishedName) { foreach($dn in $DistinguishedName) { $filter = "(distinguishedName=$dn)" $searcher.Filter = $filter try { $result = $searcher.FindOne() } catch { Write-Error "Error" } if($result -ne $null) { __CustomObject -user $result } else { Write-Error "Could not find an object with DistinguishedName $dn" } } } #endregion #region UserPrincipalName if($UserPrincipalName) { foreach($upn in $UserPrincipalName) { $filter = "(UserPrincipalName=$upn)" $searcher.Filter = $filter $result = $searcher.FindOne() if($result -ne $null) { __CustomObject -user $result } else { Write-Error "Could not find an object with UserPrincipalName $upn" } } } #endregion #region SamAccountName if($SamAccountName) { foreach($sam in $SamAccountName) { $filter = "(SamAccountName=$sam)" $searcher.Filter = $filter $result = $searcher.FindOne() if($result -ne $null) { __CustomObject -user $result } else { Write-Error "Could not find an object with SamAccountName $sam" } } } #endregion } #endregion #region End End {} #endregion } #endregion #region Remove-ActiveDirectoryObjectCertificate function Remove-ActiveDirectoryObjectCertificate { <# .Synopsis Remove a certificate from an Active Directory user object .DESCRIPTION Remove a certificate from an Active Directory user object .EXAMPLE Remove-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local -Thumbprint "6C1FC463805E72EBF401E039EC307627078C1339" -Verbose Removes the certificate with thumbprint 6C1FC463805E72EBF401E039EC307627078C1339 from the object. .EXAMPLE Remove-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local -Verbose Removes all certificates from the object .EXAMPLE Remove-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local -Expired -Verbose Removes all expired certificates from the object. #> #region Parameters [CmdletBinding(DefaultParameterSetName='Parameter Set DN', SupportsShouldProcess=$true, ConfirmImpact='High', PositionalBinding=$false)] Param ( # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set DN')] [string] $DistinguishedName, # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set UPN')] [string] $UserPrincipalName, # The SamAccountName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set SAM')] [string] $SamAccountName, # The thumbprint of the certificate to remove [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set SAM')] [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set DN')] [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set UPN')] [string] $Thumbprint, # Remove the expired certificates [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set SAM')] [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set DN')] [Parameter(Mandatory=$false, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set UPN')] [switch] $Expired ) #endregion #region Begin Begin { #region Directory Searcher setup $root = New-Object System.DirectoryServices.DirectoryEntry $searcher = New-Object System.DirectoryServices.DirectorySearcher $searcher.SearchRoot = $root $searcher.SearchScope = "Subtree" $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $searcher.PropertiesToLoad.Add("sAMAccountName") | Out-Null $searcher.PropertiesToLoad.Add("userPrincipalName") | Out-Null $searcher.PropertiesToLoad.Add("userCertificate") | Out-Null #endregion } #endregion #region Process Process { #region Get the user Write-Verbose "Getting the Active Directory object..." #region DistinguishedName if($DistinguishedName) { $filter = "(distinguishedName=$DistinguishedName)" $target = $DistinguishedName } #endregion #region UserPrincipalName if($UserPrincipalName) { $filter = "(UserPrincipalName=$UserPrincipalName)" $target = $UserPrincipalName } #endregion #region SamAccountName if($SamAccountName) { $filter = "(SamAccountName=$SamAccountName)" $target = $SamAccountName } #endregion # Get the object $searcher.Filter = $filter $Result = $searcher.FindOne() $Object = [ADSI]$Result.GetDirectoryEntry() # Check the result if($Result -eq $null) { Write-Error "Could not find the specified object." return } # Get the certificates $Certificates = New-Object -TypeName System.Collections.ArrayList for($i=0; $i -lt $Object.Properties.usercertificate.Count; $i++) { $Certificates.Add($Object.usercertificate[$i]) | Out-Null } #endregion #region Remove the certificate for($i = 0; $i -lt $Certificates.Count; $i++) { # Convert the certificate to X509 format $cert = __ADtoX509 -ADCertificate $Certificates[$i] #region Remove using thumbprint if($Thumbprint) { if($Thumbprint -eq $cert.Thumbprint) { if ($pscmdlet.ShouldProcess($target, "Remove-ActiveDirectoryUserCertificate with Thumbprint $($cert.thumbprint)")) { #region Update the object try { Write-Verbose "Removing certificate with thumbprint $($cert.Thumbprint)..." $Object.userCertificate.Remove($Object.userCertificate[$i]) $Object.CommitChanges() Write-Verbose "Certificate $($cert.Thumbprint) removed successfully." } catch { Write-Error ("Could not remove certificate $($cert.Thumbprint)" + "`n" + $_) } #endregion } continue } } #endregion #region Remove expired if($Expired) { if(([DateTime]::Now) -gt $cert.NotAfter) { if ($pscmdlet.ShouldProcess($target, "Remove-ActiveDirectoryUserCertificate with Thumbprint $($cert.thumbprint)")) { #region Update the object try { Write-Verbose "Removing certificate with thumbprint $($cert.Thumbprint)..." $Object.userCertificate.Remove($Object.userCertificate[$i]) $Object.CommitChanges() Write-Verbose "Certificate $($cert.Thumbprint) removed successfully." } catch { Write-Error ("Could not remove certificate $($cert.Thumbprint)" + "`n" + $_) } #endregion } } continue } #endregion #region remove all if( (-not $Thumbprint) -and (-not $Expired)) { if ($pscmdlet.ShouldProcess($target, "Remove-ActiveDirectoryUserCertificate with Thumbprint $($cert.thumbprint)")) { #region Update the object try { Write-Verbose "Removing certificate with thumbprint $($cert.Thumbprint)..." $Object.userCertificate.Remove($Object.userCertificate[$i]) $Object.CommitChanges() Write-Verbose "Certificate $($cert.Thumbprint) removed successfully." } catch { Write-Error ("Could not remove certificate $($cert.Thumbprint)" + "`n" + $_) } #endregion } } #endregion } #endregion } #endregion #region End End {} #endregion } #endregion #region Import-ActiveDirectoryObjectCertificate function Import-ActiveDirectoryObjectCertificate { <# .Synopsis Add a certificate to Active Directory .DESCRIPTION Add a certificate to Active Directory from file .EXAMPLE Import-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local -Path .\certificate.cer -Verbose Import the certificate from the file "certificate.cer" to the cpolydorou@lab.local Active Directory object. #> #region Parameters [CmdletBinding(DefaultParameterSetName='Parameter Set DN', PositionalBinding=$false)] Param ( # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set DN')] [string] $DistinguishedName, # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set UPN')] [string] $UserPrincipalName, # The SamAccountName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set SAM')] [string] $SamAccountName, # The path to the file [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set SAM')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set DN')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set UPN')] [string] $Path ) #endregion #region Begin Begin { #region Directory Searcher setup $root = New-Object System.DirectoryServices.DirectoryEntry $searcher = New-Object System.DirectoryServices.DirectorySearcher $searcher.SearchRoot = $root $searcher.SearchScope = "Subtree" $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $searcher.PropertiesToLoad.Add("sAMAccountName") | Out-Null $searcher.PropertiesToLoad.Add("userPrincipalName") | Out-Null $searcher.PropertiesToLoad.Add("userCertificate") | Out-Null #endregion } #endregion #region Process Process { #region Get the object Write-Verbose "Getting the object..." #region DistinguishedName if($DistinguishedName) { foreach($dn in $DistinguishedName) { $filter = "(distinguishedName=$dn)" $searcher.Filter = $filter if($result -eq $null) { Write-Error "Could not find an object with DistinguishedName $dn" } } } #endregion #region UserPrincipalName if($UserPrincipalName) { foreach($upn in $UserPrincipalName) { $filter = "(UserPrincipalName=$upn)" $searcher.Filter = $filter $result = $searcher.FindOne() if($result -eq $null) { Write-Error "Could not find an object with UserPrincipalName $upn" } } } #endregion #region SamAccountName if($SamAccountName) { foreach($sam in $SamAccountName) { $filter = "(SamAccountName=$sam)" $searcher.Filter = $filter $result = $searcher.FindOne() if($result -eq $null) { Write-Error "Could not find an object with SamAccountName $sam" } } } #endregion $Object = [ADSI]$Result.GetDirectoryEntry() #endregion #region Import the certificate Write-Verbose "Reading the file..." if((Test-Path -Path $Path) -ne $true) { Write-Error "Failed to open the file." return } else { $fullPath = (Resolve-Path -Path $Path).Path } try { $newCert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 $newCert.Import($fullPath) } catch { Write-Error "Failed read the certificate from the file.`n$_" return } Write-Verbose "Adding the certificate to the Active Directory object..." try { $Object.userCertificate.Add($newCert.GetRawCertData()) | Out-Null $Object.CommitChanges() } catch { Write-Error "Failed to add the certificate to the Active Directory object." } #endregion } #endregion #region End End {} #endregion } #endregion #region Export-ActiveDirectoryObjectCertificate function Export-ActiveDirectoryObjectCertificate { <# .Synopsis Save the user certificate from Active Directory to file .DESCRIPTION Save the user certificate from Active Directory to file .EXAMPLE Export-ActiveDirectoryObjectCertificate -UserPrincipalName cpolydorou@lab.local -Thumbprint "176ED95A217C692131DF1275B323F5574EFBF00A" -Path C:\Temp\file.cer Exports the certificate with thumbprint 176ED95A217C692131DF1275B323F5574EFBF00A to the file C:\Temp\file.cer #> #region Parameters [CmdletBinding(DefaultParameterSetName='Parameter Set DN', PositionalBinding=$false)] Param ( # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set DN')] [string] $DistinguishedName, # The DistinguishedName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set UPN')] [string] $UserPrincipalName, # The SamAccountName of the user [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=0, ParameterSetName='Parameter Set SAM')] [string] $SamAccountName, # The thumbprint of the certificate to remove [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set SAM')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set DN')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=1, ParameterSetName='Parameter Set UPN')] [string] $Thumbprint, # The path to the file [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set SAM')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set DN')] [Parameter(Mandatory=$true, ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, ValueFromRemainingArguments=$false, Position=2, ParameterSetName='Parameter Set UPN')] [string] $Path ) #endregion #region Begin Begin { #region Directory Searcher setup $root = New-Object System.DirectoryServices.DirectoryEntry $searcher = New-Object System.DirectoryServices.DirectorySearcher $searcher.SearchRoot = $root $searcher.SearchScope = "Subtree" $searcher.PropertiesToLoad.Add("distinguishedName") | Out-Null $searcher.PropertiesToLoad.Add("sAMAccountName") | Out-Null $searcher.PropertiesToLoad.Add("userPrincipalName") | Out-Null $searcher.PropertiesToLoad.Add("userCertificate") | Out-Null #endregion } #endregion #region Process Process { #region Get the certificates Write-Verbose "Getting the object's certificates..." #region DistinguishedName if($DistinguishedName) { $Certificates = Get-ActiveDirectoryObjectCertificate -DistinguishedName $DistinguishedName | % Certificate } #endregion #region UserPrincipalName if($UserPrincipalName) { $Certificates = Get-ActiveDirectoryObjectCertificate -UserPrincipalName $UserPrincipalName | % Certificate } #endregion #region SamAccountName if($SamAccountName) { $Certificates = Get-ActiveDirectoryObjectCertificate -SamAccountName $SamAccountName | % Certificate } #endregion #endregion #region Export the certificate $found = 0 foreach($c in $Certificates) { if($c.Thumbprint -eq $Thumbprint) { Write-Verbose "Exporting certificate to file..." [System.IO.File]::WriteAllBytes($Path, $c.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)) $found++ } } if($found -eq 0) { Write-Error "Could not find the specified certificate." } #endregion } #endregion #region End End {} #endregion } #endregion #region Helper Functions #region __ADtoX509 Function __ADtoX509 { # Convert a Base64 string to X509 certificate Param ( [string[]]$ADCertificate ) try { $X509Cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 $X509Cert.Import([byte[]]$ADCertificate) $X509Cert } catch{} } #endregion #region __CustomObject function __CustomObject { Param ( $user ) $cert = $user.Properties.usercertificate | %{ __ADtoX509 -ADCertificate $_ } $props = [ordered]@{ DistinguishedName = $user.Properties.distinguishedname.Item(0) UserPrincipalName = $user.Properties.userprincipalname.Item(0) SamAccountName = $user.Properties.samaccountname.Item(0) Certificate = $cert } New-Object -TypeName PSObject -Property $props } #endregion #endregion #region Exports Export-ModuleMember -Function Get-ActiveDirectoryObjectCertificate Export-ModuleMember -Function Remove-ActiveDirectoryObjectCertificate Export-ModuleMember -Function Import-ActiveDirectoryObjectCertificate Export-ModuleMember -Function Export-ActiveDirectoryObjectCertificate #endregion |