Search code examples
powershelliis-10

reformatting `GCI IIS:\SSLBindings` to avoid truncation


There are 8 IIS sites on my Windows 2016 server. 6 are covered by the same multi-SAN certificate and 2 have different certificates.

GCI IIS:\SSLBindings truncates the list with an ellipsis:

    IP Address          Port   Host Name        Store            Sites
    ----------          ----   ---------        -----            -----
                        443                     CentralCertStore QA.ARIAUTODIRECT.COM
                                                                 QA.ARIBUYDIRECT.COM
                                                                 QA.ARIDEALERDIRECT.CA
                                                                 QA.ARIDEALERDIRECT.COM
                                                                 QA.ARITRUCKDIRECT.COM
                                                                 ...
    0.0.0.0             443                     WebHosting       QA.ARIAUTODIRECT.COM

Each site in the first group has an SSL binding for *:443:hostname -- i.e., all IPs, port 443, require SNI and hostname is specified. The last binding is the default binding with SNI not required and no hostname specified, used for old browsers not supporting SNI.

The output I would really like to see is this, formatted nicely for email reporting:

    IP Address          Port   Host Name (SNI)          Store            SiteName
    ----------          ----   ---------                -----            -----
    *                   443    QA.ARIAUTODIRECT.COM     CentralCertStore QA.ARIAUTODIRECT.COM
    *                   443    QA.ARIBUYDIRECT.COM      CentralCertStore QA.ARIBUYDIRECT.COM
    *                   443    QA.ARIDEALERDIRECT.CA    CentralCertStore QA.ARIDEALERDIRECT.CA
    *                   443    QA.ARIDEALERDIRECT.COM   CentralCertStore QA.ARIDEALERDIRECT.COM
    *                   443    QA.ARITRUCKDIRECT.COM    CentralCertStore QA.ARITRUCKDIRECT.COM
    *                   443    QA.VR.ARITRUCKDIRECT.COM CentralCertStore QA.VR.ARITRUCKDIRECT.COM
    *                   443    OPSSCQA.ARIFLEET.COM     CentralCertStore OPS -SC- QA
    0.0.0.0             443    -none-                   WebHosting       QA.ARIAUTODIRECT.COM

I've been hacking away at the PowerShell script, trying to overcome warnings about being unable to change $null into a string, or an integer into a string, etc., etc. So I'm taking a step back and asking if there's any obvious way to do this that I'm overlooking.

As an example, here's something I tried. It displays the sitename only, and there are no headers.

PS C:\windows\system32> dir iis:\sslbindings |%{ 
    $x = $_; $paths = $x.Sites |%{ $_.ItemXPath.Split("'")[1]}; 
    Add-Member -inputobject $_ -membertype NoteProperty -Name "SiteName" -Value $paths; 
    $_.SiteName } |FT
QA.ARIAUTODIRECT.COM
QA.ARIBUYDIRECT.COM
QA.ARIDEALERDIRECT.CA
QA.ARIDEALERDIRECT.COM
QA.ARITRUCKDIRECT.COM
QA.VR.ARIAUTODIRECT.COM
OPS -SC- QA
ARIXSSQA
QA.ARIAUTODIRECT.COM

EDIT: Results from @thepip3r's answer attempt. (Possibly i will remove this edit later, since it doesn't really add to the question, but lets me give a well-formatted response to thepip3r's answer)

as given:

IpAddress    : 
Port         : 443
Hostname_SNI : 
Store        : CentralCertStore
Site         : {QA.ARIAUTODIRECT.COM, QA.ARIBUYDIRECT.COM, QA.ARIDEALERDIRECT.CA, QA.ARIDEALERDIRECT.COM...}

IpAddress    : 0.0.0.0
Port         : 443
Hostname_SNI : 0.0.0.0
Store        : WebHosting
Site         : QA.ARIAUTODIRECT.COM

when FT is added to pipeline:

