DSCResources/NetworkIpConfiguration/NetworkIpConfiguration.schema.psm1
configuration NetworkIpConfiguration { param ( [parameter()] [boolean] $DisableNetBios = $false, [parameter()] [int16] $ConfigureIPv6 = -1, # < 0 -> no configuration code will be generated [parameter()] [hashtable[]] $Interfaces, [parameter()] [hashtable[]] $Routes ) Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName xPSDesiredStateConfiguration Import-DscResource -ModuleName NetworkingDsc function NetIpInterfaceConfig { param( [string] $InterfaceAlias, [string] $IpAddress, [int] $Prefix, [string] $Gateway, [string[]] $DnsServer, [uint32] $InterfaceMetric, [boolean] $DisableNetbios, [boolean] $EnableDhcp, [boolean] $EnableLmhostsLookup, [boolean] $DisableIPv6, [ValidateSet('Public', 'Private', 'DomainAuthenticated')] [string] $NetworkCategory ) if ( $EnableDhcp -eq $true ) { if ( -not [string]::IsNullOrWhiteSpace($IpAddress) -or -not [string]::IsNullOrWhiteSpace($Gateway) -or ($null -ne $DnsServer -and $DnsServer.Count -gt 0)) { throw "ERROR: Enabled DHCP requires empty 'IpAddress' ($IpAddress), 'Gateway' ($Gateway) and 'DnsServer' ($DnsServer) parameters for interface '$InterfaceAlias'." } NetIPInterface "EnableDhcp_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias AddressFamily = 'IPv4' Dhcp = 'Enabled' } DnsServerAddress "EnableDhcpDNS_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias AddressFamily = 'IPv4' } } else { if ( -not [string]::IsNullOrWhiteSpace($IpAddress) ) { # disable DHCP if IP-Address is specified NetIPInterface "DisableDhcp_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias AddressFamily = 'IPv4' Dhcp = 'Disabled' } if( -not ($Prefix -match '^\d+$') ) { throw "ERROR: Valid 'Prefix' parameter is required for IP address '$IpAddress'." } $ip = "$($IpAddress)/$($Prefix)" IPAddress "NetworkIp_$InterfaceAlias" { IPAddress = $ip AddressFamily = 'IPv4' InterfaceAlias = $InterfaceAlias } } if ( -not [string]::IsNullOrWhiteSpace($Gateway) ) { DefaultGatewayAddress "DefaultGateway_$InterfaceAlias" { AddressFamily = 'IPv4' InterfaceAlias = $InterfaceAlias Address = $Gateway } } if ( $null -ne $DnsServer -and $DnsServer.Count -gt 0 ) { DnsServerAddress "DnsServers_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias AddressFamily = 'IPv4' Address = $DnsServer } } } if( $null -ne $InterfaceMetric -and $InterfaceMetric -gt 0 ) { Script "InterfaceMetric_$InterfaceAlias" { TestScript = { $netIf = Get-NetIpInterface -InterfaceAlias $using:InterfaceAlias -ErrorAction SilentlyContinue if( $null -eq $netIf ) { Write-Verbose "NetIpInterface '$using:InterfaceAlias' not found." return $false } [boolean]$result = $true $netIf | ForEach-Object { Write-Verbose "InterfaceMetric $($_.AddressFamily): $($_.InterfaceMetric)"; if( $_.InterfaceMetric -ne $using:InterfaceMetric ) { $result = $false }; } Write-Verbose "Expected Interface Metric: $using:InterfaceMetric" return $result } SetScript = { $netIf = Get-NetIpInterface -InterfaceAlias $using:InterfaceAlias $netIf | ForEach-Object { Write-Verbose "Set $($_.AddressFamily) InterfaceMetric to $using:InterfaceMetric"; $_ | Set-NetIpInterface -InterfaceMetric $using:InterfaceMetric } } GetScript = { return @{result = 'N/A' } } } } WinsSetting "LmhostsLookup_$InterfaceAlias" { EnableLmHosts = $EnableLmhostsLookup IsSingleInstance = 'Yes' } if ($DisableNetbios) { NetBios "DisableNetBios_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias Setting = 'Disable' } } if ($DisableIPv6) { NetAdapterBinding "DisableIPv6_$InterfaceAlias" { InterfaceAlias = $InterfaceAlias ComponentId = 'ms_tcpip6' State = 'Disabled' } } if( -not [string]::IsNullOrWhiteSpace($NetworkCategory) ) { if( -not ($NetworkCategory -match '^(Public|Private|DomainAuthenticated)$') ) { throw "ERROR: Invalid value of attribute 'NetworkCategory'." } Script "NetworkCategory_$InterfaceAlias" { TestScript = { $val = Get-NetConnectionProfile -InterfaceAlias $using:InterfaceAlias Write-Verbose "Current NetworkCategory of interface '$using:InterfaceAlias': $($val.NetworkCategory)" if ($null -ne $val -and $val.NetworkCategory -eq $using:NetworkCategory ) { return $true } Write-Verbose "Values are different (expected NetworkCategory: $using:NetworkCategory)" return $false } SetScript = { if( $using:NetworkCategory -eq 'DomainAuthenticated') { Write-Verbose "Set NetworkCategory of interface '$using:InterfaceAlias' to '$using:NetworkCategory ' is not supported. The computer automatically sets this value when the network is authenticated to a domain controller." # Workaround if the computer is domain joined -> Restart NLA service to restart the network location check # see https://newsignature.com/articles/network-location-awareness-service-can-ruin-day-fix/ Write-Verbose "Restarting NLA service to reinitialize the network location check..." Restart-Service nlasvc -Force Start-Sleep 5 $val = Get-NetConnectionProfile -InterfaceAlias $using:InterfaceAlias Write-Verbose "Current NetworkCategory is now: $($val.NetworkCategory)" if( $val.NetworkCategory -ne $using:NetworkCategory ) { Write-Error "Interface '$using:InterfaceAlias' is not '$using:NetworkCategory'." } } else { Write-Verbose "Set NetworkCategory of interface '$using:InterfaceAlias' to '$using:NetworkCategory '." Set-NetConnectionProfile -InterfaceAlias $using:InterfaceAlias -NetworkCategory $using:NetworkCategory } } GetScript = { return @{result = 'N/A'} } } } } if ($DisableNetbios -eq $true) { NetBios DisableNetBios_System { InterfaceAlias = '*' Setting = 'Disable' } } if ($ConfigureIPv6 -ge 0) { # see https://docs.microsoft.com/en-US/troubleshoot/windows-server/networking/configure-ipv6-in-windows if( $ConfigureIPv6 -gt 255 ) { throw "ERROR: Invalid IPv6 configuration value $ConfigureIPv6 (expected value: 0-255)." } $configIPv6KeyName = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters" $configIPv6VarName = 'DisabledComponents' Script ConfigureIPv6_System { TestScript = { $val = Get-ItemProperty -Path $using:configIPv6KeyName -Name $using:configIPv6VarName -ErrorAction SilentlyContinue Write-Verbose "Current IPv6 Configuration value: '$($val.$using:configIPv6VarName)' - expected value: '$using:ConfigureIPv6'" if ($null -ne $val -and $val.$using:configIPv6VarName -eq $using:ConfigureIPv6) { return $true } Write-Verbose 'Values are different' return $false } SetScript = { if( -not (Test-Path -Path $using:configIPv6KeyName) ) { New-Item -Path $using:configIPv6KeyName -Force } Set-ItemProperty -Path $using:configIPv6KeyName -Name $using:configIPv6VarName -Value $using:ConfigureIPv6 -Type DWord $global:DSCMachineStatus = 1 } GetScript = { return @{result = 'N/A'} } } } if ($null -ne $Interfaces) { foreach ( $netIf in $Interfaces ) { # Remove case sensitivity of ordered Dictionary or Hashtables $netIf = @{} + $netIf if ( [string]::IsNullOrWhitespace($netIf.InterfaceAlias) ) { $netIf.InterfaceAlias = 'Ethernet' } if ( $DisableNetbios -eq $true -or [string]::IsNullOrWhitespace($netIf.DisableNetbios) ) { $netIf.DisableNetbios = $false } if ( [string]::IsNullOrWhitespace($netIf.EnableLmhostsLookup) ) { $netIf.EnableLmhostsLookup = $false } if ( [string]::IsNullOrWhitespace($netIf.EnableDhcp) ) { $netIf.EnableDhcp = $false } if ( $DisableIPv6 -eq $true -or [string]::IsNullOrWhitespace($netIf.DisableIPv6) ) { $netIf.DisableIPv6 = $false } if ( $netIf.EnableDhcp -eq $true -and [string]::IsNullOrWhitespace($netIf.Prefix) ) { $netIf.Prefix = 24 } NetIpInterfaceConfig @netIf } } if ($null -ne $Routes) { foreach ( $netRoute in $Routes ) { # Remove case sensitivity of ordered Dictionary or Hashtables $netRoute = @{} + $netRoute if ( [string]::IsNullOrWhitespace($netRoute.InterfaceAlias) ) { $netRoute.InterfaceAlias = 'Ethernet' } if ( [string]::IsNullOrWhitespace($netRoute.AddressFamily) ) { $netRoute.AddressFamily = 'IPv4' } if ( [string]::IsNullOrWhitespace($netRoute.Ensure) ) { $netRoute.Ensure = 'Present' } $executionName = "route_$($netRoute.InterfaceAlias)_$($netRoute.AddressFamily)_$($netRoute.DestinationPrefix)_$($netRoute.NextHop)" -replace '[().:\s]', '' (Get-DscSplattedResource -ResourceName Route -ExecutionName $executionName -Properties $netRoute -NoInvoke).Invoke($netRoute) } } } |