Skip to content

Instantly share code, notes, and snippets.

@mgreenegit
Last active August 5, 2022 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgreenegit/394693f4b6b8adc7ece0adfb23c4b5c0 to your computer and use it in GitHub Desktop.
Save mgreenegit/394693f4b6b8adc7ece0adfb23c4b5c0 to your computer and use it in GitHub Desktop.
TODO: add enum for gposetting type, try splitting details into a reasons array
function Get-Resource {
param(
[DscProperties]$DscProperties
)
$psPath = Join-Path ([System.Environment]::SystemDirectory) 'WindowsPowerShell\v1.0\powershell.exe'
& $psPath -noProfile -command {
param(
$Name
)
$Env:PSModulePath += ";$PSHOME\Modules\NetSecurity"
$NetFirewallProfile = Get-NetFirewallProfile -Name $Name
$get = @{}
$propertiesToNotReturn = @('Caption','Description','InstanceId','ElementName','PSComputerName','CimClass','CimInstanceProperties','CimSystemProperties')
$propertiesToReturn = $NetFirewallProfile.psobject.properties | Where-Object { $_.MemberType -in @('Property','ScriptProperty') -AND $_.Name -notin $propertiesToNotReturn } | ForEach-Object {$_.Name}
$propertiesToReturn | ForEach-Object {$get[$_] = [string]$NetFirewallProfile.$_}
return $get
} -arg $DscProperties.Name
}
function Set-Resource {
param(
[DscProperties]$DscProperties
)
$DscPropertiesAsJson = $DscProperties | ConvertTo-Json
$psPath = Join-Path ([System.Environment]::SystemDirectory) 'WindowsPowerShell\v1.0\powershell.exe'
& $psPath -noProfile -command {
param(
$DscPropertiesAsJson
)
$DscProperties = $DscPropertiesAsJson | ConvertFrom-Json
$Set = @{}
$DscProperties | ForEach-Object {$property = $_; if ($null -ne $DscProperties.$property) {$Set[$property] = [string]$DscProperties.$property}}
$Env:PSModulePath += ";$PSHOME\Modules\NetSecurity"
Set-NetFirewallProfile @Set
} -arg $DscPropertiesAsJson
}
function Test-Resource {
param(
[DscProperties]$DscProperties
)
$test = $false
$Get = Get-Resource -DscProperties $DscProperties
$propertiesWithValues = $DscProperties.psobject.properties | Where-Object {$_.Value -ne $null} | ForEach-Object {$_.Name}
$Compare = Compare-Object -ReferenceObject $Get -DifferenceObject $DscProperties -Property $propertiesWithValues
if ($Compare.count -eq 0) { $test = $true }
return $test
}
class DscProperties {
[DscProperty(Key)]
[string] $Name
[DscProperty()]
[string] $Enabled
[DscProperty()]
[string] $DefaultInboundAction
[DscProperty()]
[string] $DefaultOutboundAction
[DscProperty()]
[string] $AllowInboundRules
[DscProperty()]
[string] $AllowLocalFirewallRules
[DscProperty()]
[string] $AllowLocalIPsecRules
[DscProperty()]
[string] $AllowUserApps
[DscProperty()]
[string] $AllowUserPorts
[DscProperty()]
[string] $AllowUnicastResponseToMulticast
[DscProperty()]
[string] $NotifyOnListen
[DscProperty()]
[string] $EnableStealthModeForIPsec
[DscProperty()]
[string] $LogFileName
[DscProperty()]
[string] $LogMaxSizeKilobytes
[DscProperty()]
[string] $LogAllowed
[DscProperty()]
[string] $LogBlocked
[DscProperty()]
[string] $LogIgnored
[DscProperty()]
[string] $DisabledInterfaceAliases
}
########## No need to edit below this line ##########
function Get-AdditionalText {
param (
$get
)
$text = "Additional information:"
foreach ($property in ($get.Keys | sort-object)) {
$text += "`n`t[i] $property`: $([string]$get.$property)"
}
return $text
}
class Reason {
[DscProperty()]
[string] $Code
[DscProperty()]
[string] $Phrase
}
[DscResource()]
class NetSecurityDsc : DscProperties {
[DscProperty(NotConfigurable)]
[Reason[]]$Reasons
[NetSecurityDsc] Get() {
# Splat properties to Get function
$DscProperties = $this.GetConfigurableDscProperties()
$get = Get-Resource $DscProperties
# Adds Reasons to get
$additionalText = Get-AdditionalText -get $get
$get.Add('Reasons', $this.FormatReasons($get, $additionalText))
# Return hashtable produced by Get function
return $get
}
[Void] Set() {
# Splat properties to Set function
$DscProperties = $this.GetConfigurableDscProperties()
Set-Resource $DscProperties
}
[Bool] Test() {
# Splat properties to Test function
$DscProperties = $this.GetConfigurableDscProperties()
return Test-Resource $DscProperties
}
[Hashtable] GetConfigurableDscProperties() {
# This method returns a hashtable of properties with two special workarounds
# The hashtable will not include any properties marked as "NotConfigurable"
# Any properties with a ValidateSet of "True","False" will beconverted to Boolean type
# The intent is to simplify splatting to functions
$DscProperties = @{}
foreach ($property in [DscProperties].GetProperties().Name) {
# Checks if "NotConfigurable" attribute is set
$notConfigurable = [DscProperties].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.DscPropertyAttribute] }).NotConfigurable
if (!$notConfigurable) {
$value = $this.$property
# Gets the list of valid values from the ValidateSet attribute
$validateSet = [DscProperties].GetProperty($property).GetCustomAttributes($false).Where({ $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues
if ($validateSet) {
# Workaround for boolean types
if ($null -eq (Compare-Object @('True', 'False') $validateSet)) {
$value = [System.Convert]::ToBoolean($this.$property)
}
}
# Add property to new
$DscProperties.add($property, $value)
}
}
return $DscProperties
}
[Reason[]] FormatReasons([hashtable]$get, [string]$additionalText) {
# This method takes information about a DSC resource and returns an array of Reason objects
# Including text for phrase that will render well in a browser
$DscProperties = $this.GetConfigurableDscProperties()
$state0 = $state1 = $null
foreach ($key in $DscProperties.Keys) {
if ($null -ne $DscProperties.$key) {
if ($DscProperties.$key -eq $get.$key) {
$state0 += "`t`t[+] $key" + ':' + "`n`t`t`tExpected value to be `"$($DscProperties.$key)`"`n`t`t`tActual value was `"$($get.$key)`"`n"
}
else {
$state1 += "`t`t[-] $key" + ':' + "`n`t`t`tExpected value to be `"$($DscProperties.$key)`"`n`t`t`tActual value was `"$($get.$key)`"`n"
}
}
}
$Reason = [reason]::new()
$Reason.code = $this.GetType().Name + ':' + $this.GetType().Name + ':Configuration'
$phrase = "The machine returned the following configuration details.`n`n"
$phrase += "`tSettings in desired state:`n$state0`n"
$phrase += "`tSettings not in desired state:`n$state1"
$phrase += "`n$additionalText"
$Reason.phrase = $phrase
$return = @()
$return += $Reason
return $return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment