Ssl

快速替換 IIS 8.5 上的 SAN SSL 證書

  • December 15, 2017

我徒勞地尋找這個特定查詢的解決方案,但找不到與我相同的情況。

在 IIS 8.5 中,假設我有多個域,並且我有一個使用 SNI 綁定到每個域的 SAN SSL 證書(不是萬用字元):

a.domain.com
b.domain.com
c.domain.com

如果我想添加d.domain.com並生成一個包含新域的新 SAN,我希望能夠替換目前證書而不必將新證書重新綁定到上述 3 個域(然後我可以手動綁定新的第 4 個域)。

現在想像在我上面的範例中,我實際上有 20 個域 - 這樣做相當耗時,特別是如果您每兩週添加一個新站點 - 更不用說在我重新綁定 SSL 站點時的停機時間 -地點。

有沒有我可以應用的解決方案來自動化這個過程?如果我有新證書的雜湊值,我可以設想一個 PS 腳本來執行它,但是我的 PS-fu 不夠強大,無法計算出如何遍歷所有站點並重新應用證書(如果需要這樣做的話)。理想情況下,這將是一種自動導入新證書 (.pfx)、刪除舊證書並重新綁定站點的解決方案。

**編輯:**為了確認,我為所有站點使用一個 IP 地址。

將以下函式複製並粘貼到您的 PowerShell 視窗中:

