
我徒勞地尋找這個特定查詢的解決方案,但找不到與我相同的情況。
在 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 位址。
答案1
將下列函數複製並貼上到 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
參數,以便您可以定位您可能需要觸摸的確切網站。