$repositoryRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path $serverBootstrapPath = Join-Path $repositoryRoot 'scripts\Initialize-SguDomainController.ps1' $clientBootstrapPath = Join-Path $repositoryRoot 'scripts\Invoke-SguClientBootstrap.ps1' $azureClientPath = Join-Path $repositoryRoot 'scripts\Install-SguAzureP2sClient.ps1' $bicepPath = Join-Path $repositoryRoot 'infra\azure\main.bicep' $tokens = $null $parseErrors = $null $serverAst = [Management.Automation.Language.Parser]::ParseFile( $serverBootstrapPath, [ref]$tokens, [ref]$parseErrors) if ($parseErrors.Count -gt 0) { throw ($parseErrors -join [Environment]::NewLine) } $networkFunctionNames = @( 'Test-PrivateIPv4Address', 'ConvertTo-NetworkCidr', 'ConvertTo-PrivateNetworkCidr' ) $networkFunctions = $serverAst.FindAll({ param($node) $node -is [Management.Automation.Language.FunctionDefinitionAst] -and $networkFunctionNames -contains $node.Name }, $true) Invoke-Expression (($networkFunctions | ForEach-Object { $_.Extent.Text }) -join [Environment]::NewLine) $clientTokens = $null $clientParseErrors = $null $clientAst = [Management.Automation.Language.Parser]::ParseFile( $clientBootstrapPath, [ref]$clientTokens, [ref]$clientParseErrors) if ($clientParseErrors.Count -gt 0) { throw ($clientParseErrors -join [Environment]::NewLine) } $clientNetworkFunctions = $clientAst.FindAll({ param($node) $node -is [Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -eq 'Test-IPv4AddressesSharePrefix' }, $true) Invoke-Expression (($clientNetworkFunctions | ForEach-Object { $_.Extent.Text }) -join [Environment]::NewLine) Describe 'SGU public-cloud network safety' { It 'canonicalizes a host address to its IPv4 network' { ConvertTo-NetworkCidr -Address ([ipaddress]'10.77.0.4') ` -NetworkPrefixLength 24 | Should Be '10.77.0.0/24' } It 'canonicalizes the trusted P2S pool' { ConvertTo-PrivateNetworkCidr -Cidr '172.30.4.19/16' | Should Be '172.30.0.0/16' } It 'rejects a public trusted-client CIDR' { $wasRejected = $false try { ConvertTo-PrivateNetworkCidr -Cidr '8.8.8.0/24' | Out-Null } catch { $wasRejected = $true } $wasRejected | Should Be $true } It 'exposes explicit Azure modes on both bootstraps' { ((Get-Command $serverBootstrapPath).Parameters.Keys -contains 'NetworkConfigurationMode') | Should Be $true ((Get-Command $serverBootstrapPath).Parameters.Keys -contains 'TrustedClientNetworks') | Should Be $true ((Get-Command $clientBootstrapPath).Parameters.Keys -contains 'ConnectivityMode') | Should Be $true ((Get-Command $clientBootstrapPath).Parameters.Keys -contains 'VpnProfilePackagePath') | Should Be $true } It 'accepts an explicit static IPv4 address for a private Windows adapter' { ((Get-Command $clientBootstrapPath).Parameters.Keys -contains 'ClientIPv4Address') | Should Be $true ((Get-Command $clientBootstrapPath).Parameters.Keys -contains 'ClientPrefixLength') | Should Be $true } It 'matches a client and domain controller within the requested prefix' { Test-IPv4AddressesSharePrefix -FirstAddress ([ipaddress]'192.168.50.11') ` -SecondAddress ([ipaddress]'192.168.50.10') -PrefixLength 24 | Should Be $true Test-IPv4AddressesSharePrefix -FirstAddress ([ipaddress]'192.168.51.11') ` -SecondAddress ([ipaddress]'192.168.50.10') -PrefixLength 24 | Should Be $false Test-IPv4AddressesSharePrefix -FirstAddress ([ipaddress]'10.77.15.20') ` -SecondAddress ([ipaddress]'10.77.0.4') -PrefixLength 16 | Should Be $true } It 'prefers the private adapter instead of the Internet default route' { $source = Get-Content -LiteralPath $clientBootstrapPath -Raw $source | Should Match '\$withoutDefaultGateway\.Count -eq 1' $source | Should Not Match "Get-NetRoute -AddressFamily IPv4 -DestinationPrefix '0\.0\.0\.0/0'" } It 'waits for the new address and WinRM route to stabilize' { $source = Get-Content -LiteralPath $clientBootstrapPath -Raw $source | Should Match "AddressState -eq 'Preferred'" $source | Should Match 'function Wait-TcpPort' $source | Should Match 'Wait-TcpPort -Address \$DomainControllerIPv4Address -Port 5985' } It 'uses an all-user machine-certificate VPN profile' { $source = Get-Content -LiteralPath $azureClientPath -Raw $source | Should Match '-AuthenticationMethod MachineCertificate' $source | Should Match '-AllUserConnection' $source | Should Match 'Add-DnsClientNrptRule' } It 'limits optional public administration to RDP' { $template = Get-Content -LiteralPath $bicepPath -Raw $template | Should Match "name: 'Allow-RDP-from-administrator'" $template | Should Match "destinationPortRange: '3389'" $template | Should Not Match "sourceAddressPrefix: '0\.0\.0\.0/0'" } }