#WindowsPowerShell and Windows Certificates

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