function Get-IisSslBinding{
   [CmdletBinding()]
   Param(
       [Parameter(Position=0)] [Alias("fi","sn")]
       [string]$FilterBySiteName,
       [Parameter(Position=1, ValueFromPipelineByPropertyName=$true)] [Alias("co")] [ValidateNotnullOrEmpty()]
       [string[]]$ComputerName=$env:ComputerName
   )
   Begin{
       Write-Verbose ("$(Get-Date) - INFO - Load Microsoft.Web.Administration assembly...")
       $null=[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")
   }
   Process{
       Foreach($computer in $ComputerName){
           Try{
               If($computer -eq "$env:ComputerName"){
                   Write-Verbose ("$(Get-Date) - INFO - Open connection to local computer [ {0} ]..." -f $computer)
                   $webServer=New-Object Microsoft.Web.Administration.ServerManager
                   $null=$webServer
               }
               Else{
                   Write-Verbose ("$(Get-Date) - INFO - Open connection to remote computer [ {0} ]..." -f $computer)
                   $webServer=[Microsoft.Web.Administration.ServerManager]::OpenRemote($computer)
               }
               # filter sites
               $sites=($webServer.Sites | Where{$_.Name -match $FilterBySiteName})
               Foreach($site in $sites){
                   Write-Verbose ("$(Get-Date) - INFO - Get binding(s) for [ {0} ]..." -f $site.Name)
                   # filter bindings
                   $siteHttpsBindings=($site.Bindings | Where{$_.Protocol -eq "https"})
                   Foreach($siteHttpsBinding in $siteHttpsBindings){
                       Write-Verbose ("$(Get-Date) - INFO - Get binding information ...")
                       New-Object -Type PSObject -Property @{
                           'ComputerName'=$computer.ToUpper()
                           'SiteId'=$site.ID 
                           'SiteName'=$site.Name
                           'BindingInformation'=$siteHttpsBinding.GetAttributeValue("bindinginformation")
                           'Thumbprint'=$siteHttpsBinding.GetAttributeValue("certificateHash")
                           'CertificateStore'=$siteHttpsBinding.GetAttributeValue("certificateStoreName")
                           'Protocol'=$siteHttpsBinding.GetAttributeValue("protocol")
                       }
                   }
               }
           }
           Catch{
               Write-Verbose ("$(Get-Date) - ERROR - {0}" -f $_.Exception.GetBaseException().Message)
           }
           Finally{
               Write-Verbose ("$(Get-Date) - INFO - Dispose web server resources...")
               $webServer.Dispose()
           }
       }
   }
   End{
       Write-Verbose ("$(Get-Date) - INFO - Done")
   }
}
##
function Set-IisSslBinding{
   [CmdletBinding()]
   Param(
       [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [Alias("oh")] [ValidateNotnullOrEmpty()]
       [string]$Thumbprint,
       [Parameter(Position=1, Mandatory=$true)] [Alias("nh")] [ValidateNotnullOrEmpty()]
       [string]$AfterThumbprint,
       [Parameter(Position=2, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [Alias("sn")] [ValidateNotnullOrEmpty()]
       $SiteName,
       [Parameter(Position=3, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [Alias("co")] [ValidateNotnullOrEmpty()]
       [string[]]$ComputerName=$env:ComputerName
   )
   Begin{
       Write-Verbose ("$(Get-Date) - INFO - Load Microsoft.Web.Administration assembly...")
       $null=[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")
   }
   Process{
       Foreach($computer in $ComputerName){
           Try{
               If($computer -eq "$env:ComputerName"){
                   Write-Verbose ("$(Get-Date) - INFO - Open connection to local computer [ {0} ]..." -f $computer)
                   $webServer=New-Object Microsoft.Web.Administration.ServerManager
                   $IsCertificateInStore=((Get-ChildItem -Path CERT:\LocalMachine\My) -match $AfterThumbprint)
               }
               Else{
                   Write-Verbose ("$(Get-Date) - INFO - Open connection to remote computer [ {0} ]..." -f $computer)
                   $webServer=[Microsoft.Web.Administration.ServerManager]::OpenRemote($computer)
               }
               # If(-not $IsCertificateInStore){
                   # Write-Verbose ("$(Get-Date) - INFO - The computer [ {0} ] does not contain the certificate [ {1} ]... " -f $computer,$AfterThumbprint)
                   # Break
               # }
               Write-Verbose ("$(Get-Date) - INFO - Filter sites...")
               $sites=($webServer.Sites|where{$_.Name -match $SiteName})
               Foreach($site in $sites){
                   #filter bindings
                   $siteHttpsBindings=($site.Bindings|where{$_.Protocol -eq "https"})
                   Foreach($siteHttpsBinding in $siteHttpsBindings){
                       Switch($siteHttpsBinding.GetAttributeValue("certificateHash")){
                           $Thumbprint{
                               Write-Verbose ("$(Get-Date) - INFO - Remove old certificate [ {0} ]... " -f $siteHttpsBinding.GetAttributeValue("certificateHash"))
                               $BindingMethod=$siteHttpsBinding.Methods["RemoveSslCertificate"]
                               $BindingMethodInstance=$BindingMethod.CreateInstance()
                               $BindingMethodInstance.Execute()
                               Write-Verbose ("$(Get-Date) - INFO - Add new certificate [ {0} ]..." -f $AfterThumbprint)
                               $BindingMethod=$siteHttpsBinding.Methods["AddSslCertificate"]
                               $BindingMethodInstance=$BindingMethod.CreateInstance()
                               $BindingMethodInstance.Input.SetAttributeValue("certificateHash", $AfterThumbprint)
                               $BindingMethodInstance.Input.SetAttributeValue("certificateStoreName", "My")
                               $BindingMethodInstance.Execute()
                               New-Object -Type PSObject -Property @{
                                   'ComputerName'=$computer.ToUpper()
                                   'SiteId'=$site.ID 
                                   'SiteName'=$site.Name
                                   'BindingInformation'=$siteHttpsBinding.GetAttributeValue("bindingInformation")
                                   'Thumbprint'=$siteHttpsBinding.GetAttributeValue("certificateHash")
                                   'PreviousThumbprint'=$Thumbprint
                               }
                           }
                           Default{
                               Write-Verbose ("$(Get-Date) - INFO - Could not get https binding(s) attribute for [ {0} ]" -f $site.Name)
                               break
                           }
                       }                
                   }
               }
           }
           Catch{
               Write-Verbose ("$(Get-Date) - ERROR - {0}" -f $_.Exception.GetBaseException().Message)
           }
           Finally{
               Write-Verbose ("$(Get-Date) - INFO - Dispose web server resources...")
               $webServer.Dispose()
           }
       }
   }
   End{
       Write-Verbose ("$(Get-Date) - INFO - Done.")
   }
}

然後執行:

  1. 列出所有站點及其綁定:

Get-IisSslBinding

  1. 要更新所有站點及其 SSL 綁定:

Get-IisSslBinding | Set-IisSslBinding -AfterThumbprint AAAAAAAAAAABBBBBBBBBBCCCCCCCCCCCCCCCCCCC

** 確保新的 SSL 證書已經在 SSL 儲存中。還Get-IisSslBinding具有作為-FilterBySiteName參數的功能,因此您可以定位您可能需要觸摸的確切站點。

引用自:https://serverfault.com/questions/887634