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