Automate direct domain enrollment across Windows versions
This commit is contained in:
+98
-15
@@ -34,6 +34,9 @@ param domainControllerSubnetPrefix string = '10.77.0.0/24'
|
||||
@description('Reserved Azure VPN Gateway subnet. Use /27 or larger.')
|
||||
param gatewaySubnetPrefix string = '10.77.255.0/27'
|
||||
|
||||
@description('Deploy the optional Azure Point-to-Site VPN Gateway. Direct public enrollment does not require it.')
|
||||
param deployVpnGateway bool = true
|
||||
|
||||
@description('Static private IP reserved on the Azure NIC for AD DS and DNS.')
|
||||
param domainControllerPrivateIp string = '10.77.0.4'
|
||||
|
||||
@@ -44,7 +47,10 @@ param vpnClientAddressPoolPrefix string = '172.30.0.0/24'
|
||||
param p2sRootCertificateName string = 'SGU-P2S-Root'
|
||||
|
||||
@description('Base64 DER bytes of the trusted P2S root certificate, without PEM markers.')
|
||||
param p2sRootCertificateData string
|
||||
param p2sRootCertificateData string = ''
|
||||
|
||||
@description('Public IPv4 CIDRs allowed to enroll clients directly without VPN. Leave empty to expose no AD enrollment ports.')
|
||||
param publicEnrollmentSourceAddressPrefixes array = []
|
||||
|
||||
@description('Optional public CIDR allowed to RDP to the VM public IP, for example 203.0.113.10/32. Leave empty to expose no management port.')
|
||||
param administratorSourceAddressPrefix string = ''
|
||||
@@ -63,7 +69,7 @@ resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2024-05-0
|
||||
name: networkSecurityGroupName
|
||||
location: location
|
||||
properties: {
|
||||
securityRules: concat([
|
||||
securityRules: concat(deployVpnGateway ? [
|
||||
{
|
||||
name: 'Allow-SGU-P2S-clients'
|
||||
properties: {
|
||||
@@ -78,11 +84,77 @@ resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2024-05-0
|
||||
description: 'AD, DNS, broker, monitoring, and RustDesk are reachable only through the authenticated P2S address pool.'
|
||||
}
|
||||
}
|
||||
] : [], empty(publicEnrollmentSourceAddressPrefixes) ? [] : [
|
||||
{
|
||||
name: 'Allow-Direct-AD-TCP'
|
||||
properties: {
|
||||
priority: 110
|
||||
access: 'Allow'
|
||||
direction: 'Inbound'
|
||||
protocol: 'Tcp'
|
||||
sourcePortRange: '*'
|
||||
destinationPortRanges: [
|
||||
'53'
|
||||
'88'
|
||||
'135'
|
||||
'389'
|
||||
'443'
|
||||
'445'
|
||||
'464'
|
||||
'636'
|
||||
'3268'
|
||||
'3269'
|
||||
'21115-21117'
|
||||
'49152-65535'
|
||||
]
|
||||
sourceAddressPrefixes: publicEnrollmentSourceAddressPrefixes
|
||||
destinationAddressPrefix: domainControllerPrivateIp
|
||||
description: 'AD, DoH, and RustDesk TCP access for explicitly authorized public enrollment networks.'
|
||||
}
|
||||
}
|
||||
{
|
||||
name: 'Allow-Direct-AD-UDP'
|
||||
properties: {
|
||||
priority: 120
|
||||
access: 'Allow'
|
||||
direction: 'Inbound'
|
||||
protocol: 'Udp'
|
||||
sourcePortRange: '*'
|
||||
destinationPortRanges: [
|
||||
'53'
|
||||
'88'
|
||||
'123'
|
||||
'389'
|
||||
'464'
|
||||
'21116'
|
||||
]
|
||||
sourceAddressPrefixes: publicEnrollmentSourceAddressPrefixes
|
||||
destinationAddressPrefix: domainControllerPrivateIp
|
||||
description: 'AD, time, and RustDesk UDP access for explicitly authorized public enrollment networks.'
|
||||
}
|
||||
}
|
||||
{
|
||||
name: 'Allow-Direct-SGU-Enrollment-TCP'
|
||||
properties: {
|
||||
priority: 130
|
||||
access: 'Allow'
|
||||
direction: 'Inbound'
|
||||
protocol: 'Tcp'
|
||||
sourcePortRange: '*'
|
||||
destinationPortRanges: [
|
||||
'5985'
|
||||
'8443'
|
||||
]
|
||||
sourceAddressPrefixes: publicEnrollmentSourceAddressPrefixes
|
||||
destinationAddressPrefix: domainControllerPrivateIp
|
||||
description: 'WinRM discovery and SGU broker access for direct enrollment.'
|
||||
}
|
||||
}
|
||||
], empty(administratorSourceAddressPrefix) ? [] : [
|
||||
{
|
||||
name: 'Allow-RDP-from-administrator'
|
||||
properties: {
|
||||
priority: 110
|
||||
priority: 140
|
||||
access: 'Allow'
|
||||
direction: 'Inbound'
|
||||
protocol: 'Tcp'
|
||||
@@ -106,7 +178,7 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-05-01' = {
|
||||
virtualNetworkAddressPrefix
|
||||
]
|
||||
}
|
||||
subnets: [
|
||||
subnets: concat([
|
||||
{
|
||||
name: domainControllerSubnetName
|
||||
properties: {
|
||||
@@ -116,13 +188,14 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-05-01' = {
|
||||
}
|
||||
}
|
||||
}
|
||||
], deployVpnGateway ? [
|
||||
{
|
||||
name: gatewaySubnetName
|
||||
properties: {
|
||||
addressPrefix: gatewaySubnetPrefix
|
||||
}
|
||||
}
|
||||
]
|
||||
] : [])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,9 +212,14 @@ resource domainControllerPublicIp 'Microsoft.Network/publicIPAddresses@2024-05-0
|
||||
}
|
||||
}
|
||||
|
||||
resource gatewayPublicIp 'Microsoft.Network/publicIPAddresses@2024-05-01' = {
|
||||
resource gatewayPublicIp 'Microsoft.Network/publicIPAddresses@2024-05-01' = if (deployVpnGateway) {
|
||||
name: gatewayPublicIpName
|
||||
location: location
|
||||
zones: [
|
||||
'1'
|
||||
'2'
|
||||
'3'
|
||||
]
|
||||
sku: {
|
||||
name: 'Standard'
|
||||
}
|
||||
@@ -223,6 +301,8 @@ resource virtualMachine 'Microsoft.Compute/virtualMachines@2024-07-01' = {
|
||||
}
|
||||
osDisk: {
|
||||
createOption: 'FromImage'
|
||||
// AD DS requires durable writes; the bootstrap stores NTDS on this disk.
|
||||
caching: 'None'
|
||||
managedDisk: {
|
||||
storageAccountType: 'Premium_LRS'
|
||||
}
|
||||
@@ -248,7 +328,7 @@ resource virtualMachine 'Microsoft.Compute/virtualMachines@2024-07-01' = {
|
||||
}
|
||||
}
|
||||
|
||||
resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2024-05-01' = {
|
||||
resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2024-05-01' = if (deployVpnGateway) {
|
||||
name: virtualNetworkGatewayName
|
||||
location: location
|
||||
properties: {
|
||||
@@ -271,8 +351,8 @@ resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2024-05
|
||||
}
|
||||
]
|
||||
sku: {
|
||||
name: 'VpnGw1'
|
||||
tier: 'VpnGw1'
|
||||
name: 'VpnGw1AZ'
|
||||
tier: 'VpnGw1AZ'
|
||||
}
|
||||
vpnClientConfiguration: {
|
||||
vpnClientAddressPool: {
|
||||
@@ -282,7 +362,7 @@ resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2024-05
|
||||
}
|
||||
vpnClientProtocols: [
|
||||
'IkeV2'
|
||||
'SSTP'
|
||||
'OpenVPN'
|
||||
]
|
||||
vpnAuthenticationTypes: [
|
||||
'Certificate'
|
||||
@@ -307,17 +387,20 @@ output domainControllerPrivateIp string = domainControllerPrivateIp
|
||||
output domainControllerPublicIp string = domainControllerPublicIp.properties.ipAddress
|
||||
output virtualNetworkName string = virtualNetwork.name
|
||||
output virtualNetworkAddressPrefix string = virtualNetworkAddressPrefix
|
||||
output vpnGatewayName string = virtualNetworkGateway.name
|
||||
output vpnGatewayName string = deployVpnGateway ? virtualNetworkGateway.name : ''
|
||||
output vpnClientAddressPoolPrefix string = vpnClientAddressPoolPrefix
|
||||
output serverBootstrapArguments array = [
|
||||
output serverBootstrapArguments array = concat([
|
||||
'-ServerIPv4Address'
|
||||
domainControllerPrivateIp
|
||||
'-PrefixLength'
|
||||
last(split(domainControllerSubnetPrefix, '/'))
|
||||
'-NetworkConfigurationMode'
|
||||
'PlatformManaged'
|
||||
'-TrustedClientNetworks'
|
||||
vpnClientAddressPoolPrefix
|
||||
'-DnsForwarders'
|
||||
'168.63.129.16'
|
||||
]
|
||||
], deployVpnGateway ? [
|
||||
'-TrustedClientNetworks'
|
||||
vpnClientAddressPoolPrefix
|
||||
] : [], empty(publicEnrollmentSourceAddressPrefixes) ? [] : concat([
|
||||
'-PublicEnrollmentNetworks'
|
||||
], publicEnrollmentSourceAddressPrefixes))
|
||||
|
||||
Reference in New Issue
Block a user