Назначение SSL-сертификата IIS для привязки с заголовком узла с помощью PowerShell
Я пытаюсь назначить сертификат привязке HTTPS. К сожалению, я получаю эту ошибку от PowerShell:
new-item : Cannot create a file when that file already exists
At line:3 char:56
+ get-item -Path "cert:localmachinemy$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:LocalMachineMy | where-Object {$_.subject -like "*cloud.domain.com*"} | Select-Object -ExpandProperty Thumbprint
get-item -Path "cert:localmachinemy$cert" | new-item -path IIS:SslBindings.0.0.0!443!$Name.domain.com
похоже, что он может найти сертификат, но не может назначить его созданной привязке. Привязка создается с правильным IP / Port / HostHeader, SNI проверяется, но SSL-сертификат "не выбран"
все это отлично работает с IIS Manager
Я пробовал различные инструкции от SO и других сайтов, e.g.:
http://technet.microsoft.com/en-us/magazine/jj871065.aspx
оснастка Powershell IIS7 назначает SSL-сертификат привязке https
Powershell-добавить привязку SSL с помощью общего сертификата
кроме того, я пробовал с
IIS:SslBindings.0.0.0!443!$Name.domain.com
и
IIS:SslBindings.0.0.0!443
сертификат имеет предмет cloud.domain.com и несколько SAN атрибуты, например для **.domain.com*,domain.com, **.seconddomain.com*,seconddomain.com, cloud.domain.com
Edit:
сейчас я использую этот подход, который работает:
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"
меня все еще интересует решение без netsh
/ appcmd
7 ответов
вот как я смог создать самозаверяющий сертификат для 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")
сейчас я использую этот подход, который работает:
$guid = [guid]::NewGuid().ToString("B")
netsh http add sslcert hostnameport=$Name.domain.com:443 certhash=b58e54ca68c94f93c134c5da00a388ab0642a648 certstorename=MY appid="$guid"
Я не знаком с 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!443!$Name.domain.com -Force
я столкнулся с некоторыми проблемами с 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
приведенный ниже метод работал для меня:
после добавления новой конфигурации ssl в http.sys добавьте новую привязку к веб-сайту с SslFlags, установленным в 1, как показано ниже
-
добавить новую привязку в http.sys
* * $guid = [guid]:: NewGuid().ToString ("B")
$certHash = (GCI Cert:\LocalMachine\My | where {$_.Тема-совпадение "CN\=TestSSLBinding"} / Select-First 1).Отпечаток
netsh http добавить sslcert hostnameport=TestsslBinding: 443 certhash="$certHash "certstorename=MY appid= "$guid"**
-
добавить новую привязку к веб-сайту с помощью New-WebBinding
New-WebBinding-Name TestWebsite-протокол https-порт 443-HostHeader TestsslBinding-IPAddress 192.168.1.108 -SslFlags 1
настройка существующего SSL-сертификата на веб-сайте IIS, который использует hostheader
основываясь на ответе @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:
new-item: не удается создать файл, когда этот файл уже существует
падение 0.0.0.0!443
привязка заранее исправляет это для меня:
Get-Item IIS:\SslBindings.0.0.0!443 | Remove-Item
FYI: вот сценарий Powershell, который я сделал для массового назначения сертификата подстановочного знака сайтам, использующим заголовки хостов SNI/SSL без явных Привязок IP, и где понятное имя нового сертификата похоже *.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!443 | Remove-Item
ссылки, используемые при создании этого скрипта: