使用 Win-ACME 來更新憑證
以下 Script 基於僅有兩台 RDWeb/Gateway 角色合一的 FrontEnd Server
僅做到將憑證更新完畢匯入系統,派送新的 RDCB 憑證指紋 (Thumbprints) 參考這篇文章
環境預設禁止 RDWeb/Gateway 主機主動對 Internet 連線
也禁止 Internet 對 RDWeb/Gateway 的 TCP Port 80 連線
因此開始 Renew 之前會先打開防火牆,此外也會先更新 TrustedRootCA
由於此例將 RDWeb、RDGateway、RDCB 全部都用公開憑證
所以必須要將 RDCB HA URL 的 Internet IP 也指到 RDWeb / RDGateway 這台上讓外網連線
實際上 RDCB 不需要對外,所以外網 DNS 對應哪個 IP 沒差
- 2020.06.10 Updated
- Script 最後將憑證指紋寫入 Thumbprint.txt 檔存放在 RDWeb 的 wwwroot
這樣就可以另外寫一隻 Script 以 http get 的方式抓取 寫入 GPO - 另外,為了彌補 GPO 更新的時間差
在憑證即將到期的 15 日內,且為周六或周日
才執行 RDS 系統更新憑證的指令
# -----------------
# Configuration
$WACSPath = "C:\Cert\"
$WACSEXEFileName = "wacs.exe"
$PFXPath = ($WACSPath + "Cert\")
$RDWebGWURL = "Contoso.com"
$RDCBHAURL = "RDCB.Contoso.com"
$DefaultActivedRDCBMaster = "RDCB-01.Contoso.com"
$TrustedRootCAPath = ($WACSPath + "TrustedRootCA\")
$TrustedRootCAFile = "roots.sst"
$BlockIPs = @("1.0.0.0-9.255.255.255", "11.0.0.0-172.15.255.255", "172.33.0.0-192.167.255.255", "192.169.0.0-255.255.255.255")
# Get Password SecureString by the following Command
# ConvertFrom-SecureString -SecureString (Read-Host -AsSecureString) -Key (1..16)
$CertPasswordPlain = "Password SecureString"
$CertPassword = ConvertTo-SecureString -String $CertPasswordPlain -Key (1..16)
# Assume this Script run on RDWeb-01.Contoso.com
$SecondRDWebGW = "RDWeb-02.Contoso.com"
$SecondRDWebGWAdmin = "Administrator"
$SecondRDWebGWPasswordPlain = "Password SecureString"
$SecondRDWebGWPassword = ConvertTo-SecureString -String $SecondRDWebGWPasswordPlain -Key (1..16)
# -----------------
# Make Sure Cert Working Path Exists
if (-not ( Test-Path -Path 'C:\Cert' -PathType Container )) {
md "C:\Cert"
};
if (-not ( Test-Path -Path (('\\' + $SecondRDWebGW + '\' + $WACSPath) -Replace 'C:','C$') -PathType Container )) {
md (('\\' + $SecondRDWebGW + '\' + $WACSPath) -Replace 'C:','C$')
};
if (-not ( Test-Path -Path 'C:\Cert\TrustedRootCA' -PathType Container )) {
md "C:\Cert\TrustedRootCA"
};
if (-not ( Test-Path -Path (('\\' + $SecondRDWebGW + '\' + $TrustedRootCAPath) -Replace 'C:','C$') -PathType Container )) {
md (('\\' + $SecondRDWebGW + '\' + $TrustedRootCAPath) -Replace 'C:','C$')
};
# -----------------
# Change Path to WACS Path
Set-Location -Path $WACSPath
# -----------------
# Start Logging
$DateTimeString = Get-Date -format ("yyyyMMdd HHmmss")
$TranscriptLog = (Get-Item -Path ".\" -Verbose).FullName + "\Logs\" + ("WACS " + $DateTimeString + ".log")
start-transcript -path $TranscriptLog
# -----------------
# Allow Programs to Connect to Internet
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' UnBlock Programs Connecting to Internet')
$RemovePrepare = New-NetFirewallRule -DisplayName "RemovePrepare" -Group "Block Connection To Internet" -Direction Outbound -Action Block -RemoteAddress $BlockIPs
$RemoveFirewallRule = Remove-NetFirewallRule -Group "Block Connection To Internet" -Confirm:$False
# -----------------
# Update Trusted Root CA
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Downloading Trusted Root CA')
if (Test-Path ($TrustedRootCAPath + $TrustedRootCAFile) -PathType Leaf) {
Remove-Item ($TrustedRootCAPath + $TrustedRootCAFile)
};
Start-Process -wait -FilePath "C:\Windows\System32\certutil.exe" -ArgumentList ('-generateSSTFromWU ' + ($TrustedRootCAPath + $TrustedRootCAFile))
if (-not (Test-Path ($TrustedRootCAPath + $TrustedRootCAFile) -PathType Leaf)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Can not Update Trusted Root CA')
Stop-Transcript
exit;
};
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updating Local Trusted Root CA')
$UpdateTrustedRootCA = (Get-ChildItem -Path ($TrustedRootCAPath + $TrustedRootCAFile)) | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root
copy-item ($TrustedRootCAPath + $TrustedRootCAFile) (('\\' + $SecondRDWebGW + '\' + ($TrustedRootCAPath + $TrustedRootCAFile)) -Replace 'C:','C$')
# -----------------
# Update Trusted Root CA for Second RDWebGW Server
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updating Remote Trusted Root CA')
$Command = {
param($TrustedRootCAPath,$TrustedRootCAFile)
$UpdateTrustedRootCA = (Get-ChildItem -Path ($TrustedRootCAPath + $TrustedRootCAFile)) | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root
}
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $SecondRDWebGWAdmin,$SecondRDWebGWPassword
Invoke-Command -ComputerName $SecondRDWebGW -ArgumentList $TrustedRootCAPath,$TrustedRootCAFile -ScriptBlock $Command -credential $Cred
# -----------------
# Allow TCP Port 80 Connection From Internet
$RemovePrepare = New-NetFirewallRule -DisplayName "RemovePrepare" -Group "TCP80BlockFromInternet" -Direction Inbound -Action Block -RemoteAddress $BlockIPs
$RemoveFirewallRule = Remove-NetFirewallRule -Group "TCP80BlockFromInternet" -Confirm:$False
# -----------------
# Allow TCP Port 80 Connection From Internet for Second RDWebGW Server
$Command = {
$RemovePrepare = New-NetFirewallRule -DisplayName "RemovePrepare" -Group "TCP80BlockFromInternet" -Direction Inbound -Action Block -RemoteAddress $BlockIPs
$RemoveFirewallRule = Remove-NetFirewallRule -Group "TCP80BlockFromInternet" -Confirm:$False
}
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $SecondRDWebGWAdmin,$SecondRDWebGWPassword
Invoke-Command -ComputerName $SecondRDWebGW -ScriptBlock $Command -credential $Cred
# -----------------
# Start Syncing RDWeb-01 and RDWeb-02
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Start Sync')
$SyncBatchProcess = Start-Process -passthru -FilePath "$env:comspec" -ArgumentList '/C C:\Cert\Sync.bat'
# -----------------
# Renew Cert with Let's Encrypy
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Start WACS')
Start-Process -wait -NoNewWindow -FilePath "$env:comspec" -ArgumentList ('/C ' + $WACSPath + $WACSEXEFileName + ' --renew --baseuri "https://acme-v02.api.letsencrypt.org/"')
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' End WACS')
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' End Sync')
$CheckSyncProcessAlive = Get-Process -ID $SyncBatchProcess.Id -ErrorAction SilentlyContinue
if ($CheckSyncProcessAlive -ne $null) {
Stop-Process -ID $SyncBatchProcess.Id -Force
}
# -----------------
# Block Programs Connecting to Internet
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Add Firewall Rule Back')
$AddFirewallRuleBack = New-NetFirewallRule -DisplayName "Block Connection To Internet" -Group "Block Connection To Internet" -Direction Outbound -Action Block -RemoteAddress $BlockIPs
# -----------------
# Block TCP Port 80 Connection From Internet
$AddFirewallRuleBack = New-NetFirewallRule -DisplayName "TCP80BlockFromInternet" -Group "TCP80BlockFromInternet" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Block -RemoteAddress $BlockIPs
# -----------------
# Block TCP Port 80 Connection From Internet for Second RDWebGW Server
$Command = {
param($BlockIPs)
$AddFirewallRuleBack = New-NetFirewallRule -DisplayName "TCP80BlockFromInternet" -Group "TCP80BlockFromInternet" -Direction Inbound -LocalPort 80 -Protocol TCP -Action Block -RemoteAddress $BlockIPs
}
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $SecondRDWebGWAdmin,$SecondRDWebGWPassword
Invoke-Command -ComputerName $SecondRDWebGW -ArgumentList $BlockIPs -ScriptBlock $Command -credential $Cred
# -----------------
# Check New Cert and Old Cert
Import-Module RemoteDesktopServices
$WebGWPFXFullPath = "$PFXPath$RDWebGWURL.pfx"
$RDCBPFXFullPath = "$PFXPath$RDCBHAURL.pfx"
if (-not (Test-Path $WebGWPFXFullPath -PathType Leaf)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + $WebGWPFXFullPath + ' Not Exist.')
Stop-Transcript
exit;
};
if (-not (Test-Path $RDCBPFXFullPath -PathType Leaf)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + $RDCBPFXFullPath + ' Not Exist.')
Stop-Transcript
exit;
};
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Get Actived RDCB Server')
$ActiveRDCBMaster = $(Get-RDConnectionBrokerHighAvailability -ConnectionBroker $DefaultActivedRDCBMaster).ActiveManagementServer
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + 'Active RDCB Server is ' + $ActiveRDCBMaster)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Get New Cert Properties')
$NewRDWebGWCertProperties = $(Get-PfxData -FilePath $WebGWPFXFullPath -Password $CertPassword).EndEntityCertificates | Select Thumbprint,NotAfter
$NewRDCBCertProperties = $(Get-PfxData -FilePath $RDCBPFXFullPath -Password $CertPassword).EndEntityCertificates | Select Thumbprint,NotAfter
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Get Old Cert Properties')
$LastRDWebAccessCertProperties = Get-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDWebAccess | Select Thumbprint,ExpiresOn
$LastRDGatewayCertProperties = Get-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDGateway | Select Thumbprint,ExpiresOn
$LastRDRedirectorCertProperties = Get-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDRedirector | Select Thumbprint,ExpiresOn
$LastRDPublishingCertProperties = Get-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDPublishing | Select Thumbprint,ExpiresOn
$NewRDWebGWCertThumbprint = $NewRDWebGWCertProperties.Thumbprint
$NewRDWebGWCertExpireDateTime = $NewRDWebGWCertProperties.NotAfter
$LastRDWebAccessCertThumbprint = $LastRDWebAccessCertProperties.Thumbprint
$LastRDWebAccessCertExpireDateTime = $LastRDWebAccessCertProperties.ExpiresOn
$LastRDGatewayCertThumbprint = $LastRDGatewayCertProperties.Thumbprint
$LastRDGatewayCertExpireDateTime = $LastRDGatewayCertProperties.ExpiresOn
$NewRDCBCertThumbprint = $NewRDCBCertProperties.Thumbprint
$NewRDCBCertExpireDateTime = $NewRDCBCertProperties.NotAfter
$LastRDRedirectorCertThumbprint = $LastRDRedirectorCertProperties.Thumbprint
$LastRDRedirectorCertExpireDateTime = $LastRDRedirectorCertProperties.ExpiresOn
$LastRDPublishingCertThumbprint = $LastRDPublishingCertProperties.Thumbprint
$LastRDPublishingCertExpireDateTime = $LastRDPublishingCertProperties.ExpiresOn
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDWebGW Cert Thumbprint is: ' + $NewRDWebGWCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDWebGW Cert ExpireDateTime is: ' + $NewRDWebGWCertExpireDateTime)
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDWebAccess Cert Thumbprint is: ' + $LastRDWebAccessCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDWebAccess Cert ExpireDateTime is: ' + $LastRDWebAccessCertExpireDateTime)
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDGateway Cert Thumbprint is: ' + $LastRDGatewayCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDGateway Cert ExpireDateTime is: ' + $LastRDGatewayCertExpireDateTime)
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDCB Cert Thumbprint is: ' + $NewRDCBCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDCB Cert ExpireDateTime is: ' + $NewRDCBCertExpireDateTime)
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDRedirector Cert Thumbprint is: ' + $LastRDRedirectorCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDRedirector Cert ExpireDateTime is: ' + $LastRDRedirectorCertExpireDateTime)
write-host
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDPublishing Cert Thumbprint is: ' + $LastRDPublishingCertThumbprint)
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Last RDPublishing Cert ExpireDateTime is: ' + $LastRDPublishingCertExpireDateTime)
write-host
if (($NewRDWebGWCertExpireDateTime -le $LastRDWebAccessCertExpireDateTime) -or ($NewRDWebGWCertExpireDateTime -le $LastRDGatewayCertExpireDateTime)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDWebGW Certs ExpireDate is Less than or equal to the old one, Please check.')
Stop-Transcript
exit;
}
if (($NewRDWebGWCertThumbprint -eq $LastRDWebAccessCertThumbprint) -or ($NewRDWebGWCertThumbprint -eq $LastRDGatewayCertThumbprint)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' RDWebGW Cert Doesnt Change, Program Close, Please check.')
Stop-Transcript
exit;
}
if (($NewRDCBCertExpireDateTime -le $LastRDRedirectorCertExpireDateTime) -or ($NewRDCBCertExpireDateTime -le $LastRDPublishingCertExpireDateTime)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' New RDCB Certs ExpireDate is Less than or equal to the old one, Please check.')
Stop-Transcript
exit;
}
if (($NewRDCBCertThumbprint -eq $LastRDRedirectorCertThumbprint) -or ($NewRDCBCertThumbprint -eq $LastRDPublishingCertThumbprint)) {
write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' RDCB Cert Does not Change, Program Close, Please check.')
Stop-Transcript
exit;
}
# ----------------- # Output Thumbprint to Text File for use of GPO Updating $ThumbprintOutput = $LastRDPublishingCertThumbprint; if ($NewRDCBCertThumbprint -ne $LastRDPublishingCertThumbprint) { $ThumbprintOutput += (',' + $NewRDCBCertThumbprint) }; $ThumbprintFileFullPath = "C:\inetpub\wwwroot\Thumbprint.txt" $ThumbprintOutput | Out-File -Encoding ASCII -FilePath $ThumbprintFileFullPath -Force $ThumbprintFileFullPath = ('\\' + $SecondRDWebGW + '\C$\inetpub\wwwroot\Thumbprint.txt') $ThumbprintOutput | Out-File -Encoding ASCII -FilePath ('\\' + $SecondRDWebGW + '\C$\inetpub\wwwroot\Thumbprint.txt') -Force # ----------------- # Replace Cert if it is Sunday or Saturday and the Cert will be Expired in 15 days if ( (([Int](Get-Date).DayOfWeek) -eq 0) -or (([Int](Get-Date).DayOfWeek) -eq 6) ) { write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' It is ' + (Get-Date).DayOfWeek + '~') if ( ($(New-TimeSpan –Start (Get-Date) –End $LastRDWebAccessCertExpireDateTime).Days -lt 15) -and ($(New-TimeSpan –Start (Get-Date) –End $LastRDRedirectorCertExpireDateTime).Days -lt 15) ) { write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updateing RDWebAccess Cert.') Set-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDWebAccess -ImportPath $WebGWPFXFullPath -Password $CertPassword -Force write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updateing RDGateway Cert.') Set-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDGateway -ImportPath $WebGWPFXFullPath -Password $CertPassword -Force write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updateing RDRedirector Cert.') Set-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDRedirector -ImportPath $RDCBPFXFullPath -Password $CertPassword -Force write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' Updateing RDPublishing Cert.') Set-RDCertificate -ConnectionBroker $ActiveRDCBMaster -Role RDPublishing -ImportPath $RDCBPFXFullPath -Password $CertPassword -Force write-host ($(Get-Date -format ("yyyy.MM.dd HH:mm:ss")) + ' All Set!') }; }; Stop-Transcript exit;
沒有留言:
張貼留言