在多个 Windows Server 2016+ 端点上批量安装新证书

在多个 Windows Server 2016+ 端点上批量安装新证书

多年来,我一直不情愿地手动更新我们购买的通配符证书,现在我已经受够了,因为我有 100 多个 Web 和客户端服务器。这些服务器大多是独立的,分布在几个不同的域中,但有几个正在运行的服务器场可能会让这至少对那些少数服务器来说更容易。

所有操作系统均为 Windows Server 2016 和 2019。

我目前的流程是,在每个证书有效期结束时,从我的内部管理箱中购买新的(续订)证书并完成 CSR,然后以 .pfx 格式导出证书,并在每台服务器上手动安装它个人商店. 在 Web 服务器上 (互联网信息服务)我也手动修改了绑定。

我知道如果我使用域中生成的证书,我只需在每个域中使用 AD CA 即可将它们推送出去,但根据我的研究,我找不到一种方法来推出我们从供应商处购买

我还看到 GPO 至少可能是在服务器上获取证书的答案 - 对我来说,设置项目级定位或将所有 Web 服务器放在每个域中的组或 OU 中并不难。我遇到的唯一问题是,我找不到使用此方法将证书放在个人商店,这是要求。

这里可能有不止一个“正确”的答案,但我想知道你们每年如何处理这个过程,所以请随意发表意见。如果这个社区之前已经回答过这个问题,我很抱歉,但我的搜索没有结果。

答案1

PowerShell 是你的朋友。

https://docs.microsoft.com/en-us/powershell/module/pki/import-pfxcertificate
https://docs.microsoft.com/en-us/powershell/module/iisadministration/remove-iissitebinding
https://docs.microsoft.com/en-us/powershell/module/iisadministration/new-iissitebinding

如果您具有所需的权限,则可以直接从网络路径 () 中提取 PFX 文件\\server\share\filename.pfx;如果您需要指定凭据,请使用新-PSDrive

您可以将所有内容放在一个脚本块中,然后使用以下命令在远程服务器上运行它调用命令;如果需要,您也可以在这里指定凭证。

当然,这可以在服务器列表上循环完成,例如

$serverlist = "server1","server2","server3"

foreach ($server in $serverlist)
{
    Invoke-Command -ComputerName $server -ScriptBlock
    {
        Import-PfxCertificate [...]
        Remove-IISSiteBinding [...]
        New-IISSiteBinding [...]
    }
}

如果你需要创建私人秘书凭证物体,看看这里

最后但同样重要的一点是,您可以使用以下方式从 CSV 文件中获取所需的一切(例如服务器名称、凭据、网站名称等)导入-Csv

答案2

大家好,

似乎我在这里用“ol PowerShell”争论了另一个问题。感谢@Massimo 让我朝着正确的方向前进。

到目前为止,下面的 PS 脚本对我来说非常完美。我在脚本中留下了注释,因此即使是最没有经验的牛仔/女牛仔也能非常清楚地理解。

注意事项:

  1. 这是以域管理员的身份从管理计算机运行的,该管理计算机的子网具有对所有其他段的 VLAN 访问权限。(我知道这听起来像是一场安全噩梦,但它受到全面审计和访问日志记录,并且在不使用时保持离线状态。)
  2. 这仅在 Windows Server 2016 和 2019 上进行了测试 - 如果它适用于 2016 以下的任何版本,那会感到惊讶。
  3. Windows Server 2016 默认为 IISAdmin 模块 1.0,但此脚本需要 1.1.0.0,因此我内置了从远程存储库下载/安装的功能。您可以随意删除以供自己使用,或自行决定使用它。
  4. 我选择将 .pfx 文件复制到每台机器,而不是从网络共享安装,因为这样可以简化流程(身份验证、循环、冗余等等)。不过,在脚本结束时,.pfx 会被删除。如果您的文件有复杂的密码,这应该没问题,但请自行决定。
  5. 该解决方案应用了新的证书和 IIS 绑定并为本地 SMTP 启用 TLS。
