使用PowerShell将IIS SSL证书分配给与主机头的绑定

使用PowerShell将IIS SSL证书分配给与主机头的绑定,powershell,ssl,certificate,iis-8,Powershell,Ssl,Certificate,Iis 8,我正在尝试将证书分配给HTTPS绑定。 不幸的是,我从PowerShell中收到以下错误: new-item : Cannot create a file when that file already exists At line:3 char:56 + get-item -Path "cert:\localmachine\my\$cert" | new-item -path IIS:\SslBi ... +

我正在尝试将证书分配给HTTPS绑定。 不幸的是,我从PowerShell中收到以下错误:

new-item : Cannot create a file when that file already exists
At line:3 char:56
+         get-item -Path "cert:\localmachine\my\$cert" | new-item -path IIS:\SslBi ...
+                                                        ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-Item], Win32Exception
    + FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.NewItemCommand
我执行的PowerShell是:

 New-WebBinding -name $Name -Protocol https -HostHeader "$Name.domain.com" -Port 443 -SslFlags 1
 $cert = Get-ChildItem -Path Cert:\LocalMachine\My | where-Object {$_.subject -like "*cloud.domain.com*"} | Select-Object -ExpandProperty Thumbprint
 get-item -Path "cert:\localmachine\my\$cert" | new-item -path IIS:\SslBindings\0.0.0.0!443!$Name.domain.com
它似乎能够找到证书,但无法将其分配给创建的绑定。 使用正确的IP/Port/HostHeader创建绑定,检查SNI,但“未选择”SSL证书

在IIS管理器中一切正常

我尝试过SO和其他网站的各种说明,例如:


而且,我也试过

IIS:\SslBindings\0.0.0.0!443!$Name.domain.com

证书的主题为cloud.domain.com,并具有多个SAN属性,例如**.domain.com*、domain.com、**.seconddomain.com*、seconddomain.com、cloud.domain.com

编辑:


现在我正在使用这种方法,它确实有效:

$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"

但是,我仍然对没有
netsh
/
appcmd
的解决方案感兴趣。我不熟悉IIS,但错误表明绑定(文件)已经存在,因此您不是在添加SSL绑定,而是在更新一个。尝试将
-Force
添加到
新项
命令中。如果它与文件类似,则应覆盖现有绑定。比如:

New-WebBinding -name $Name -Protocol https -HostHeader "$Name.domain.com" -Port 443 -SslFlags 1
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | where-Object {$_.subject -like "*cloud.domain.com*"} | Select-Object -ExpandProperty Thumbprint
get-item -Path "cert:\localmachine\my\$cert" | new-item -path IIS:\SslBindings\0.0.0.0!443!$Name.domain.com -Force

现在我正在使用这种方法,它确实有效:

$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"

我在SNI和powershell方面也遇到了一些问题。我错过的一个重要步骤实际上是在证书的导入过程中。您需要确保证书标记为“可导出”,否则webadministration模块将无法与其绑定

如果你有,那么你的原始脚本应该可以工作。不过,我个人更喜欢使用证书变量,而不是指纹

像这样:

New-WebBinding -name $Name -Protocol https -HostHeader "$Name.domain.com" -Port 443 -SslFlags 1
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | where-Object {$_.subject -like "*cloud.domain.com*"}
New-Item -Path "IIS:\SslBindings\!443!$Name.domain.com" -Value $cert -SSLFlags 1

以下方法对我有效:

在HTTP.sys中添加新的SSL配置后,将SslFlags设置为1的新绑定添加到网站,如下所示

  • 在HTTP.sys中添加新绑定
  • 使用新WebBinding向网站添加新绑定

  • 以下是我如何为机器FQDN生成自签名证书并添加SSL证书和绑定的方法

    $fqdn = "$((Get-WmiObject win32_computersystem).DNSHostName).$((Get-WmiObject win32_computersystem).Domain)" 
    $cert=(Get-ChildItem cert:\LocalMachine\My | where-object { $_.Subject -match "CN=$fqdn" } | Select-Object -First 1) 
    if ($cert  -eq $null) { 
    $cert = New-SelfSignedCertificate -DnsName $fqdn -CertStoreLocation "Cert:\LocalMachine\My" 
    } 
    $binding = (Get-WebBinding -Name SiteNameHere | where-object {$_.protocol -eq "https"})
    if($binding -ne $null) {
        Remove-WebBinding -Name SiteNameHere -Port 443 -Protocol "https" -HostHeader $fqdn
    } 
    New-WebBinding -Name SiteNameHere -Port 443 -Protocol https -HostHeader $fqdn 
    (Get-WebBinding -Name SiteNameHere -Port 443 -Protocol "https" -HostHeader $fqdn).AddSslCertificate($cert.Thumbprint, "my")
    

    根据@ElanHasson的回答,我制作了这个脚本,它将生成一个自签名的TLS证书,并将其应用于一个网站。可以稍微整理一下,但它可以:

    Clear-Host
    $certificateDnsName = 'my.localcert.ssl' # a name you want to give to your certificate (can be anything you want for localhost)
    
    $siteName = "Default Web Site" # the website to apply the bindings/cert to (top level, not an application underneath!).
    $fqdn = ""                     #fully qualified domain name (empty, or e.g 'contoso.com')
    
    
    # ----------------------------------------------------------------------------------------
    # SSL CERTIFICATE CREATION
    # ----------------------------------------------------------------------------------------
    
    # create the ssl certificate that will expire in 2 years
    $newCert = New-SelfSignedCertificate -DnsName $certificateDnsName -CertStoreLocation cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(2)
    "Certificate Details:`r`n`r`n $newCert"
    
    
    # ----------------------------------------------------------------------------------------
    # IIS BINDINGS
    # ----------------------------------------------------------------------------------------
    
    
    $webbindings = Get-WebBinding -Name $siteName
    $webbindings
    
    
    $hasSsl = $webbindings | Where-Object { $_.protocol -like "*https*" }
    
    if($hasSsl)
    {
        Write-Output "ERROR: An SSL certificate is already assigned. Please remove it manually before adding this certificate."
        Write-Output "Alternatively, you could just use that certificate (provided it's recent/secure)."
    }
    else
    {
        "Applying TLS/SSL Certificate"
        New-WebBinding -Name $siteName -Port 443 -Protocol https -HostHeader $fqdn #could add -IPAddress here if needed (and for the get below)
        (Get-WebBinding -Name $siteName -Port 443 -Protocol "https" -HostHeader $fqdn).AddSslCertificate($newCert.Thumbprint, "my")
    
        "`r`n`r`nNew web bindings"
        $webbindings = Get-WebBinding -Name $siteName
        $webbindings
    }
    
    
    "`r`n`r`nTLS/SSL Assignment Complete"
    
    fqdn为空(且未分配
    -IPAddress
    ),它将在IIS中为您提供以下信息:

    新建项:当文件已存在时,无法创建该文件

    正在删除
    0.0.0.0!443
    预先绑定为我解决了这个问题:

    Get-Item IIS:\SslBindings\0.0.0.0!443 | Remove-Item
    
    仅供参考:我制作了一个Powershell脚本,用于在没有显式IP绑定的情况下,使用SNI/SSL主机头将通配符证书批量分配给站点,其中新证书的友好名称类似于
    *。example.com 2019

    #SCRIPT FOR ADMIN POWERSHELL TO BULK ASSIGN A WILDCARD SSL CERTIFICATE TO ONE OR MORE WEBSITES USING SSL HOST HEADERS WITHOUT EXPLICIT IPS
    
    
    # —————————————————————————————
    # User Configurable Variables:
    # —————————————————————————————
    $wildcardDomain="*.example.com";    # This string should be present in the friendly name of the new SSL certificate
    
    $yearMatchingNewCert="2019";    # This string should be UNIQUELY present in the friendly name of the new SSL certificate
    
    
    # Make the IIS: drive available
    Import-Module WebAdministration;
    
    
    
    # —————————————————————————————
    # Auto-Determine the certificate store to use from the usual 'My' or 'WebHosting' locations
    # —————————————————————————————
    $certInWebHostingStore=dir Cert:\localmachine\WebHosting | where-Object {$_.subject -like "$wildcardDomain*"};
    $certInPersonalStore=dir Cert:\localmachine\My | where-Object {$_.subject -like "$wildcardDomain*"};
    if ($certInWebHostingStore) {$certStoreDir="WebHosting"} elseif ($certInPersonalStore) {$certStoreDir="My"} else {$certStoreDir=null};
    $certStorePath="\localmachine\$certStoreDir";
    echo "███ The NEW certificate is living in this store: $certStorePath";
    
    
    # —————————————————————————————
    # Get the Thumbprint of the NEW certificate
    # —————————————————————————————
    $certThumbHashNew=Get-ChildItem -Path Cert:$certStorePath | where-Object {$_.subject -like "$wildcardDomain*" -and $_.FriendlyName -like "*$yearMatchingNewCert*"} | Select-Object -ExpandProperty Thumbprint;
    echo "███ The NEW certificate's thumbprint hash is: $certThumbHashNew"; # If this displays as empty then you have either not installed the certificate, it's not in the usual Certificate stores or the certificate friendly name doesn't match the pattern "*.example.com 2019" e.g. "*.example.com (2018-2021)"
    
    
    
    # —————————————————————————————
    # Display the existing bindings
    # —————————————————————————————
    #Dir IIS:\SslBindings;                      # Shows all bindings
    #Dir IIS:\SslBindings\!443!*;               # Shows all port 443 bindings
    Dir IIS:\SslBindings\!443!$wildcardDomain;  # Shows all bindings in use matching the wildcard certificate
    
    
    
    # —————————————————————————————
    # Remove the Existing Bindings
    # —————————————————————————————
    # NOTE: SNI settings are in the Registry if all else fails: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\HTTP\Parameters\SslSniBindingInfo
    Get-Item IIS:\SslBindings\!443!$wildcardDomain | Remove-Item;
    
    
    
    # —————————————————————————————
    # Add the New Bindings
    # —————————————————————————————
    Get-Item -Path "cert:$certStorePath\$certThumbHashNew" | New-Item -Path IIS:\SslBindings\!443!$wildcardDomain;
    
    
    
    # —————————————————————————————
    # The IIS Manager doesn't seem to update its GUI without this bit
    # —————————————————————————————
    #(Get-WebBinding -Port 443 -Protocol "https" -HostHeader $wildcardDomain).RemoveSslCertificate($certThumbHashNew, $certStoreDir);
    (Get-WebBinding -Port 443 -Protocol "https" -HostHeader $wildcardDomain).AddSslCertificate($certThumbHashNew, $certStoreDir);
    
    奇怪的是,在获得新的控制台会话之前,查看PowerShell中的更改(列出绑定)不会显示更改,因此关闭并重新打开Admin PowerShell窗口

    # —————————————————————————————
    # User Configurable Variables:
    # —————————————————————————————
    $wildcardDomain="*.example.com";
    # —————————————————————————————
    
    
    # Make the IIS: drive available
    Import-Module WebAdministration;
    
    
    # —————————————————————————————
    # Display the new bindings
    # —————————————————————————————
    Dir IIS:\SslBindings\!443!$wildcardDomain
    
    
    
    # —————————————————————————————
    # Troubleshooting
    # —————————————————————————————
    # If things go awry, the 0.0.0.0 address usually seems to be at fault, particularly if the error is "New-Item : Cannot create a file when that file already exists"
    # To remove it follow these steps, then start over with the previous script again:
    # View all the port 443 bindings, not just the ones matching our wilcard:
    #Dir IIS:\SslBindings\!443!*
    # If the 0.0.0.0 binding shows in the list then use this to drop it:
    #Get-Item IIS:\SslBindings\0.0.0.0!443 | Remove-Item
    
    制作此脚本时使用的参考:

    • 这根线

    谢谢。我没有覆盖现有的绑定。无论是
    Get Webbinding
    还是
    Get item-路径IIS:\sslbindings\*
    都不显示
    0.0.0.0:443:mysite.domain.com
    的现有绑定。有一个是0.0.0.0:443。我设法用
    netsh
    实现了这一点,但我仍然对PowerShell方式感兴趣。而且
    -force
    参数不起作用,我遇到了同样的错误不幸的是,我没有太多的IIS经验。此时,powershell中的IIS提供程序可能不知道SNI。您还可以考虑使用CCS解决方案的SNI吗?这不是一个更易于维护的解决方案吗?:)我还没有玩过中央证书,也许值得一试。但是,即使没有SNI,您也应该能够将同一证书分配给多个主机头。(我目前只使用一个证书),SSL主机头从IIS 7开始就存在。。(因此我假设PS支持它)这是不真实的,证书绝对不必标记为可导出,从安全角度来看,这样做是不可取的。我成功地使用powershell绑定到未标记为可导出的证书。OPs问题是将ssl与主机头绑定,但主机头对我不起作用,但它与证书的可导出性无关。这到底有什么帮助?这将创建HTTP.SYS绑定,但这如何帮助您解决克服IIS绑定错误的原始问题?我尝试了这个,但当文件存在时,我仍然无法创建文件。您是否以某种方式将GUID与绑定相关联?如果要更改已存在的绑定,您必须先执行“netsh http delete sslcert hostnameport=MYHOSTNAME:443”操作。此部分为+1,我一直无法理解,但比我读到的任何其他内容都更有意义:
    新Web绑定
    <代码>(获取网络绑定)。添加证书(…)
    # —————————————————————————————
    # User Configurable Variables:
    # —————————————————————————————
    $wildcardDomain="*.example.com";
    # —————————————————————————————
    
    
    # Make the IIS: drive available
    Import-Module WebAdministration;
    
    
    # —————————————————————————————
    # Display the new bindings
    # —————————————————————————————
    Dir IIS:\SslBindings\!443!$wildcardDomain
    
    
    
    # —————————————————————————————
    # Troubleshooting
    # —————————————————————————————
    # If things go awry, the 0.0.0.0 address usually seems to be at fault, particularly if the error is "New-Item : Cannot create a file when that file already exists"
    # To remove it follow these steps, then start over with the previous script again:
    # View all the port 443 bindings, not just the ones matching our wilcard:
    #Dir IIS:\SslBindings\!443!*
    # If the 0.0.0.0 binding shows in the list then use this to drop it:
    #Get-Item IIS:\SslBindings\0.0.0.0!443 | Remove-Item