I have a script that gets the remote computer certificates from the MY store, but it didn’t get certs from any other store, or the Template name. I found how to specify the store name (or get all stores) and a script to list the template name, so I’m posting an updated version.
To get the remote computer’s Personal store:
powershell .\Get-RemoteMachineCertificates.ps1 <COMPUTERNAME>
or
powershell .\Get-RemoteMachineCertificates.ps1 <COMPUTERNAME> my
To get the remote computer’s Trusted Root Certification Authorities store:
powershell .\Get-RemoteMachineCertificates.ps1 <COMPUTERNAME> root
To get all the certificates on the remote computer:
powershell .\Get-RemoteMachineCertificates.ps1 <COMPUTERNAME> *
Output resembles:
Path : Microsoft.PowerShell.Security\Certificate::localmachine\my
Subject : CN=computername.domain.name
FriendlyName :
Issuer : CN=Company Device Management CA, DC=domain, DC=name
ExpirationDate : 3/31/2023 3:14:07 PM
Thumbprint : 4E3B34D12348B5687F0366AA7B231268A324BBBB
IntendedPurposes : Client Authentication; KeyEncipherment, DigitalSignature
Template : Company SCCM Client v1
Get-RemoteMachineCertificates.ps1:
param([Parameter(Mandatory=$true)][string] $Computer, [string] $Store = "my")
function Get-CertificateTemplateName($certificate)
{
# The template name is stored in the Extension data.
# If available, the best is the extension named "Certificate Template Name", since it contains the exact name.
$templateExt = $certificate.Extensions | Where-Object{ ( $_.Oid.FriendlyName -eq 'Certificate Template Name') } | Select-Object -First 1
if($templateExt) {
return $templateExt.Format(1)
}
else {
# Our fallback option is the "Certificate Template Information" extension, it contains the name as part of a string like:
# "Template=Web Server v2(1.3.6.1.4.1.311.21.8.2499889.12054413.13650051.8431889.13164297.111.14326010.6783216)"
$templateExt = $certificate.Extensions | Where-Object{ ( $_.Oid.FriendlyName -eq 'Certificate Template Information') } | Select-Object -First 1
if($templateExt) {
$information = $templateExt.Format(1)
# Extract just the template name in $Matches[1]
if($information -match "^Template=(.+)\([0-9\.]+\)") {
return $Matches[1]
} else {
# No regex match, just return the complete information then
return $information
}
} else {
# No template name found
return $null
}
}
}
Write-Host "
To list certificates from something other than the MY store, use the following:
Store Display Name Store name to use
============================================= =================================
AAD Token Issuer 'AAD Token Issuer'
Certificate Enrollment Requests REQUEST
Client Authentication Issuers ClientAuthIssuer
Enterprise Trust Trust
eSIM Certification Authorities 'eSIM Certification Authorities'
Homegroup Machine Certificates 'Homegroup Machine Certificates'
Intermediate Certification Authorities CA
Local NonRemovable Certificates 'Local NonRemovable Certificates'
MSIEHistoryJournal MSIEHistoryJournal
Other People addressbook
Personal My
Preview Build Roots FlightRoot
Remote Desktop 'Remote Desktop'
Smart Card Trusted Roots SmartCardRoot
sms SMS
Test Roots TestSignRoot
Third-Party Root Certification Authorities AuthRoot
Trusted Devices TrustedDevices
Trusted Packaged App Installation Authorities TrustedAppRoot
Trusted People TrustedPeople
Trusted Publishers TrustedPublisher
Trusted Root Certification Authorities Root
Untrusted Certificates Disallowed
Windows Live ID Token Issuer 'Windows Live ID Token Issuer'
WindowsServerUpdateServices WindowsServerUpdateServices
For all stores, use *
" -ForegroundColor "Yellow"
$Store = "cert:localmachine\" + $Store
$parameters = @{
ComputerName = $Computer
ScriptBlock = {Get-ChildItem $args[0] -Recurse}
ArgumentList = $Store
}
$certs = Invoke-Command @parameters
$certs | foreach-object {
$Usages = foreach($key in $_.Extensions) {
if('KeyUsages' -in $key.psobject.Properties.Name ) {$key.KeyUsages}
if('EnhancedKeyUsages' -in $key.psobject.Properties.Name) {$key.EnhancedKeyUsages.FriendlyName}
}
$IntendedPurposes = $Usages -join "; "
$Template = Get-CertificateTemplateName($_)
$output = new-object PSObject
$output | add-member NoteProperty -Name Path -Value $_.PSParentPath
$output | add-member NoteProperty -name Subject -value $_.Subject
$output | add-member NoteProperty -name FriendlyName -value $_.FriendlyName
$output | add-member NoteProperty -name Issuer -value $_.Issuer
$output | add-member NoteProperty -name ExpirationDate -value $_.GetExpirationDateString()
$output | add-member NoteProperty -name Thumbprint -value $_.Thumbprint
$output | add-member NoteProperty -name IntendedPurposes -value $IntendedPurposes
$output | add-member NoteProperty -name Template -value $Template
$output
}