DSCResources/cFirewallRule/cFirewallRule.psm1
<#
Author : Serge Nikalaichyk (https://www.linkedin.com/in/nikalaichyk) Version : 1.0.0 Date : 2015-10-14 #> function Get-TargetResource { [CmdletBinding()] [OutputType([Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction, [Parameter(Mandatory = $false)] [Boolean] $Enabled, [Parameter(Mandatory = $false)] [ValidateSet('Absent', 'Present')] [String] $Ensure, [Parameter(Mandatory = $false)] [String] $Group, [Parameter(Mandatory = $false)] [String[]] $LocalAddress, [Parameter(Mandatory = $false)] [String[]] $LocalPort, [Parameter(Mandatory = $false)] [ValidateScript({$_ | Where-Object {$_ -in @('All', 'Domain', 'Private', 'Public')}})] [String[]] $Profile, [Parameter(Mandatory = $false)] [String] $Program, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol, [Parameter(Mandatory = $false)] [String[]] $RemoteAddress, [Parameter(Mandatory = $false)] [String[]] $RemotePort, [Parameter(Mandatory = $false)] [String] $Service ) $PSBoundParameters.GetEnumerator() | ForEach-Object -Begin { $Width = $PSBoundParameters.Keys.Length | Sort-Object -Descending | Select-Object -First 1 } -Process { "{0,-$($Width)} : '{1}'" -f $_.Key, ($_.Value -join ', ') | Write-Verbose } $PSBoundParameters.Remove('Ensure') $MatchingRules = @(Get-cFirewallRule @PSBoundParameters -ErrorAction Stop) if ($MatchingRules.Count -eq 0) { Write-Verbose -Message 'A matching firewall rule was not found.' $EnsureResult = 'Absent' } elseif ($MatchingRules.Count -eq 1) { Write-Verbose -Message 'A matching firewall rule was found.' $EnsureResult = 'Present' } else { Write-Verbose -Message "Multiple matching firewall rules were found (Count: $($MatchingRules.Count))." $EnsureResult = 'Present' } $ReturnValue = @{ Name = $Name Action = $(if ($MatchingRules) {$MatchingRules[0].Action}) Description = $(if ($MatchingRules) {$MatchingRules[0].Description}) Direction = $(if ($MatchingRules) {$MatchingRules[0].Direction}) Enabled = [Boolean]$(if ($MatchingRules) {$MatchingRules[0].Enabled}) Ensure = $EnsureResult Group = $(if ($MatchingRules) {$MatchingRules[0].Group}) LocalAddress = [String[]]@($(if ($MatchingRules) {$MatchingRules[0].LocalAddress -split ','})) LocalPort = [String[]]@($(if ($MatchingRules) {$MatchingRules[0].LocalPort -split ','})) Profile = [String[]]@($(if ($MatchingRules) {$MatchingRules[0].Profile.ToString() -replace '\s' -split ','})) Program = $(if ($MatchingRules) {$MatchingRules[0].Program}) Protocol = $(if ($MatchingRules) {$MatchingRules[0].Protocol}) RemoteAddress = [String[]]@($(if ($MatchingRules) {$MatchingRules[0].RemoteAddress -split ','})) RemotePort = [String[]]@($(if ($MatchingRules) {$MatchingRules[0].RemotePort -split ','})) Service = $(if ($MatchingRules) {$MatchingRules[0].Service}) } return $ReturnValue } function Test-TargetResource { [CmdletBinding()] [OutputType([Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction, [Parameter(Mandatory = $false)] [Boolean] $Enabled, [Parameter(Mandatory = $false)] [ValidateSet('Absent', 'Present')] [String] $Ensure, [Parameter(Mandatory = $false)] [String] $Group, [Parameter(Mandatory = $false)] [String[]] $LocalAddress, [Parameter(Mandatory = $false)] [String[]] $LocalPort, [Parameter(Mandatory = $false)] [ValidateScript({$_ | Where-Object {$_ -in @('All', 'Domain', 'Private', 'Public')}})] [String[]] $Profile, [Parameter(Mandatory = $false)] [String] $Program, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol, [Parameter(Mandatory = $false)] [String[]] $RemoteAddress, [Parameter(Mandatory = $false)] [String[]] $RemotePort, [Parameter(Mandatory = $false)] [String] $Service ) $TargetResource = Get-TargetResource @PSBoundParameters $InDesiredState = $Ensure -eq $TargetResource.Ensure if ($InDesiredState -eq $true) { Write-Verbose -Message 'The target resource is already in the desired state. No action is required.' } else { Write-Verbose -Message 'The target resource is not in the desired state.' } return $InDesiredState } function Set-TargetResource { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction, [Parameter(Mandatory = $false)] [Boolean] $Enabled, [Parameter(Mandatory = $false)] [ValidateSet('Absent', 'Present')] [String] $Ensure, [Parameter(Mandatory = $false)] [String] $Group, [Parameter(Mandatory = $false)] [String[]] $LocalAddress, [Parameter(Mandatory = $false)] [String[]] $LocalPort, [Parameter(Mandatory = $false)] [ValidateScript({$_ | Where-Object {$_ -in @('All', 'Domain', 'Private', 'Public')}})] [String[]] $Profile, [Parameter(Mandatory = $false)] [String] $Program, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol, [Parameter(Mandatory = $false)] [String[]] $RemoteAddress, [Parameter(Mandatory = $false)] [String[]] $RemotePort, [Parameter(Mandatory = $false)] [String] $Service ) if (-not $PSCmdlet.ShouldProcess($Name)) { return } if ($Ensure -eq 'Absent') { $PSBoundParameters.Remove('Ensure') Remove-cFirewallRule @PSBoundParameters -Confirm:$false } else { $PSBoundParameters.Remove('Ensure') New-cFirewallRule @PSBoundParameters } } #region Helper Functions function Initialize-cFirewallRuleType { $TypeDefinition = @' using System; namespace FwRule { public enum Action { Block = 0, Allow = 1 } public enum Direction { Inbound = 1, Outbound = 2 } [FlagsAttribute] public enum Profiles { Domain = 1, Private = 2, Public = 4, All = Domain | Private | Public | 2147483647 } } '@ if (-not ('FwRule.Action' -as [Type])) { Add-Type -TypeDefinition $TypeDefinition } <# .NOTES Each time you change a property of a rule, Windows Firewall commits the rule and verifies it for correctness. As a result, when you edit a rule, you must perform the steps in a specific order. For example, the Protocol property must be set before the LocalPorts or RemotePorts properties or an error will be returned. .LINK https://msdn.microsoft.com/en-us/library/windows/desktop/aa365344%28v=vs.85%29.aspx #> if (-not (Get-Variable -Name FwRulePropertyData -Scope Script -ErrorAction Ignore)) { New-Variable -Name FwRulePropertyData -Force -Option ReadOnly -Scope Script -Value @( [PSCustomObject]@{Order = 0; ParameterName = 'Name'; PropertyName = 'Name'; PropertyType = [String]} [PSCustomObject]@{Order = 1; ParameterName = 'Description'; PropertyName = 'Description'; PropertyType = [String]} [PSCustomObject]@{Order = 2; ParameterName = 'Program'; PropertyName = 'ApplicationName'; PropertyType = [String]} [PSCustomObject]@{Order = 3; ParameterName = 'Service'; PropertyName = 'ServiceName'; PropertyType = [String]} [PSCustomObject]@{Order = 4; ParameterName = 'Protocol'; PropertyName = 'Protocol'; PropertyType = [System.Net.Sockets.ProtocolType]} [PSCustomObject]@{Order = 5; ParameterName = 'LocalPort'; PropertyName = 'LocalPorts'; PropertyType = [String]} [PSCustomObject]@{Order = 6; ParameterName = 'RemotePort'; PropertyName = 'RemotePorts'; PropertyType = [String]} [PSCustomObject]@{Order = 7; ParameterName = 'LocalAddress'; PropertyName = 'LocalAddresses'; PropertyType = [String]} [PSCustomObject]@{Order = 8; ParameterName = 'RemoteAddress'; PropertyName = 'RemoteAddresses'; PropertyType = [String]} [PSCustomObject]@{Order = 9; ParameterName = 'Direction'; PropertyName = 'Direction'; PropertyType = [FwRule.Direction]} [PSCustomObject]@{Order = 10; ParameterName = 'Enabled'; PropertyName = 'Enabled'; PropertyType = [Boolean]} [PSCustomObject]@{Order = 11; ParameterName = 'Group'; PropertyName = 'Grouping'; PropertyType = [String]} [PSCustomObject]@{Order = 12; ParameterName = 'Profile'; PropertyName = 'Profiles'; PropertyType = [FwRule.Profiles]} [PSCustomObject]@{Order = 13; ParameterName = 'Action'; PropertyName = 'Action'; PropertyType = [FwRule.Action]} ) } } function Get-cFirewallRule { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction, [Parameter(Mandatory = $false)] [Boolean] $Enabled, [Parameter(Mandatory = $false)] [String] $Group, [Parameter(Mandatory = $false)] [String[]] $LocalAddress, [Parameter(Mandatory = $false)] [String[]] $LocalPort, [Parameter(Mandatory = $false)] [ValidateSet('All', 'Domain', 'Private', 'Public')] [String[]] $Profile, [Parameter(Mandatory = $false)] [String] $Program, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol, [Parameter(Mandatory = $false)] [String[]] $RemoteAddress, [Parameter(Mandatory = $false)] [String[]] $RemotePort, [Parameter(Mandatory = $false)] [String] $Service ) begin { Initialize-cFirewallRuleType $FwPolicy = New-Object -ComObject HNetCfg.FwPolicy2 -ErrorAction Stop } process { if ($Protocol -in @('*', 'Any', 'All')) { $PSBoundParameters.Item('Protocol') = [String]$Protocol = '256' } $PSBoundParameters.Keys.Where({$_ -in $Script:FwRulePropertyData.ParameterName}) | ForEach-Object -Begin { [String[]]$FilterConditions = @('($_ -ne $null)') } -Process { $ParameterName = $_ $PropertyData = $Script:FwRulePropertyData.Where({$_.ParameterName -eq $ParameterName}) if ($ParameterName -in @('LocalAddress', 'RemoteAddress')) { $PSBoundParameters.Item($ParameterName) = ( $PSBoundParameters.Item($ParameterName) | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Resolve-cFirewallRuleAddress | Sort-Object ) -join ',' $FilterConditions += '((($_."{0}" -split "," | Sort-Object) -join ",") -as [{2}]) -eq ($PSBoundParameters.Item("{1}") -as [{2}])' -f $PropertyData.PropertyName, $PropertyData.ParameterName, $PropertyData.PropertyType return } if ($ParameterName -in @('LocalPort', 'RemotePort')) { $PSBoundParameters.Item($ParameterName) = ( $PSBoundParameters.Item($ParameterName) | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Sort-Object ) -join ',' } if ($ParameterName -eq 'Program') { $PSBoundParameters.Item($ParameterName) = [Environment]::ExpandEnvironmentVariables($PSBoundParameters.Item($ParameterName)) } $FilterConditions += '($_."{0}" -as [{2}]) -eq ($PSBoundParameters.Item("{1}") -as [{2}])' -f $PropertyData.PropertyName, $PropertyData.ParameterName, $PropertyData.PropertyType } -End { $FilterScript = [ScriptBlock]::Create(($FilterConditions -join ' -and ')) } $FwPolicy.Rules | Where-Object -FilterScript $FilterScript -PipelineVariable FwRule | ForEach-Object { $Script:FwRulePropertyData | Select-Object -PipelineVariable PropertyData | ForEach-Object -Begin { $OutputObject = [PSCustomObject]@{} } -Process { $OutputObject | Add-Member -NotePropertyname $PropertyData.ParameterName ` -NotePropertyValue ($FwRule."$($PropertyData.PropertyName)" -as $PropertyData.PropertyType) } -End { return $OutputObject } } } } function New-cFirewallRule { [CmdletBinding(ConfirmImpact = 'Medium', SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action = 'Allow', [Parameter(Mandatory = $false)] [String] $Description = $null, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction = 'Inbound', [Parameter(Mandatory = $false)] [Boolean] $Enabled = $true, [Parameter(Mandatory = $false)] [String] $Group = $null, [Parameter(Mandatory = $false)] [String[]] $LocalAddress = $null, [Parameter(Mandatory = $false)] [String[]] $LocalPort = $null, [Parameter(Mandatory = $false)] [ValidateSet('All', 'Domain', 'Private', 'Public')] [String[]] $Profile = 'All', [Parameter(Mandatory = $false)] [String] $Program = $null, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol = 'TCP', [Parameter(Mandatory = $false)] [String[]] $RemoteAddress = $null, [Parameter(Mandatory = $false)] [String[]] $RemotePort = $null, [Parameter(Mandatory = $false)] [String] $Service = $null ) begin { Initialize-cFirewallRuleType $FwPolicy = New-Object -ComObject HNetCfg.FwPolicy2 -ErrorAction Stop } process { if (-not $PSCmdlet.ShouldProcess($Name, 'Create Rule')) { return } trap { Write-Error -Message $_.Exception.Message return } $MyInvocation.MyCommand.Parameters.Keys.Where({$_ -in $Script:FwRulePropertyData.ParameterName}) | ForEach-Object -Begin { $Properties = @{} } -Process { $ParameterName = $_ $ParameterValue = Get-Variable -Name $ParameterName -Scope Local -ValueOnly -ErrorAction Ignore if (-not $ParameterValue -and -not $PSBoundParameters.ContainsKey($ParameterName)) { return } if ($ParameterName -in @('LocalAddress', 'RemoteAddress')) { $ParameterValue = ( $ParameterValue | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Resolve-cFirewallRuleAddress | Sort-Object ) -join ',' } if ($ParameterName -in @('LocalPort', 'RemotePort')) { $ParameterValue = ( $ParameterValue | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Sort-Object ) -join ',' } if ($ParameterName -eq 'Program') { $ParameterValue = [Environment]::ExpandEnvironmentVariables($ParameterValue); } if ($ParameterName -eq 'Protocol' -and $ParameterValue -in @('*', 'Any', 'All')) { $ParameterValue = '256' } $PropertyData = $Script:FwRulePropertyData.Where({$_.ParameterName -eq $ParameterName}) $Properties.Add($PropertyData.PropertyName, $ParameterValue) } $Script:FwRulePropertyData.Where({$_.PropertyName -in $Properties.Keys}) | Sort-Object -Property Order | ForEach-Object -Begin { $FwRule = New-Object -ComObject HNetCfg.FwRule -ErrorAction Stop } -Process { $PropertyData = $_ try { $FwRule."$($PropertyData.PropertyName)" = ($Properties.Item($PropertyData.PropertyName) -as $PropertyData.PropertyType) } catch { throw "Failed to set property '$($PropertyData.PropertyName)': '$($_.Exception.Message)'." } } -End { try { $FwPolicy.Rules.Add($FwRule) } catch { throw "Failed to add rule '$Name': '$($_.Exception.Message)'." } } } } function Remove-cFirewallRule { [CmdletBinding(ConfirmImpact = 'High', SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [String] $Name, [Parameter(Mandatory = $false)] [ValidateSet('Allow', 'Block')] [String] $Action, [Parameter(Mandatory = $false)] [String] $Description, [Parameter(Mandatory = $false)] [ValidateSet('Inbound', 'Outbound')] [String] $Direction, [Parameter(Mandatory = $false)] [Boolean] $Enabled, [Parameter(Mandatory = $false)] [String] $Group, [Parameter(Mandatory = $false)] [String[]] $LocalAddress, [Parameter(Mandatory = $false)] [String[]] $LocalPort, [Parameter(Mandatory = $false)] [ValidateSet('All', 'Domain', 'Private', 'Public')] [String[]] $Profile, [Parameter(Mandatory = $false)] [String] $Program, [Parameter(Mandatory = $false)] [ValidateScript({($_ -in [System.Net.Sockets.ProtocolType].GetEnumNames()) -or ($_ -in @('*', 'Any', 'All'))})] [String] $Protocol, [Parameter(Mandatory = $false)] [String[]] $RemoteAddress, [Parameter(Mandatory = $false)] [String[]] $RemotePort, [Parameter(Mandatory = $false)] [String] $Service ) begin { Initialize-cFirewallRuleType $FwPolicy = New-Object -ComObject HNetCfg.FwPolicy2 -ErrorAction Stop } process { if (-not $PSCmdlet.ShouldProcess($Name, 'Remove Rule')) { return } if ($Protocol -in @('*', 'Any', 'All')) { $PSBoundParameters.Item('Protocol') = [String]$Protocol = '256' } $PSBoundParameters.Keys.Where({$_ -in $Script:FwRulePropertyData.ParameterName}) | ForEach-Object -Begin { [String[]]$FilterConditions = @() } -Process { $ParameterName = $_ $PropertyData = $Script:FwRulePropertyData.Where({$_.ParameterName -eq $ParameterName}) if ($ParameterName -in @('LocalAddress', 'RemoteAddress')) { $PSBoundParameters.Item($ParameterName) = ( $PSBoundParameters.Item($ParameterName) | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Resolve-cFirewallRuleAddress | Sort-Object ) -join ',' $FilterConditions += '((($_."{0}" -split "," | Sort-Object) -join ",") -as [{2}]) -eq ($PSBoundParameters.Item("{1}") -as [{2}])' -f $PropertyData.PropertyName, $PropertyData.ParameterName, $PropertyData.PropertyType return } if ($ParameterName -in @('LocalPort', 'RemotePort')) { $PSBoundParameters.Item($ParameterName) = ( $PSBoundParameters.Item($ParameterName) | Where-Object {[String]::IsNullOrEmpty($_) -eq $false} | Sort-Object ) -join ',' } if ($ParameterName -eq 'Program') { $PSBoundParameters.Item($ParameterName) = [Environment]::ExpandEnvironmentVariables($PSBoundParameters.Item($ParameterName)) } $FilterConditions += '($_."{0}" -as [{2}]) -eq ($PSBoundParameters.Item("{1}") -as [{2}])' -f $PropertyData.PropertyName, $PropertyData.ParameterName, $PropertyData.PropertyType } -End { $FilterScript = [ScriptBlock]::Create(($FilterConditions -join ' -and ')) } $MatchingRules = @($FwPolicy.Rules | Where-Object -FilterScript $FilterScript) <# .NOTES Due to the 'INetFwRules::Remove' method limitations, rules can be removed only by name. Workaround is to rename all the matching rules with a random name before removing them. .LINKS https://msdn.microsoft.com/en-us/library/windows/desktop/aa365349%28v=vs.85%29.aspx #> if ($MatchingRules.Count -eq 0) { Write-Verbose -Message "No matching firewall rules could be found." } else { $MatchingRules | ForEach-Object -Begin { Write-Verbose -Message "Removing all the matching firewall rules." [String[]]$RuleNamesToRemove = @() } -Process { $RuleNamesToRemove += $NewRandomName = [Guid]::NewGuid().Guid Write-Verbose -Message "Renaming firewall rule '$($_.Name)' to '$NewRandomName'." $_.Enabled = $false $_.Description = "Disabled and marked for removal: $(Get-Date -Format s)." $_.Name = $NewRandomName } if ($RuleNamesToRemove.Count -ne 0) { foreach ($RuleName in $RuleNamesToRemove) { Write-Verbose -Message "Removing firewall rule '$RuleName'." $FwPolicy.Rules.Remove($RuleName) } } } } } function Resolve-cFirewallRuleAddress { [CmdletBinding()] [OutputType([String])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [String] $InputString ) begin { $IPAddressPattern = '(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])' $NetworkPrefixPattern = '(\d{1}|[0-2]{1}\d{1}|3[0-2])' function Convert-NetworkPrefix { <# .SYNOPSIS Converts network prefix (a.k.a. CIDR prefix) to a subnet mask. #> [CmdletBinding()] [OutputType([String])] param ( [Parameter(Mandatory = $true)] [ValidateRange(0, 32)] [Int32] $Prefix ) process { $Array = New-Object -TypeName 'System.Int32[]' -ArgumentList 32 0..($Prefix - 1) | ForEach-Object {$Array.SetValue(1, $_)} $SubnetMask = [System.Convert]::ToUInt64((-join $Array), 2) -as [IPAddress] Write-Output -InputObject $SubnetMask.IPAddressToString } } function Test-IPAddressRange { <# .SYNOPSIS Tests whether the IP End address is greater than the IP Start address. #> [CmdletBinding()] [OutputType([Boolean])] param ( [Parameter(Mandatory = $true)] [IPAddress] $Start, [Parameter(Mandatory = $true)] [IPAddress] $End ) process { $StartBytes = $Start.GetAddressBytes() $EndBytes = $End.GetAddressBytes() [Array]::Reverse($StartBytes) [Array]::Reverse($EndBytes) $StartInt = [BitConverter]::ToUInt32($StartBytes, 0) $EndInt = [BitConverter]::ToUInt32($EndBytes, 0) $Result = $EndInt -gt $StartInt Write-Output -InputObject $Result } } } process { switch -Regex ($InputString) { ('^{0}\/{1}$' -f $IPAddressPattern, $NetworkPrefixPattern) { [IPAddress]$IPAddress, [Int32]$NetworkPrefix = $InputString -split '/' $SubnetMask = Convert-NetworkPrefix -Prefix $NetworkPrefix $OutputString = $IPAddress.IPAddressToString, $SubnetMask -join '/' } ('^{0}\/{0}$' -f $IPAddressPattern) { [IPAddress]$IPAddress, [IPAddress]$SubnetMask = $InputString -split '/' $OutputString = $IPAddress.IPAddressToString, $SubnetMask.IPAddressToString -join '/' } ('^{0}\-{0}$' -f $IPAddressPattern) { [IPAddress]$StartIPAddress, [IPAddress]$EndIPAddress = $InputString -split '-' if ($StartIPAddress.IPAddressToString -eq $EndIPAddress.IPAddressToString) { $OutputString = $StartIPAddress.IPAddressToString, '255.255.255.255' -join '/' } else { if (Test-IPAddressRange -Start $StartIPAddress -End $EndIPAddress) { $OutputString = $StartIPAddress.IPAddressToString, $EndIPAddress.IPAddressToString -join '-' } else { "The End address '{0}' is less than the Start address '{1}' in the IP address range '{2}'. Please change the End address." -f $EndIPAddress.IPAddressToString, $StartIPAddress.IPAddressToString, $InputString | Write-Error return } } } ('^{0}$' -f $IPAddressPattern) { [IPAddress]$IPAddress = $InputString $OutputString = $IPAddress.IPAddressToString, '255.255.255.255' -join '/' } default { $OutputString = $InputString } } Write-Output -InputObject $OutputString } } #endregion |