Configure the firewall profile with DSC (Part 3)

The third part deals with the most advanced or modern way of creating custom DSC resources.
Sorry, this time, there’s no helper module 😦 but there’s an excellent documentation on MSDN on this page 😀

mkdir 'C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile'

$Manifest = @{
    Path = 'C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile\xFirewallProfile.psd1'
    RootModule = 'xFirewallProfile.psm1'
    Guid = ([guid]::NewGuid().Guid) ;
    Author  = 'Emin Atac' ;
    CompanyName  = 'Emin Atac'
    Copyright = 'Free to use'
    ModuleVersion = '1.0.0'
    PowerShellVersion = '5.0'
    DscResourcesToExport = 'ClassFirewallProfile'
New-ModuleManifest @Manifest -Verbose

psedit "C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile\xFirewallProfile.psm1"

NB: Notice that the RootModule and DscResourcesToExport statements added to the manifest.

Now here’s what to paste into the xFirewallProfile.psm1 file.

Let’s first examine the syntax.

Looks good. Let’s create a configuration to test it. This isn’t much different from what we saw in part 2.

If my machine is already configured as expected, I’ll get:

If I change the domain profile and reapply my configuration, it’s set back to its desired state

Configure the firewall profile with DSC (Part 2)

The 2nd part deals with the classic way of creating custom DSC resources.
To help demo that, there’s actually an xDSCResourceDesginer module available in the PowerShell Gallery (a.k.a. PSGallery).

Here’s what I run if it’s not installed

# 1. Get the module and load it
Find-Module -Name xDSCResourceDesigner -Repository PsGallery -Verbose
Install-Module -Name xDSCResourceDesigner -Repository PsGallery -Verbose
Import-Module -Name xDSCResourceDesigner -Force -Verbose

There are only a few steps required to get started

# 2. Create the resource
$resource = @{
    Name = 'cFirewallProfile';
    Property  = (New-xDscResourceProperty -Name 'Name' -Type 'String' -Attribute = 'Key' -ValidateSet 'Domain','Public','Private'),
                (New-xDscResourceProperty -Name "Enabled" -Type "String" -Attribute Required -ValidateSet 'True','False','NotConfigured'),
                (New-xDscResourceProperty -Name DefaultInboundAction -Type "String" -Attribute Required -ValidateSet 'Allow','Block','NotConfigured'),
                (New-xDscResourceProperty -Name DefaultOutboundAction -Type "String" -Attribute Required -ValidateSet 'Allow','Block','NotConfigured')
    Path = 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile';
    ClassVersion = '1.0' ;
    FriendlyName = 'cFirewallProfile' ;
    Force = $true ;
New-xDscResource @resource

# 3. Create its manifest
$Manifest = @{
    Path = 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile\cFirewallProfile.psd1'
    Guid = ([guid]::NewGuid().Guid) ;
    Author  = 'Emin Atac' ;
    CompanyName  = 'Emin Atac'
    Copyright = 'Free to use'
    ModuleVersion = '1.0.0'
    PowerShellVersion = '4.0'
    FunctionsToExport = 'Get-TargetResource','Test-TargetResource','Set-TargetResource'
New-ModuleManifest @Manifest -Verbose

# 4. Ready to edit the resource
psedit 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile\DSCResources\cFirewallProfile\cFirewallProfile.psm1'

All the parameters of the 3 functions have been populated automatically thanks to the New-xDscResource and New-xDscResourceProperty cmdlets and we only have to focus and create the body of these functions. Nice isn’t it?

Here’s what to paste inside the cFirewallProfile.psm1 file.

Now, I can use the above custom DSC resource to configure the firewall profiles:

Configuration TestFirewallProfileConfig {

    Param (
        [string[]]$NodeName = 'localhost'

    Import-DscResource -Name * -ModuleName 'cFirewallProfile';

    Node $NodeName
        Foreach ($fw in @('Domain','Public','Private'))
            cFirewallProfile "$($fw)"
                Name = "$($fw)"
                Enabled = 'True'
                DefaultInboundAction = 'Block' ;
                DefaultOutboundAction = 'Allow' ;

The last step consists in compiling the configuration into a MOF file and applying it like this:

if (-not(test-path -Path C:\DSC -PathType Container)){
    mkdir C:\DSC
# Compile into MOF file
TestFirewallProfileConfig -OutputPath C:\DSC 

# Apply
Start-DscConfiguration -Path C:\DSC -ComputerName localhost -Verbose -Force -Wait

To be able to test it, I’ll set the exact opposite way I want it to be. Don’t do that on a production server.

Set-NetFirewallProfile -All -DefaultInboundAction Allow -DefaultOutboundAction Block  -Enabled false

When I apply the configuration, we can see all the 3 profiles being configured:

If I ask whether the system is in its desired state with the Test-DscConfiguration cmdlet, I get:
If I refresh the wf.msc MMC snap-in I’ve actually restored back the defaults thanks to my DSC configuration.

Let’s say I only mess up the Domain profile.

When I (re)apply the configuration, there’s only one profile that is being reconfigured before the Test-DscConfiguration cmdlet tells me it’s compliant again 😀


Configure the firewall profile with DSC (Part 1)

I was preparing a DSC configuration for a new server this week and after configuring firewall rules with the xNetworking DSC resources available on the PowerShell Gallery, I realized that having only rules without configuring the firewall profiles is wrong.

Keep in mind DSC is for compliance not security.
In my opinion, we should first configure the firewall rules AND then the firewall profiles.
If you’ve got the rules and an admin turns the firewall off, DSC will either tell you and/or fix the problem depending on the way you configured the ConfigurationMode of the LCM (Local Configuration Manager)
In this case, I’d suggest that the xfirewall DSC should be renamed to xFirewallRule and a new DSC resource xFirewallProfile should be added.

As I was in a hurry, here is the quick and dirty way I used to configure the firewall profiles:

As you can see, I had to explicitly use scopes inside the TestScript block.
In the meantime, I’ve discovered what scopes can be used inside a Tescript block. Using the global or local scope worked but not the script scope.
Using the Set-Variable to define the problem variable in the parent scope didn’t work either.

You may also have noticed that I’ve hardcoded the firewall state, its DefaultInboundAction and DefaultOutboundAction properties.
We’ll see in Part 2 how to create a proper DSC resource and use these as parameters.