Comparing certificates using Powershell - powershell

I'm working on a disaster recovery project and I am recommending as part of the plan to do regular audits of the primary and secondary sites. One of the audit tasks is to make sure that the secondary site has the same certificates installed as the primary site. I think I can accomplish this using Powershell
Get-ChildItem -Path Cert:\LocalMachine\My
Get-ChildItem -Path Cert:\LocalMachine\Root
I know I can use the above commands to get a list of certs but what I'm having trouble with is trying to do this all in one script. I would like to get the list of certs on one server and then get the list of certs on another server and then compare the two lists. I'm very new to Powershell so I'm not to sure where to start.

To retrieve the certificates you would use the underlying .NET classes since the Certificates provider does not expose remote machine connectivity by default. You may find another possibility with PS remoting as well. Here is the function:
function Get-Certificates {
Param(
$Computer = $env:COMPUTERNAME,
[System.Security.Cryptography.X509Certificates.StoreLocation]$StoreLocation,
[System.Security.Cryptography.X509Certificates.StoreName]$StoreName
)
$Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("\\$computer\$StoreName",$StoreLocation)
$Store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly")
$Store.Certificates
}
And here is how you would use it to compare two lists:
$Left = Get-Certificates -StoreLocation LocalMachine -StoreName Root
$Right = Get-Certificates -StoreLocation LocalMachine -StoreName Root -Computer "REMOTE-PC"
# Dump to console
Compare-Object $Left $Right -property Thumbprint, FriendlyName, Subject, NotAfter | Format-Table
# Export results to file
Compare-Object $Left $Right -property Thumbprint, FriendlyName, Subject, NotAfter | Export-Csv Comparison.csv

Related

Update multiple Certificate friendly names using PowerShell

I am fairly new to PowerShell and I am currently updating a large list of Certificate Friendly names remotely using PowerShell.
I have done the below script which works fine if there is one certificate but it fails if there is multiple certificates in the store as I need to add a Loop into the script. When I am trying to add a loop in it doesn't seem to be working. Could someone help or point me in the right direction please?
Enter-PSSession –ComputerName Servername
Get-ChildItem -Path Cert:\LocalMachine\My
$CertStore = "Cert:\LocalMachine\My\"
$FriendlyName = 'Examplename'
$cert = Get-ChildItem $CertStore
$cert.FriendlyName = $FriendlyName
Thanks for any help.
Just add a Foreach Loop into the script.
Something like below:
$CertStore = "Cert:\LocalMachine\My\"
$FriendlyName = 'Examplename'
$cert = Get-ChildItem $CertStore | foreach {$_.FriendlyName = $FriendlyName}
And this will update multiple Certificates with friendly names.

Remove Expired Certificates with Powershell

