Configure private IPv4 during Windows enrollment
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
param(
|
||||
[ipaddress]$DomainControllerIPv4Address,
|
||||
[string]$NetworkInterfaceAlias,
|
||||
[ipaddress]$ClientIPv4Address,
|
||||
[ValidateRange(1, 32)]
|
||||
[int]$ClientPrefixLength = 24,
|
||||
[PSCredential]$DomainCredential,
|
||||
[string]$DomainName = 'lci.lasalle.mx',
|
||||
[string]$DomainNetbios = 'LCI',
|
||||
@@ -16,6 +19,7 @@ param(
|
||||
[securestring]$VpnClientCertificatePfxPassword,
|
||||
[string]$VpnClientRootCertificatePath,
|
||||
[string[]]$AzureNetworkPrefixes = @('10.77.0.0/16'),
|
||||
[switch]$PauseOnError,
|
||||
[switch]$SkipRestart
|
||||
)
|
||||
|
||||
@@ -24,6 +28,35 @@ $brokerRecordName = 'sgu-auth'
|
||||
$brokerDnsName = "$brokerRecordName.$DomainName"
|
||||
$brokerEndpoint = "https://${brokerDnsName}:8443/v1/authenticate"
|
||||
$temporaryRoot = Join-Path $env:ProgramData ("SGU\Bootstrap\Client-" + [Guid]::NewGuid().ToString('N'))
|
||||
$bootstrapLogRoot = Join-Path $env:ProgramData 'SGU\Bootstrap\Client'
|
||||
$bootstrapErrorLog = Join-Path $bootstrapLogRoot 'latest-error.log'
|
||||
|
||||
trap {
|
||||
$failure = $_
|
||||
$failureText = @(
|
||||
"SGU client enrollment failed at $((Get-Date).ToString('s')).",
|
||||
'',
|
||||
$failure.Exception.Message,
|
||||
'',
|
||||
$failure.ScriptStackTrace
|
||||
) -join [Environment]::NewLine
|
||||
try {
|
||||
New-Item -ItemType Directory -Path $bootstrapLogRoot -Force | Out-Null
|
||||
[IO.File]::WriteAllText($bootstrapErrorLog, $failureText, [Text.UTF8Encoding]::new($false))
|
||||
}
|
||||
catch {
|
||||
# Keep the original enrollment error when diagnostics cannot be written.
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'SGU client enrollment did not complete.' -ForegroundColor Red
|
||||
Write-Host $failure.Exception.Message -ForegroundColor Red
|
||||
Write-Host "Diagnostic log: $bootstrapErrorLog" -ForegroundColor Yellow
|
||||
if ($PauseOnError -and [Environment]::UserInteractive) {
|
||||
Read-Host 'Press ENTER to close this window' | Out-Null
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
function Assert-Administrator {
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
@@ -62,21 +95,119 @@ function Resolve-ClientInterfaceAlias {
|
||||
return $RequestedAlias
|
||||
}
|
||||
|
||||
$defaultRoute = Get-NetRoute -AddressFamily IPv4 -DestinationPrefix '0.0.0.0/0' `
|
||||
-ErrorAction SilentlyContinue |
|
||||
Sort-Object RouteMetric,InterfaceMetric |
|
||||
Select-Object -First 1
|
||||
if ($defaultRoute) {
|
||||
return [string](Get-NetAdapter -InterfaceIndex $defaultRoute.InterfaceIndex).Name
|
||||
}
|
||||
|
||||
$upAdapters = @(Get-NetAdapter | Where-Object Status -eq 'Up')
|
||||
$withoutDefaultGateway = @($upAdapters | Where-Object {
|
||||
-not (Get-NetIPConfiguration -InterfaceIndex $_.ifIndex).IPv4DefaultGateway
|
||||
})
|
||||
if ($withoutDefaultGateway.Count -eq 1) {
|
||||
return [string]$withoutDefaultGateway[0].Name
|
||||
}
|
||||
if ($upAdapters.Count -eq 1) {
|
||||
return [string]$upAdapters[0].Name
|
||||
}
|
||||
|
||||
$aliases = ($upAdapters.Name | Sort-Object) -join ', '
|
||||
throw "Could not select a network adapter. Re-run with -NetworkInterfaceAlias. Available adapters: $aliases"
|
||||
throw "Could not select the private domain adapter unambiguously. Re-run with -NetworkInterfaceAlias. Available adapters: $aliases"
|
||||
}
|
||||
|
||||
function Test-IPv4AddressesSharePrefix {
|
||||
param(
|
||||
[Parameter(Mandatory)][ipaddress]$FirstAddress,
|
||||
[Parameter(Mandatory)][ipaddress]$SecondAddress,
|
||||
[Parameter(Mandatory)][ValidateRange(1, 32)][int]$PrefixLength
|
||||
)
|
||||
|
||||
if ($FirstAddress.AddressFamily -ne [Net.Sockets.AddressFamily]::InterNetwork -or
|
||||
$SecondAddress.AddressFamily -ne [Net.Sockets.AddressFamily]::InterNetwork) {
|
||||
return $false
|
||||
}
|
||||
|
||||
$firstBytes = $FirstAddress.GetAddressBytes()
|
||||
$secondBytes = $SecondAddress.GetAddressBytes()
|
||||
$remainingBits = $PrefixLength
|
||||
for ($index = 0; $index -lt 4; $index++) {
|
||||
$bits = [Math]::Min(8, $remainingBits)
|
||||
$mask = if ($bits -eq 0) {
|
||||
0
|
||||
}
|
||||
elseif ($bits -eq 8) {
|
||||
255
|
||||
}
|
||||
else {
|
||||
256 - [int][Math]::Pow(2, 8 - $bits)
|
||||
}
|
||||
if (($firstBytes[$index] -band $mask) -ne ($secondBytes[$index] -band $mask)) {
|
||||
return $false
|
||||
}
|
||||
$remainingBits -= $bits
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
||||
function Assert-UsableClientIPv4Address {
|
||||
param(
|
||||
[Parameter(Mandatory)][ipaddress]$Address,
|
||||
[Parameter(Mandatory)][ipaddress]$DomainControllerAddress,
|
||||
[Parameter(Mandatory)][ValidateRange(1, 32)][int]$PrefixLength
|
||||
)
|
||||
|
||||
if ($Address.AddressFamily -ne [Net.Sockets.AddressFamily]::InterNetwork) {
|
||||
throw "The SGU client address '$Address' must be IPv4."
|
||||
}
|
||||
if ($Address.IPAddressToString -eq $DomainControllerAddress.IPAddressToString) {
|
||||
throw 'The SGU client and domain controller cannot use the same IPv4 address.'
|
||||
}
|
||||
if ($Address.IPAddressToString -match '^(0\.|127\.|169\.254\.|22[4-9]\.|23\d\.)') {
|
||||
throw "The SGU client address '$Address' is not usable on the private domain network."
|
||||
}
|
||||
if (-not (Test-IPv4AddressesSharePrefix -FirstAddress $Address `
|
||||
-SecondAddress $DomainControllerAddress -PrefixLength $PrefixLength)) {
|
||||
throw "The SGU client address '$Address/$PrefixLength' is not on the same network as domain controller $DomainControllerAddress."
|
||||
}
|
||||
}
|
||||
|
||||
function Set-ClientDomainAddress {
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$InterfaceAlias,
|
||||
[Parameter(Mandatory)][ipaddress]$DomainControllerAddress,
|
||||
[ipaddress]$RequestedAddress,
|
||||
[Parameter(Mandatory)][ValidateRange(1, 32)][int]$PrefixLength
|
||||
)
|
||||
|
||||
$adapter = Get-NetAdapter -Name $InterfaceAlias -ErrorAction Stop
|
||||
$matchingAddress = Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 `
|
||||
-ErrorAction SilentlyContinue |
|
||||
Where-Object {
|
||||
$_.IPAddress -notmatch '^(127\.|169\.254\.)' -and
|
||||
(Test-IPv4AddressesSharePrefix -FirstAddress ([ipaddress]$_.IPAddress) `
|
||||
-SecondAddress $DomainControllerAddress -PrefixLength $PrefixLength)
|
||||
} |
|
||||
Select-Object -First 1
|
||||
|
||||
if (-not $RequestedAddress -and $matchingAddress) {
|
||||
return [ipaddress]$matchingAddress.IPAddress
|
||||
}
|
||||
if (-not $RequestedAddress) {
|
||||
$RequestedAddress = [ipaddress](Read-Host "Fixed IPv4 address for this SGU client on '$InterfaceAlias'")
|
||||
}
|
||||
Assert-UsableClientIPv4Address -Address $RequestedAddress `
|
||||
-DomainControllerAddress $DomainControllerAddress -PrefixLength $PrefixLength
|
||||
|
||||
Set-NetIPInterface -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 -Dhcp Disabled
|
||||
$existingAddresses = @(Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 `
|
||||
-ErrorAction SilentlyContinue | Where-Object PrefixOrigin -ne 'WellKnown')
|
||||
foreach ($existingAddress in $existingAddresses) {
|
||||
if ($existingAddress.IPAddress -ne $RequestedAddress.IPAddressToString -or
|
||||
[int]$existingAddress.PrefixLength -ne $PrefixLength) {
|
||||
Remove-NetIPAddress -InputObject $existingAddress -Confirm:$false
|
||||
}
|
||||
}
|
||||
if (-not (Get-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 `
|
||||
-IPAddress $RequestedAddress.IPAddressToString -ErrorAction SilentlyContinue)) {
|
||||
New-NetIPAddress -InterfaceIndex $adapter.ifIndex -AddressFamily IPv4 `
|
||||
-IPAddress $RequestedAddress.IPAddressToString -PrefixLength $PrefixLength | Out-Null
|
||||
}
|
||||
return $RequestedAddress
|
||||
}
|
||||
|
||||
function Test-TcpPort {
|
||||
@@ -210,6 +341,9 @@ if ($ConnectivityMode -eq 'AzureP2S') {
|
||||
}
|
||||
else {
|
||||
$NetworkInterfaceAlias = Resolve-ClientInterfaceAlias -RequestedAlias $NetworkInterfaceAlias
|
||||
$ClientIPv4Address = Set-ClientDomainAddress -InterfaceAlias $NetworkInterfaceAlias `
|
||||
-DomainControllerAddress $DomainControllerIPv4Address `
|
||||
-RequestedAddress $ClientIPv4Address -PrefixLength $ClientPrefixLength
|
||||
Set-DnsClientServerAddress -InterfaceAlias $NetworkInterfaceAlias `
|
||||
-ServerAddresses $DomainControllerIPv4Address.IPAddressToString
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user