Using PowerNSX to Build NSX Distributed Firewall Rules

I've been helping one of my customers set up a proof of concept NSX implementation, which has involved configuring and then destroying several firewall designs.  In order to speed up this process, we've had to get pretty good at using PowerNSX to script out the creation of those NSX firewall rules (and other security objects).

First, how do you get PowerNSX?  Just like PowerCLI!  Open up your PowerShell window, then use this command: Install-Module PowerNSX

Now that you've got PowerNSX installed, take a moment to look at what it does for you.  Look at all of the available cmdlets by using: get-command -module PowerNSX

There's a lot going on there!  In general, the PowerNSX cmdlets use the normal PowerShell verbs: get, set, add, remove, and new, and the nouns are prefixed with NSX.  So, if you're using tab completion to figure out what command you're doing, <verb>-nsx... is usually a pretty safe place to start.  For example, if I want to get my security tags, I would use get-nsxSecurityTag.  So, what commands did we find especially useful when creating our firewall configurations?

The first thing that we did was to break up our firewall into logical sections.  When creating firewall rules, it's very easy to place them into a specific section, and the sections can be easily ordered via the GUI.  We designed our firewall rule logic so that the order of the rules within a section would be completely irrelevant, so long as each rule was set up in its correct section.  Creating sections via PowerNSX is really easy, although you need to order them via the GUI: New-NSXFirewallSection <Section Name>

Our firewall rules were all based on Security Groups, so the next important thing for us to do was to create those Security Groups.  The command for that is New-NSXSecurityGroup <Group Name>

To populate those Security Groups, we decided to generally use Security Tags (which would be assigned to VMs).  It's easy to create those tags: New-NSXSecurityTag <Tag Name>

We had a few use cases (such as the F5 VIP to DMZ traffic, for example) where we could not leverage tags, so we had to define some IP Address ranges as IP Sets.  You've probably guessed the command that we used there: New-NSXIPSet -name <IP Set Name> -IPAddress <IP Address>.  The IPAddress field can be provided in a lot of ways, either an individual IP Address (, a range of IP Addresses (, or as a whole subnet (  In addition, it accepts an array of these IP Address strings, so you can get pretty detailed here.

With our Security Tags and IP Sets created, we had to add them to our Security Groups (so that our rules would be able to do something).  That's easily done like this: Get-NSXSecurityGroup <Group Name> | Add-NSXSecurityGroupMember -Member (get-NSXSecurityTag <Tag Name>)

That example would add all VMs that have that Security Tag to that Security Group (and that's dynamic, as VM tags are changed, their group membership also changes).  The -Member argument accepts just about any object that you could logically include as a member of a Security Group, so you could feed it a VM object via get-vm <VM name> or an IP Set object via get-NSXIPSet <Set Name> just as easily.

The Security Group membership is well sorted out by this point, but we need to assign our Security Tags to our VMs so that they'll inherit behaviors from the correct Security Groups.  You can add a VM to a Security Group like this: Get-VM <VM Name> | New-NSXSecurityTagAssignment -ApplyTag -SecurityTag (Get-NSXSecurityTag <Tag Name>)

With the VMs tagged and the Security Groups populated, we can create some Firewall rules in those sections that we created earlier.  This will use the New-NSXFirewallRule cmdlet, which has a bunch of options.  One very common use that we had was to create a rule that would block all traffic originating from outside of a given Security Group from getting into that Security Group.  To do that, we used a command like this: Get-NSXFirewallSection <Section Name> | New-NSXFirewallRule -name <Firewall Rule Name> -Source (Get-NSXSecurityGroup <Group Name>) -NegateSource -Destination (Get-NSXSecurityGroup <Group Name>) -Action deny

I want to note that that previous command is fairly inefficient; I just wrote it out that way to make it more obvious what it's doing.  If you're making a bunch of rules, you'd be best served by capturing the output of Get-NSXSecurityGroup into a variable and then searching through that for your specific object with | ? instead of running a new Get-* every time.

So, how do you put all of this together?  Well, that's going to be very environment specific.  Things like creating Firewall Sections, Security Groups, Security Tags and IP Sets are probably best done by using a spreadsheet as input and parsing through it line by line to create each of those things.  If you have strong naming conventions, you may be able to use a regular expression to assign VMs Security Tags by something like this:
Get-VM | ? {$ -match "DMZ"} | New-NSXSecurityTagAssignment -ApplyTag -SecurityTag (get-NSXSecurityTag DMZ)

That, in turn, can be automated even further, as we have a fairly repetitive process that requires 2 variables: a Regular Express ("DMZ" in this case) and the name of the Security Tag associated with that Regular Express (also "DMZ" in this example).  So, you could make yourself a spreadsheet with 2 columns: RegEx and SecTag, then use a little loop to go through it and assign those tags to the VMs caught by each RegEx:

$allVMs = get-vm
$allTags = get-NSXSecurityTag
foreach ($secDefinition in (import-csv <Spreadsheet with those columns>){
$allVMs | ? {$ -match $secDefinition.RegEx} | New-NSXSecurityTagAssignment -ApplyTag -SecurityTag ($allTags | ? {$ -eq $secDefinition.SecTag})

So, that's what we did!  Hopefully this all helps someone to build out their NSX Firewall a little more easily than doing everything through a web portal.


Popular posts from this blog

Deleting Orphaned (AKA Zombie) VMDK Files

Clone a Standard vSwitch from one ESXi Host to Another

vCenter Server Appliance Crash due to Full /Storage/SEAT Partition