Search code examples
windowspowershellwindows-firewall

what's cleanest way in adding local windows firewall rules with powershell


I have written the following simple script that reads a csv file then iterates through each and adds in some firewall rules to a local machine.

I wanted to know if this the 'cleanest' way of achieving this. (i know there is gpo etc) but I am trying more of my powershell. I'll also try and add a check if the rule names already exist or not.

$rulenames = Import-Csv -Path "C:\temp\newrulenames.csv"

ForEach ($name in $rulenames) {
    New-NetFirewallRule -DisplayName $name.DisplayName -Name $name.Name -Enabled $name.Enabled -Profile $name.Profile -Direction $name.Direction -Action $name.Action -Protocol $name.Protocol -Program $name.Program -EdgeTraversalPolicy $name.EdgeTraversalPolicy
}

Solution

  • GPO seems like the way to go really but since you already are aware of that and are trying out PowerShell...

    In cases like this I personally like to use something called splatting (see about_Splatting) since it improves script readability quite a bit in my opinion. For your particular code it could look something like this;

    $rulenames = Import-Csv -Path "C:\temp\newrulenames.csv"
    foreach($name in $rulenames)
    {
        $ruleProps=@{
            DisplayName = $name.DisplayName
            Name = $name.Name
            Enabled = $name.Enabled
            Profile = $name.Profile
            Direction = $name.Direction
            Action = $name.Action
            Protocol = $name.Protocol
            Program = $name.Program
            EdgeTraversalPolicy = $name.EdgeTraversalPolicy
        }
        New-NetFirewallRule @ruleProps
    }
    

    And, in order to run some checks (rule name as you mentioned for instance) this could be done right away within the hashtable. For instance you could do something like this;

    $ruleProps=@{
        DisplayName = $name.DisplayName
        Name = if(Get-NetFireWallRule -Name $name.Name -ErrorAction SilentlyContinue) { "$($name.Name)-2" } else { $name.name }
        Enabled = $name.Enabled
        Profile = $name.Profile
        Direction = $name.Direction
        Action = $name.Action
        Protocol = $name.Protocol
        Program = $name.Program
        EdgeTraversalPolicy = $name.EdgeTraversalPolicy
    }
    

    In this hashtable example we run a check right away if we get a hit on that particular rule name. If it's a hit, we add -2 to the end of the name, else we name it as originally intended.

    Alrighty, that was my lunch break - I will check back if you have any follow up questions and double check if I had any typos, sloppy mistakes or whatever, just figured I'd give you an idea of what you can do.

    Edit: Well I came back sooner than I had imagined. In the second hashtable example, quite a bit of the improved readability I mentioned in example 1 actually gets lost. Maybe not with only the one name check but certainly so if you run multiple checks. It will most likely still work but - as I said - the readability might suffer.