Back in August 2012, I posted about getting certificates bound to Office Communication Server 2007 interfaces using PSExec.  As much as I respect MarkRuss and SysInternals, PSExec is quite fiddly.  We have PSH V2 in our lab (finally!), so a coworker (hi, Keith!) paved the way for using WinRM.

Now, getting OCS 2007 certs is quite painful because some are exposed through WMI, but only on the local box.  Get-WmiObject –ComputerName OCS2007Server1 <etc.> doesn’t work.  Previously, enter PSExec.  Now, enter WinRm.

  
function Get-OcsCert {
     param (
         $ComputerName = $null,
         $wmiClass = $null,
         $wmiInstance = $null
     );
    
     function ConvertTo-CertSn {
         begin   { $sn = $null; }
         process { $input | % { $sn = ("{0:x2}" -f $_) + $sn; }}
         end     { $sn; }
     }

     $callingFunction = (Get-Variable -Scope 1 -Name MyInvocation).Value.MyCommand -replace " .*";

     foreach ($var in @('ComputerName', 'wmiClass', 'wmiInstance')) {
         if (!(Test-Path variable:$var)) { Out-Error "$callingFunction -$var not specified."; }
     }

     $serialNumber = Invoke-Command -ComputerName $ComputerName -ScriptBlock {
         param (
             $wmiClass,
             $wmiInstance
         );
         if ($wmi = Get-WmiObject $wmiClass) {
             if ($wmi.Count) {
                 $snArray = $wmi | %{ if ($_.$wmiInstance) { $_.$wmiInstance; }} 
             } else {
                 $snArray = $wmi.$wmiInstance;
             }
             $sn = $null;
             $snArray |  % { $sn = ("{0:x2}" -f $_) + $sn; }
             $sn;
         } 
     } -ArgumentList $wmiClass, $wmiInstance;
    
     if ($serialNumber) { 
         $store = 'My'; # locally installed certs
         $ro = [System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly";
         $cu = [System.Security.Cryptography.X509Certificates.StoreLocation]"LocalMachine" ;
         $c = new-object System.Security.Cryptography.X509Certificates.X509Store("\\$computerName\$store",$cu);
         $c.Open($ro);
         $c.certificates | Where-Object { $_.SerialNumber -eq $serialNumber }
     }
}

function Get-AcessEdgeServerInternalCert {
     param ( $ComputerName = $null );
     Get-OCSCert -ComputerName $ComputerName -wmiClass MSFT_SIPFederationInternalEdgeListeningAddressSetting -wmiInstance TLSCertSN;
}


function Get-AcessEdgeServerExternalCert {
     param ( $ComputerName = $null );
     Get-OCSCert -ComputerName $ComputerName -wmiClass MSFT_SIPFederationExternalEdgeListeningAddressSetting -wmiInstance TLSCertSN;
}

function Get-ProxyServerCert {
     param ( $ComputerName = $null );
     Get-OCSCert -ComputerName $ComputerName -wmiClass MSFT_SIPListeningAddressData -wmiInstance TLSCertSN;
}

function Get-MediaRelayServerInternalCert {
     param ( $ComputerName = $null );
     # Same as Get-AccessEdgeServerInternalCert
     Get-OCSCert -ComputerName $ComputerName -wmiClass MSFT_SIPFederationInternalEdgeListeningAddressSetting -wmiInstance TLSCertSN;
}

function Get-MediaRelayServerExternalCert {
     param ( $ComputerName = $null );
     # Very different from Get-AccessEdgeServerExternalCert
     Get-OCSCert -ComputerName $ComputerName -wmiClass MSFT_SIPMediaRelaySetting -wmiInstance BankCertSN;
}

The more eagle-eyed among you will see that the wrapper functions (Get-AccessEdgeServerExternalCert, etc.) didn’t change much, save not having to pass in a $psExecPath.   Get-OCSCert is where all the fun lives.