
Я тщетно пытался найти решение этого конкретного вопроса, но не смог найти ситуацию, идентичную моей.
Предположим, в IIS 8.5 у меня есть несколько доменов и к каждому из них привязан сертификат SAN SSL (не wildcard) с помощью SNI:
a.domain.com
b.domain.com
c.domain.com
Если бы я хотел добавить d.domain.com
и сгенерировать новый SAN, включающий новый домен, я бы хотел иметь возможность заменить текущий сертификат без необходимости повторной привязки нового к трем вышеуказанным доменам (затем я мог бы вручную привязать новый 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
, чтобы можно было указать точные сайты, которые вам, возможно, нужно будет задействовать.