Add self-hosted RustDesk bootstrap management

This commit is contained in:
2026-09-07 17:29:25 -06:00
parent b3ec649199
commit 675db6bc1e
14 changed files with 1068 additions and 8 deletions
@@ -10,6 +10,7 @@ param(
[string]$DomainName = 'lci.lasalle.mx',
[string]$DomainNetbios = 'LCI',
[string]$BrokerRecordName = 'sgu-auth',
[string]$RustDeskRecordName = 'rustdesk',
[string]$PackageSharePath = 'C:\Packages',
[securestring]$SafeModeAdministratorPassword,
[switch]$SkipRestart,
@@ -313,6 +314,7 @@ if ($Resume -or (-not $ServerIPv4Address -and $existingState)) {
$DomainName = [string]$existingState.DomainName
$DomainNetbios = [string]$existingState.DomainNetbios
$BrokerRecordName = [string]$existingState.BrokerRecordName
$RustDeskRecordName = if ($existingState.RustDeskRecordName) { [string]$existingState.RustDeskRecordName } else { $RustDeskRecordName }
$PackageSharePath = [string]$existingState.PackageSharePath
}
@@ -336,6 +338,7 @@ else {
$NetworkInterfaceAlias = Resolve-PrivateInterfaceAlias -RequestedAlias $NetworkInterfaceAlias
$baseDn = Get-DomainBaseDn -DnsDomainName $DomainName
$brokerDnsName = "$BrokerRecordName.$DomainName"
$rustDeskDnsName = "$RustDeskRecordName.$DomainName"
$stagedScriptPath = Join-Path $bootstrapRoot 'Initialize-SguDomainController.ps1'
$scriptsRoot = Join-Path $bootstrapRoot 'payload\scripts'
$brokerPublishPath = Join-Path $bootstrapRoot 'payload\broker'
@@ -349,9 +352,13 @@ foreach ($requiredPath in @(
(Join-Path $scriptsRoot 'Set-SguDomainUserPolicies.ps1'),
(Join-Path $scriptsRoot 'Enable-SguServerRemoteManagement.ps1'),
(Join-Path $scriptsRoot 'Install-SguDomainMonitoring.ps1'),
(Join-Path $scriptsRoot 'Install-SguRustDeskClient.ps1'),
(Join-Path $scriptsRoot 'Install-SguRustDeskServer.ps1'),
(Join-Path $scriptsRoot 'Invoke-SguMonitoringMaintenance.ps1'),
(Join-Path $scriptsRoot 'Get-SguRustDeskDevice.ps1'),
(Join-Path $scriptsRoot 'Get-SguUsageReport.ps1'),
(Join-Path $scriptsRoot 'Get-SguBrokerLog.ps1'),
(Join-Path $scriptsRoot 'Register-SguRustDeskDevice.ps1'),
(Join-Path $brokerPublishPath 'SGU.AuthBroker.exe'))) {
if (-not (Test-Path -LiteralPath $requiredPath -PathType Leaf)) {
throw "The server bootstrap package is incomplete: $requiredPath"
@@ -378,6 +385,7 @@ if (-not $existingState) {
DomainName = $DomainName
DomainNetbios = $DomainNetbios
BrokerRecordName = $BrokerRecordName
RustDeskRecordName = $RustDeskRecordName
PackageSharePath = $PackageSharePath
}
[IO.File]::WriteAllText(
@@ -516,6 +524,10 @@ if (-not $remoteDesktopGroup) {
-RecordName $BrokerRecordName `
-IPv4Address $ServerIPv4Address `
-ExternalForwarders $DnsForwarders | Out-Null
& (Join-Path $scriptsRoot 'Set-LabBrokerDns.ps1') `
-ZoneName $DomainName `
-RecordName $RustDeskRecordName `
-IPv4Address $ServerIPv4Address | Out-Null
$certificateDirectory = Join-Path $bootstrapRoot 'certificates'
$serverCertificate = Get-ChildItem Cert:\LocalMachine\My |
@@ -626,6 +638,32 @@ $userPolicyParameters = @{
}
& (Join-Path $scriptsRoot 'Set-SguDomainUserPolicies.ps1') @userPolicyParameters | Out-Null
$rustDeskServer = & (Join-Path $scriptsRoot 'Install-SguRustDeskServer.ps1') `
-ServerAddress $rustDeskDnsName `
-FirewallRemoteAddress $privateSubnet
$rustDeskManagementRoot = Join-Path $env:ProgramData 'SGU\RustDesk'
New-Item -ItemType Directory -Path $rustDeskManagementRoot -Force | Out-Null
foreach ($scriptName in @('Register-SguRustDeskDevice.ps1', 'Get-SguRustDeskDevice.ps1')) {
Copy-Item -LiteralPath (Join-Path $scriptsRoot $scriptName) `
-Destination (Join-Path $rustDeskManagementRoot $scriptName) -Force
}
$rustDeskServerClient = & (Join-Path $scriptsRoot 'Install-SguRustDeskClient.ps1') `
-ServerAddress $rustDeskDnsName `
-ServerPublicKey $rustDeskServer.PublicKey
$rustDeskPasswordPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR(
$rustDeskServerClient.AccessPassword)
try {
$rustDeskPassword = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($rustDeskPasswordPointer)
& (Join-Path $rustDeskManagementRoot 'Register-SguRustDeskDevice.ps1') `
-ComputerName $env:COMPUTERNAME `
-RustDeskId $rustDeskServerClient.RustDeskId `
-AccessPassword $rustDeskPassword | Out-Null
}
finally {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($rustDeskPasswordPointer)
$rustDeskPassword = $null
}
$validation = [ordered]@{
CompletedAt = (Get-Date).ToString('o')
ComputerName = $env:COMPUTERNAME
@@ -637,6 +675,12 @@ $validation = [ordered]@{
BrokerPortListening = [bool](Get-NetTCPConnection -LocalPort 8443 -State Listen -ErrorAction SilentlyContinue)
WinRM = (Get-Service WinRM).Status.ToString()
RemoteDesktop = (Get-Service TermService).Status.ToString()
RustDeskServerAddress = $rustDeskServer.ServerAddress
RustDeskHbbsTask = $rustDeskServer.HbbsTask
RustDeskHbbrTask = $rustDeskServer.HbbrTask
RustDeskHbbsListening = $rustDeskServer.HbbsListening
RustDeskHbbrListening = $rustDeskServer.HbbrListening
RustDeskServerClientId = $rustDeskServerClient.RustDeskId
EventCollector = (Get-Service Wecsvc).Status.ToString()
EventSubscription = @(& wecutil.exe enum-subscription) -contains 'SGU-Lab-Monitoring'
MonitoringRetentionDays = 183
@@ -652,6 +696,10 @@ if ($validation.BrokerService -ne 'Running' -or
-not $validation.BrokerPortListening -or
$validation.WinRM -ne 'Running' -or
$validation.RemoteDesktop -ne 'Running' -or
$validation.RustDeskHbbsTask -ne 'Running' -or
$validation.RustDeskHbbrTask -ne 'Running' -or
-not $validation.RustDeskHbbsListening -or
-not $validation.RustDeskHbbrListening -or
$validation.EventCollector -ne 'Running' -or
-not $validation.EventSubscription) {
throw 'Server finalization did not pass service validation. Review bootstrap.log and re-run the bootstrap.'