I have a simple script to show all certificates on a server, I would like to expand that script to then remove all expired certificates
I have tried several scripts from MS and 3rd parties to find a remove certs but have had no luck with them working properly
The first code I am using is:
Get-ChildItem Cert:\ -Recurse
This Powershell script shows all certificates on a server.
Example output is below for each certificate. I want to target the NotAfter field and have the script then remove the certificate if it's old than todays date
Subject:
Issuer:
Thumbprint:
FriendlyName:
NotBefore:
NotAfter:
Extensions
I would also like to do this for a list of servers, have the script run on each server in a text document, query all certificates, then remove the certs that are expired and move on to the next server.
I have seen some code targeting the date like the following:
ForEach-Object -begin { $now = get-date } -process { if ($PSItem.NotAfter -lt $now ) { $PSItem } } | Remove-Item
I would like the script to go out and query a servers certificates, then deletes out the expired certificates
What you are after is this. This should work perfectly for you. You were close in your logic, just the execution seemed to be a bit off.
$ListOfServers = Get-Content "c:\temp\serv.txt"
Foreach($Server in $ListOfServers) {
Invoke-Command -ComputerName $Server -ScriptBlock {
# Get Certificate list and assign to a variable
$Certs = Get-ChildItem "Cert:\LocalMachine\My" -Recurse
# Loop through each object in $Certs
Foreach($Cert in $Certs) {
# If The objects property "NotAfter" is older than the current time, delete
If($Cert.NotAfter -lt (Get-Date)) {
$Cert | Remove-Item
}
}
}
}
Edited based on comment to prevent accidental destruction of all certs.
To get a list of all cert storage locations.
(Get-ChildItem -Path "Cert:" -Recurse `
| Where-Object {($_).GetType().Name -eq 'X509Store'}).Name

How do I delete a user's certificate while remoting to his laptop as admin?

While remoting in using a PS Session and as a Remote Admin, I need to delete a certificate from the store: CurrentUser\My.
I've noticed that while there are similar questions already, they do NOT answer my question. None of them address the problem of inserting local user as the context for the command.
I have tried recursing through the directories of ...\Roaming\Microsoft\Crypto\RSA, changing the cert store to LocalMachine and inserting the username manually. Nothing works.
THIS WORKS
Get-ChildItem cert:"CurrentUser\My" | where {($_.Subject -like "*OU=CO*")} | remove-item -WhatIf
THIS DOES NOT (with remote session active)
PS C:\Users\Remote Admin: Get-ChildItem cert:"CurrentUser\My" | where {($_.Subject -like "*OU=CO*")} | remove-item -WhatIf
Certificates are stored in the Registry or in LocalAppData.
If you have administrative rights you can access the registry remotely via .Net for that user or the file system and remove the certificates as needed. Here's a test I ran.
First I created a dummy cert on a remote machine. This adds the cert to CurrentUser\My and CurrentUser\CA
New-SelfSignedCertificate -DnsName "www.fabrikam.com" -CertStoreLocation "Cert:\CurrentUser\My"
Thumbprint Subject
---------- -------
E5A33C1BB6FBA8A6DA397C6BFE2CE489F751AF10 CN=www.fabrikam.com
Next I remotely access and remove the cert by thumbprint from Registry CA store.
$computer = 'ComputerA'
$targetSID = 'S-1-5-21-1234567890-1234567890-1234567890-12345' #get-aduser username
$reg = [Microsoft.win32.registryKey]::OpenRemoteBaseKey('Users', $computer) #open remote registry
$avaliableSID = #($($reg.GetSubKeyNames() | Where-Object { $_ -match 'S-\d-\d+-(\d+-){1,14}\d+$' })) #get all users SIDS
if($avaliableSID -contains $targetSID ) #if it contains the one we want
{
$otherUserStore = $reg.OpenSubKey("$targetSID\software\microsoft\systemcertificates\ca\certificates", $true) #open profile for writing
$otherUserStore.DeleteSubKey('E5A33C1BB6FBA8A6DA397C6BFE2CE489F751AF10', $false) #delete key and suppress error if missing
}
I then remove it from the My store in %localappdata%
Remove-Item "\\$computer\c$\users\SOME.USER\appdata\roaming\microsoft\systemcertificates\my\certificates\$thumbprint" -Force #force required or you get access denied
Checking cert:\currentuser\my as that user shows no sign of the certificate. Of course you should add error checking, etc. but this example should help.

How to find and delete previously created certificates based on their dns name using powershell?

I can create a self signed certificate with PowerShell:
$cert = New-SelfSignedCertificate –DnsName www.test.com -CertStoreLocation “cert:\LocalMachine\My”
Because this is an automated test scenario, I must allow multiple runs. Next time I (which is a completely separate session) would like to find all certificates with dns name www.test.com, and completely wipe them. It could be more than one, of course with different thumbprint, etc.
Unfortunatelly I can not find any PowerShell command removes certificates. I suppose I should query based on dns, then in a loop remove...
Question
Can this task solved at all entirely in Powershell? (remove all certificates with given dns name)
If you have PowerShell v3 or greater this becomes very simple, as PS3 introduced the -DnsName parameter to the Certificate provider options of Get-ChildItem. This will find and delete anything with the DNSName of www.test.com:
Get-ChildItem Cert:\ -Recurse -DnsName 'www.test.com' | Remove-Item
It even supports wildcards, so if you have several certificates that you need to clean up with similar names such as 'mailproxy.test.com', 'www.test.com', and 'ftp.test.com' you could run this:
Get-ChildItem Cert:\ -Recurse -DnsName '*.test.com' | Remove-Item
Simple oneliner for this :
Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object {$_.DnsNameList -contains 'www.domain.org'} | Remove-Item
Remove-Item is the command used to remove a certificate.

How to search for Server Exchange or Server Authentication type certificates installed on host computer using PowerShell?

I'm trying to choose a certificate from the computer certificate store LocalMachine\My that serves for Server Exchange or Authentication (I'm unsure regarding the exact nomenclature) purposes. I know there are filters to return only certificates of a certain type, as such:
PS> Get-ChildItem Cert:\LocalMachine\My -codesigning
and what I want is to do something like:
PS> Get-ChildItem Cert:\LocalMachine\My -exchange
Which fails in PowerShell.
If such a filter keyword doesn't exists, can some venture a way to do it, or at least how to go about it?
To get a list of certs with server authentication you can filter by the enhanced key usage properties:
dir cert:\localmachine\my | ? {
$_.Extensions | % {
$_.EnhancedKeyUsages | ? {
$_.FriendlyName -eq "Server Authentication"}}}
You can read each certificate properties in this way:
Get-ChildItem Cert:\LocalMachine\My | fl *
then you can filter by property, in this case filtering by name of issuer:
Get-ChildItem Cert:\LocalMachine\My | where-object { $_.issuer -match "servername" }