Ssl
快速替換 IIS 8.5 上的 SAN SSL 證書
我徒勞地尋找這個特定查詢的解決方案,但找不到與我相同的情況。
在 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.") } }
然後執行:
- 列出所有站點及其綁定:
Get-IisSslBinding
- 要更新所有站點及其 SSL 綁定:
Get-IisSslBinding | Set-IisSslBinding -AfterThumbprint AAAAAAAAAAABBBBBBBBBBCCCCCCCCCCCCCCCCCCC
** 確保新的 SSL 證書已經在 SSL 儲存中。還
Get-IisSslBinding
具有作為-FilterBySiteName
參數的功能,因此您可以定位您可能需要觸摸的確切站點。