#Setup the vars below.  Yes, you gotta do some of the work...
$OldCertDirHash = 'Cert:\LocalMachine\My\1234567890QWERTYUIOPLKJHGFDSA' # Old/Expired cert's store path and hash ID
$NewCertHash = '0987654321POIUYTREWQASDFGHJKL' 
$NewCertSharePath = '\\FS01.foo.internal\ITStuff\SCENSATIVE\install\STAR.foo.com_2022.pfx' # PFX file's shared location on the network
$CertPass = Get-Credential -UserName 'Type PFX password below' -Message 'Enter password below' #Stores PXF's password obscurely
$IISSiteName = 'Default Web Site' #Website's name for new binding
$ADCPUs = Get-ADComputer -Filter * -SearchBase "OU=Testing Lab,OU=Web Servers,DC=Foo,DC=com" |  select-object -expandproperty name  #Target machines in AD using an OU's Distinguished Name
$NetworkPFXPath = 'C$\Temp\Certs' #Network path for each remote machine
$LocalPXFPath = 'C:\temp\Certs\STAR.foo.com_2022.pfx'  #Path were the .pxf file will be accessed locally on each machine


ForEach ($ADCPU in $ADCPUs)
{Write-Host Copying file $NewCertSharePath to $ADCPU $NetworkPFXPath -ForegroundColor Yellow
New-Item -Path \\$ADCPU\$NetworkPFXPath -ItemType Directory #Creates local folder on each remote machine
Copy-Item -Path $NewCertSharePath -Destination \\$ADCPU\$NetworkPFXPath # Copies pfx file from network to each remote machine's local folder
}


# ~~~ End of Setup. Magic happens below ~~~


ForEach  ($ADCPU in $ADCPUs)
  {
Write-Host $ADCPU -ForegroundColor Yellow # Highlights Server names while in process
Invoke-Command -ComputerName $ADCPU -ScriptBlock { 

#Get latest IISAdmin version from online repo with suppressed dialog
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name IISAdministration -RequiredVersion 1.1.0.0 -SkipPublisherCheck -Confirm:$False -Force

#The default IISAdmin version for server 2016 is 1.0 - below brings it up to the required version which was installed above.       
Import-Module IISAdministration -Version 1.1.0.0

#This line installs the cert from the .pfx using the password set earlier into the Computer's Personal cert store.
Import-PfxCertificate -FilePath $Using:LocalPXFPath -CertStoreLocation Cert:\LocalMachine\My -Password $Using:CertPass.Password -ErrorAction Inquire

#Use below if importing .crt rather than .pfx ~ Not in use here ~
        #Import-Certificate -FilePath "UNCPath" -CertStoreLocation Cert:\LocalMachine\My -ErrorAction Inquire

#Clear out any other active or pending IIS Server Manager tasks - prevents config file collision.        
Reset-IISServerManager -Confirm:$false

#Remove current HTTPS binding using old/expired cert
Remove-IISSiteBinding -Name 'Default Web Site' -BindingInformation '*:443:' -Protocol https -Confirm:$false

#Delete expired cert - not required but is good houskeeping
Get-ChildItem $Using:OldCertDirHash | Remove-Item -ErrorAction Ignore

#Delete Cert by subject,serialnumber,issuer,etc... ~ Not in use here. ~
#Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.FriendlyName -match '*.foo.com_2021' } | Remove-Item

#Setup https binding on 443 using new cert
New-IISSiteBinding -Name $Using:IISSiteName -BindingInformation "*:443:" -CertificateThumbPrint $Using:NewCertHash -CertStoreLocation "Cert:\LocalMachine\My" -Protocol https 

IISRESET #for obvious reasons...

Remove-Item -Path $Using:LocalPXFPath -Recurse -Verbose  #Cleanup the dir created to store the pfx file

Write-Host $ADCPU Done -ForegroundColor Green #This is more of a marker for reviewing output and would be helpful if writing to log/oputfile
    }
    
  }

抱歉发了这么长的帖子,但这是解决我的问题的有力而彻底的解决方案。为了解决这个问题,我下班后多喝了几杯。如果这个方法对你有用,请随意给我送一杯饮料!

相关内容