So I had a need to get an idea of certificates installed on my Exchange 2010 Servers. So after a but of “binging” I adapted and created this function.
function Get-Certificate{
param([switch]$verbose=$False,
[string]$Server=(hostname),
[ValidateSet("AuthRoot","Root","CA","MY","Disallowed", "AddressBook","TrustedPeople","TrustedPublisher")] [string]$MemberName="root")
IF($verbose){Write-Host $Server"\"$MemberName -Foregroundcolor Yellow}
$ro=[System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly"
$lm=[System.Security.Cryptography.X509Certificates.StoreLocation]"LocalMachine"
$store=new-object System.Security.Cryptography.X509Certificates.X509Store("\\$Server\$MemberName",$lm)
$store.Open($ro)
$store.Certificates
}
Now this is okay, but I wanted to get it for all my Exchange Servers. So I bolted this around the function. (NB you have to run it in the Exchange Management Shell). Now this part
$CertStoresCSV =@()
$CertStoresCSV+="CertStore,Name"
$CertStoresCSV+="AuthRoot,Third-Part Root Certification Authorities"
$CertStoresCSV+="CA,Intermediate Certification Authorities"
$CertStoresCSV+="My,Personal"
$CertStoresCSV+="Root,Trusted Root Certification Authorities"
$CertStoresCSV+="AddressBook,AddressBook"
$CertStoresCSV+="TrustedPeople,TrustedPeople"
$CertStoresCSV+="TrustedPublisher,TrustedPublisher"
$CertStores = $CertStoresCSV | ConvertFrom-CSV
$matrix=@()
$s=@(); Get-ExchangeServer | where {-NOT $_.IsEdgeServer}| ForEach{$s+= $_.Name+"."+$_.Domain}
ForEach($Server in $s){
ForEach($CertStore in $CertStores){
$cs = $CertStore.CertStore
$n = $CertStore.Name
Write-Host $server"\"$cs"\"$n -Foregroundcolor Yellow
$c=Get-Certificate -Server $server -MemberName $cs
[array]$tmpMatrix = $c | Select @{Expression={$server};Label="Server"}, @{Expression={$cs};Label="Certstore"}, @{Expression={$n};Label="CertStoreName"},FriendlyName, Issuer, Subject, Thumbprint, NotAfter, NotBefore, HasPrivateKey
$Matrix += $tmpMatrix
}
Write-Host "-"
}
Okay so that is cool. We now have an array object called $Matrix, how about a bit of output. This creates another array that we can output to html in a bit.
$HtmlMatrix = @()
$byServer = $Matrix | Group Server | Sort Name
$tmpColS = @();$byServer | ForEach{$tmpColS += $_.Name}
$tmpCol = @();$tmpCol += "Certstore","CertStoreName", "FriendlyName", "Subject","Thumbprint";
$tmpCol += $tmpColS
[array]$byCert = $Matrix | Group Certstore, CertStoreName, Subject, FriendlyName, Thumbprint | Sort Name
ForEach($tmpCert in $byCert){
$tmpHtmlMatrix = "" | Select $tmpCol
[Array]$tmpName = $tmpCert.Name.Split(",")
$tmpHtmlMatrix.CertStore = $tmpCert.Group[0].CertStore
$tmpHtmlMatrix.CertStoreName = $tmpCert.Group[0].CertStoreName
$tmpHtmlMatrix.FriendlyName = $tmpCert.Group[0].FriendlyName
[Array]$tmpCertGroup = $tmpCert.Group
ForEach($tmpGroup in $tmpCertGroup){
$tmpS = $tmpGroup.Server
$tmpHtmlMatrix.$tmpS = "x"
$tmpHtmlMatrix.Subject = $tmpGroup.Subject
$tmpHtmlMatrix.Thumbprint = $tmpGroup.Thumbprint
}
$HtmlMatrix += $tmpHtmlMatrix
}
Now that is a bit funky, we have taken the array and then flipped it ;-) We now have servers as columns and certificates as rows. What the it then does is against each server / certificate, it puts an x in column. The result is $HtmlMatrix. Lets format that bad boy:
$today = Get-Date
$OutHtml = @()
$OutHtml += @"
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<head>
<TITLE>Certificate Information</TITLE></HEAD></span>
<span style="font-family: Consolas;"><Style>
TABLE{border-width: 1px;padding: 1px;border-style: solid;border-color: black;border-collapse: collapse; width=100%}
TD{border-width: 1px;padding: 1px;border-style: solid;border-color: black;}
TH{font-family:'Arial';font-size:12px;border-width: 1px;padding: 1px;border-style: solid;border-color: black;background-color:peachpuff;}
TR{font-family:'Arial';font-size:10px}
P{font-family:'Arial';font-size:12px;}
H2{font-family:'Arial';}
</Style>
</head>
<B><FONT size='2' face='VERDANA'>Certificate Information</B></font>
<BR><FONT size='1' face='VERDANA'>Last updated: $today</FONT></FONT>
"@
$tmpColH = @(); $tmpColH += "FriendlyName", "Subject","Thumbprint"; $tmpColH += $tmpColS
$htmlMatrix | Group CertStoreName | ForEach{$OutHtml += "<HR Size=6 Color=Green><H2>" + $_.Name + " [" + $_.Count + "]</H2>";$OutHtml += $_.Group | Select $tmpColH | ConvertTo-Html -Fragment}
$x=0
$i=0; $OutHtml | foreach{
If($x -eq 0){$bgcolor = "style='background-color:#dddddd'";$x=1}ELSE{$bgcolor = ""; $x=0}
Switch -wildcard ($_){
"*<tr>*" { $OutHtml[$i] = $OutHtml[$i].Replace("<tr>", "<tr $bgcolor>")}
"*<td>x</td>*" { $OutHtml[$i] = $OutHtml[$i].Replace("<td>x</td>","<td bgcolor=Yellow align=center><B>x</B></td>")}
"*<th>*" { $OutHtml[$i] = $OutHtml[$i].Replace("<th>", "<th class='vertical'>")}
}
$i++
}
$OutHtml | out-file CertificateInformation.html
The end result should be CertificateInformation.html.
Code to download is here: https://ucinfo.files.wordpress.com/2014/03/get-certificate.zip
Enjoy