Automate direct domain enrollment across Windows versions

This commit is contained in:
2026-09-11 17:34:19 -06:00
parent 7f8a9eed4e
commit 520b4be955
23 changed files with 1244 additions and 108 deletions
+27 -11
View File
@@ -7,7 +7,8 @@ param(
[string]$DeploymentPrefix = 'sgu-lab',
[Parameter(Mandatory)][string]$AdministratorUsername,
[securestring]$AdministratorPassword,
[Parameter(Mandatory)][string]$P2sRootCertificatePath,
[string]$P2sRootCertificatePath,
[bool]$DeployVpnGateway = $true,
[string]$ComputerName = 'SGU-DC01',
[string]$VmSize = 'Standard_D2s_v5',
[string]$VirtualNetworkAddressPrefix = '10.77.0.0/16',
@@ -15,6 +16,7 @@ param(
[ipaddress]$DomainControllerPrivateIp = '10.77.0.4',
[string]$GatewaySubnetPrefix = '10.77.255.0/27',
[string]$VpnClientAddressPoolPrefix = '172.30.0.0/24',
[string[]]$PublicEnrollmentSourceAddressPrefixes = @(),
[string]$AdministratorSourceAddressPrefix = '',
[string]$TemplateFile = (Join-Path $PSScriptRoot '..\infra\azure\main.bicep')
)
@@ -28,20 +30,24 @@ if (-not (Get-Command az -ErrorAction SilentlyContinue)) {
if (-not (Test-Path -LiteralPath $TemplateFile -PathType Leaf)) {
throw "Azure Bicep template not found: $TemplateFile"
}
if (-not (Test-Path -LiteralPath $P2sRootCertificatePath -PathType Leaf)) {
throw "P2S root certificate not found: $P2sRootCertificatePath"
}
if (-not $AdministratorPassword) {
$AdministratorPassword = Read-Host 'Password for the local Azure VM administrator' -AsSecureString
}
$rootCertificate = [Security.Cryptography.X509Certificates.X509Certificate2]::new(
(Resolve-Path -LiteralPath $P2sRootCertificatePath).Path)
if (-not ($rootCertificate.Extensions | Where-Object {
$_.Oid -and $_.Oid.Value -eq '2.5.29.19' -and $_.Format($false) -match 'CA' })) {
throw 'P2sRootCertificatePath must contain a certificate-authority certificate.'
$rootCertificateData = ''
if ($DeployVpnGateway) {
if (-not $P2sRootCertificatePath -or
-not (Test-Path -LiteralPath $P2sRootCertificatePath -PathType Leaf)) {
throw 'P2sRootCertificatePath is required when DeployVpnGateway is true.'
}
$rootCertificate = [Security.Cryptography.X509Certificates.X509Certificate2]::new(
(Resolve-Path -LiteralPath $P2sRootCertificatePath).Path)
if (-not ($rootCertificate.Extensions | Where-Object {
$_.Oid -and $_.Oid.Value -eq '2.5.29.19' -and $_.Format($false) -match 'CA' })) {
throw 'P2sRootCertificatePath must contain a certificate-authority certificate.'
}
$rootCertificateData = [Convert]::ToBase64String($rootCertificate.RawData)
}
$rootCertificateData = [Convert]::ToBase64String($rootCertificate.RawData)
$account = & az account show --output json 2>$null
if ($LASTEXITCODE -ne 0) {
@@ -52,7 +58,13 @@ if ($LASTEXITCODE -ne 0) {
throw "Could not select Azure subscription $SubscriptionId."
}
if ($PSCmdlet.ShouldProcess("$ResourceGroupName in $Location", 'Create Azure VNet, Windows Server 2025 VM, public IP, and P2S VPN Gateway')) {
$deploymentDescription = if ($DeployVpnGateway) {
'Create Azure VNet, Windows Server 2025 VM, public IP, and P2S VPN Gateway'
}
else {
'Create Azure VNet, Windows Server 2025 VM, and public IP for direct enrollment'
}
if ($PSCmdlet.ShouldProcess("$ResourceGroupName in $Location", $deploymentDescription)) {
& az group create --name $ResourceGroupName --location $Location --only-show-errors --output none
if ($LASTEXITCODE -ne 0) {
throw "Could not create or update resource group $ResourceGroupName."
@@ -89,7 +101,9 @@ if ($PSCmdlet.ShouldProcess("$ResourceGroupName in $Location", 'Create Azure VNe
gatewaySubnetPrefix = @{ value = $GatewaySubnetPrefix }
domainControllerPrivateIp = @{ value = $DomainControllerPrivateIp.IPAddressToString }
vpnClientAddressPoolPrefix = @{ value = $VpnClientAddressPoolPrefix }
deployVpnGateway = @{ value = $DeployVpnGateway }
p2sRootCertificateData = @{ value = $rootCertificateData }
publicEnrollmentSourceAddressPrefixes = @{ value = @($PublicEnrollmentSourceAddressPrefixes) }
administratorSourceAddressPrefix = @{ value = $AdministratorSourceAddressPrefix }
}
}
@@ -135,6 +149,8 @@ if ($PSCmdlet.ShouldProcess("$ResourceGroupName in $Location", 'Create Azure VNe
DomainControllerPublicIp = $values.domainControllerPublicIp
VpnGatewayName = $values.vpnGatewayName
VpnClientAddressPoolPrefix = $values.vpnClientAddressPoolPrefix
DeployVpnGateway = $DeployVpnGateway
PublicEnrollmentSourceAddressPrefixes = @($PublicEnrollmentSourceAddressPrefixes)
ServerBootstrapArguments = $values.serverBootstrapArguments
}
}