Substitua o certificado SAN SSL no IIS 8.5 rapidamente

Substitua o certificado SAN SSL no IIS 8.5 rapidamente

Procurei em vão encontrar uma solução para esta dúvida específica, mas não consigo encontrar uma situação idêntica à minha.

No IIS 8.5, digamos que eu tenha vários domínios e um certificado SAN SSL (não curinga) vinculado a cada um deles usando SNI:

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

Se eu quiser adicionar d.domain.come gerar uma nova SAN que inclua o novo domínio, quero poder substituir o certificado atual sem precisar vincular novamente o novo aos três domínios acima (posso vincular manualmente o novo quarto domínio ).

Agora imagine no meu exemplo acima que eu realmente tenho 20 domínios - é bastante demorado fazer isso, especialmente se você adicionar um novo site a cada duas semanas - sem mencionar o tempo de inatividade enquanto eu revinculo o site SSL por site. site.

Existe uma solução que posso aplicar para automatizar esse processo? Eu poderia imaginar um script PS fazendo isso, desde que eu tenha o hash do novo certificado, mas meu PS-fu não é forte o suficiente para descobrir como iterar por todos os sites e reaplicar o certificado (se é assim que precisa ser feito ). O ideal seria uma solução que importasse automaticamente o novo certificado (.pfx), removesse o antigo e religasse os sites.

EDITAR:Para confirmar, estou usando um endereço IP para todos os sites.

Responder1

Copie e cole as seguintes funções na janela do 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.")
    }
}

Em seguida, execute:

  1. Para listar todos os sites e suas ligações:

Get-IisSslBinding

  1. Para atualizar todos os sites e suas ligações SSL:

Get-IisSslBinding | Set-IisSslBinding -AfterThumbprint AAAAAAAAAAABBBBBBBBBBCCCCCCCCCCCCCCCCCCC

** Certifique-se de que o novo certificado SSL já esteja no armazenamento SSL. Além disso, Get-IisSslBindingfunciona como um -FilterBySiteNameparâmetro para que você possa direcionar os sites exatos em que precisa tocar.

informação relacionada