Search code examples
powershelliisssl-certificateinvoke-command

Powershell retrieving cert by Thumbprint as string versus string variable


I'm trying to piece together some PowerShell code to loop through a list of servers, return some info regarding their IIS sites and bindings, and if they have an https binding, get the certificateHash and use that locate the cert by thumbprint and return its expiration date.

The problem I am having is, when i run my code below $binding.cerficateHash seems to return what I would expect, a string of the cert Hash, but when I use that certificateHash property to try and get the cert by its thumbprint, it doesnt work... but when I take the raw string value of the certificateHash value and hardcode it, it works...

I've inspected the certificateHash.GetType() and it appears to be just a string, so i dont understand what im doing wrong, and ive tried a handful of things, with no avail, granted this is my first crack at powershell so there's lots I don't know.

$sites = Invoke-Command  -ComputerName $serverName { Import-Module WebAdministration; Get-ChildItem -path IIS:\Sites }  -ErrorAction SilentlyContinue 

foreach($site in $sites)
{
   $serverName
   $site.name
   $site.physicalPath

   foreach($binding in $site.bindings.Collection)
   {
        $binding.protocol 
        $binding.bindingInformation 
        $binding.certificateHash 
        $binding.certificateStoreName

        if($binding.certificateHash)
        {
            # This outputs AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
            $binding.certificateHash 

            # this retrieves a cert and returns its expiration date, Woohooo!
            Start-Job  Invoke-Command -ComputerName  $serverName -ScriptBlock  { (Get-ChildItem -path Cert:\LocalMachine\WebHosting | Where-Object {$_.Thumbprint -eq "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" })[0].GetExpirationDateString() }         

            # this does not find a cert, and ive tried many things, and no dice.
            Start-Job  Invoke-Command -ComputerName  $serverName -ScriptBlock  { (Get-ChildItem -path Cert:\LocalMachine\WebHosting | Where-Object {$_.Thumbprint -eq $binding.certificateHash })[0].GetExpirationDateString() }                        

            # i've tried extracting the hash via "tostring" and using that, no dice
            $hash = $binding.certificateHash.ToString() 
            Start-Job  Invoke-Command -ComputerName  $serverName -ScriptBlock  { (Get-ChildItem -path Cert:\LocalMachine\WebHosting | Where-Object {$_.Thumbprint -eq $hash })[0].GetExpirationDateString() }                       

            # i've tried adding some wildcards and using the -like operator, no dice.
            $hash = "*" + $binding.certificateHash + "*" 
            Start-Job  Invoke-Command -ComputerName  $serverName -ScriptBlock  { (Get-ChildItem -path Cert:\LocalMachine\WebHosting | Where-Object {$_.Thumbprint -lilke $hash })[0].GetExpirationDateString() }                                    
        }
   }      
}

Example output for a site.

  • Site1
  • D:\Apps\site1
  • http
  • *:80:Site1-test.ourdomain.com
  • https
  • *:443:Site1-test.ourdomain.com
  • AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  • WebHosting

Solution

  • The computer you invoke the script block on doesn't know about the $binding variable in your local session. (That's also why it works when passing a literal string.)

    Try passing the value as argument:

    Invoke-Command -Computer $serverName -Script {
       param ($hash)
       (gci Cert:\LocalMachine\WebHosting | ? Thumbprint -eq $hash)[0].GetExpirationDateString()
    } -Arg $binding.certificateHash