IpAddress Port Hostname_SNI Store            Site                                                                                         
--------- ---- ------------ -----            ----                                                                                         
           443              CentralCertStore {QA.ARIAUTODIRECT.COM, QA.ARIBUYDIRECT.COM, QA.ARIDEALERDIRECT.CA, QA.ARIDEALERDIRECT.COM...}
0.0.0.0    443 0.0.0.0      WebHosting       QA.ARIAUTODIRECT.COM

Solution

  • BETTER ANSWER

    Get-WebBinding produces a far better solution than IIS:\WebBindings.

     Get-WebBinding -Protocol https `
       |%{ 
          $bi = $_.bindingInformation.Split(":");
          [PsCustomObject]@{
            'IpAddress' = $bi[0]
            'Port' = $bi[1]
            'Hostname_SNI' = $bi[2]
            Store = $( if ($_.sslFlags -eq 3) {"CentralCertStore"} else {$_.certificatestorename} )
            SiteName = $_.ItemXPath.split("'")[1]
          }
        } |ft
    

    Results:

    IpAddress     Port Hostname_SNI            Store            SiteName               
    ---------     ---- ------------            -----            --------               
    *             443                          WebHosting       QA.ARIAUTODIRECT.COM   
    *             443  qa.ariautodirect.com    CentralCertStore QA.ARIAUTODIRECT.COM   
    *             443  qa.aribuydirect.com     CentralCertStore QA.ARIBUYDIRECT.COM    
    *             443  qa.aridealerdirect.ca   CentralCertStore QA.ARIDEALERDIRECT.CA  
    *             443  qa.aridealerdirect.com  CentralCertStore QA.ARIDEALERDIRECT.COM 
    *             443  qa.aritruckdirect.com   CentralCertStore QA.ARITRUCKDIRECT.COM  
    *             443  qa.vr.ariautodirect.com CentralCertStore QA.VR.ARIAUTODIRECT.COM
    *             443  OPSSCQA.ARIFLEET.COM    CentralCertStore OPS -SC- QA            
    10.220.100.98 443  arixssqa.arifleet.com   CentralCertStore ARIXSSQA            
    

    PREVIOUS ANSWER

    Thanks to 2 things I learned from the answer by @thepip3r (Split-Path -Leaf and [pscustomobject]@{...}) , I have surmounted the formatting problems. The blank Hostname_SNI problem remains and is due to the folding of the bindings. I guess because each of the bindings uses *:443, SNI, and CCS, it folds them together. It's still a little unexplained because those bindings actually have hostnames. But I'm happy enough with this for now.

    import-module webadministration
    dir iis:\sslbindings `
     |%{ $Binding = $_
         $Binding.Sites.ItemXPath |%{ $_.split("'")[1] } `
         |% { 
            [pscustomobject]@{
                'IpAddress'    = $( $ip = $Binding.IpAddress.IpAddressToString; if ([String]::IsNullOrWhiteSpace($ip)) { "*" } else { $ip } )
                'Port'         = $Binding.Port
                'Hostname_SNI' = $( $h = ($Binding.PSPath | Split-Path -Leaf).Split('!')[0]; if ([String]::IsNullOrWhiteSpace($h)) { "--none--" } else {$h} )
                'Store'        = $Binding.Store
                'SiteName'     = $_
            }
         }
     } |ft
    

    Output:

    IpAddress Port Hostname_SNI Store            SiteName               
    --------- ---- ------------ -----            --------               
    *          443 --none--     CentralCertStore QA.ARIAUTODIRECT.COM   
    *          443 --none--     CentralCertStore QA.ARIBUYDIRECT.COM    
    *          443 --none--     CentralCertStore QA.ARIDEALERDIRECT.CA  
    *          443 --none--     CentralCertStore QA.ARIDEALERDIRECT.COM 
    *          443 --none--     CentralCertStore QA.ARITRUCKDIRECT.COM  
    *          443 --none--     CentralCertStore QA.VR.ARIAUTODIRECT.COM
    *          443 --none--     CentralCertStore OPS -SC- QA            
    *          443 --none--     CentralCertStore ARIXSSQA               
    0.0.0.0    443 0.0.0.0      WebHosting       QA.ARIAUTODIRECT.COM