PowerCLI Collection: PowerNSX Horizon Jumpstart script ready to rumble

Reading Time: 5 minutes

A few blog posts ago (https://www.pascalswereld.nl/2017/08/24/nsx-for-desktop-jumpstart-microsegmentation-with-horizon-service-installer-fling/) I wrote about using the Horizon Service Installer fling for adding Horizon services to NSX for Desktop. From that blog post, I have been continuing to evolve the services file with services, sections, and rules that will normally appear in an EUC solution with VMware products. I tried to maintain the services yml file to keep on working with the fling. Currently you still can, however I don’t know how long this will be.

Sections - This One

And this is because of another part I am working on, using PowerNSX for adding the services file to the NSX environment, and in turn, replace the need of the fling. You can read about me starting this at the post PowerCLI Collection: PowerNSX Desktop Jumpstart and process YAML (yml) config file. And this blog post is about explaining the first version to reach feature parity to the Horizon Service installer fling. The NSXHorizonJumpstart script now reads and adds to the complete yml file to NSX services, service groups, security groups and adds the Firewall sections with the firewall groups.

Rules Example

You can find both the services file as the current version of the script from the master branch at: https://github.com/Paikke/NSXHorizonJumpstart.

Walkthrough of the NSXHorizonJumpstart script

Script Stages

Currently, there is a working test version released in the master branch. The script currently does:

  • Check for existence of yml file
  • read contents of yml file
  • Get input user for connecting to vCenter / NSX Manager
  • Connect
  • Loop through Firewall services and checks if they exist (Get-NsxService)
  • Log actions (can be turned off in settings part)
  • Add services to NSX if they do not exist (New-NsxService)
  • Loop through ServiceGroups and check if they exist (Get-NSxServiceGroup)
  • Add Servicegroups in NSX when not existing (New-NsxServiceGroup)
  • within the service groups adds one or more children. (Get-NsxService for id and Get-NsxServiceGroup | Add-NsxServiceGroupMember)
  • Empty service groups with no children in the yml configuration will throw error
  • Loop through SecurityGroups and check if they exist (Get-NsxSecurityGroup)
  • Add SecurityGroup in NSX when not existing (New-NsxSecurityGroup)
  • Empty firewall section in the yml configuration will throw error
  • Loop through FirewallSections and check if they exist and have rules (Get-NsxFirewallSection)
  • Add firewall section in NSX when not existing (New-NsxFirewallSection)
  • Empty rule components like source and destination will throw error
  • Adds within that section Firewall rules (Get-NsxFirewallSection | New-NsxFireWallRule)

Especially the part of matching the sections, firewall rules and multiple security groups as source or destination was a little exciting for my brain. But my brain, in the end, managed to do this. The script first checks the sections and collects the named firewall rules when not existing as a firewall section. The script then returns to the yml configuration and checks the firewall rules, if they don’t exist (preferably only in one section). Collect the source and destination security groups (and count these for the loop in getting the objects back from NSX) and service groups from NSX, this will be more than one. And continue for each loop for the next section.

A small snippet using the above, starting from getting the source security groups from NSX within the Firewall Section loop (the section has been created when not existing and information was captured in the variables used)

$itemFWRuleSrcID = @()
For ($i = 0; $i -lt $RuleSplitCount; $i++){
ForEach($itemRuleSourceSplit in $itemFWRuleSourceSplit){
If ($logon -eq “Yes”) { Write-Log “[DEBUG] Getting Source SecurityGroup ID for $itemRuleSourceSplit” }
$SourceArgumentStr = $itemRuleSourceSplit
$itemFWRuleSrcID += Get-NsxSecurityGroup -Name $SourceArgumentStr -connection $NSXConnection
$itemFWRuleDestID = @()
For ($z = 0; $z -lt $DestSplitCount; $z++){
ForEach($itemRuleDestSplit in $itemFWRuleDestSplit){
If ($logon -eq “Yes”) { Write-Log “[DEBUG] Getting Destination SecurityGroup ID for $itemRuleDestSplit” }
$DestArgumentStr = $itemRuleDestSplit
$itemFWRuleDestID += Get-NsxSecurityGroup -Name $DestArgumentStr -connection $NSXConnection
$SrcArgument = $itemFWRuleSrcID
$DestArgument = $itemFWRuleDestID
If ($logon -eq “Yes”) { Write-Log “[DEBUG] Sources Argument : $SrcArgument.name” }
If ($logon -eq “Yes”) { Write-Log “[DEBUG] Dest Argument : $DestArgument.name” }
# Get Servicegroup ID’s for service
# PowerNSX checks on XML object if -service is a serviceGroup
$SvcGrpArgument = Get-NsxServiceGroup -Name $itemFWRuleserviceGroup -connection $NSXConnection

If ($logon -eq “Yes”) { Write-Log “[DEBUG] ServiceGrp Argument : $SvcGrpArgument” }

# Add new rule to Previously created section
If ($logon -eq “Yes”) { Write-Log “Adding new rule $itemFWRuleName to Section $itemFWSecName” }
Get-NsxFirewallSection -name $itemFWSecName -connection $NSXConnection | New-NsxFirewallRule -name $itemFWRuleName -Source $SrcArgument -Destination $DestArgument -Action $itemFWRuleAction -Service $SvcGrpArgument -Connection $NSXConnection

We will use as the Section object as input when creating the rules. Using the earlier created Firewall Section variable (created as $itemFWSecName) and Get-NsxFirewallSection as piped input for the section with New-NsxFirewallRule cmdlet. And the rules are added….

In a completely empty NSX environment (just basic NSX Manager and hosts prepped) this script takes about ten minutes to insert the objects.


PowerNSX is essential for this script, therefore please ensure you have the latest version of PowerNSX installed. PowerNSX can be updated in an administrative PowerShell terminal with the following command (or use -User for installing in the user context):

Update-PowerNsx master (tested with master branch of 09/16/2017)

General rule of thumb for the configuration

Zero trust, therefore last NSX rule is a “Deny any/any rule”. For example the default rule. There are Reject rules in the service configuration file, but these are for demonstration only the NSX Jumpstart rules should have allow as action only together with the Deny any.

Source or Destination “any” should never be used with the exception of the “Deny any/any rule”. The configuration file works with groups. However, I noticed that a typo as string here could mean an any been inserted. Don’t know if this was a fluke or a bug.

Rules utilize “Security Groups”. The configuration does not setup members, you will have to do this yourself. Go with Security Groups that are set up with dynamic entity members which in turn can be Security Tags or LDAP groups for example.

Currently, the rules are applied to the DFW as a whole. This can also somewhat be targetted to a specific object in your environment.

Feature Parity, does that means stopping?

No, I still will be evolving the script further. Currently, ideas are to add overwrite routines, reporting routines and going further with deploying Edges for load balancing. And work a bit on the documentation part on Github. If you have ideas, please drop me a note or join in at https://github.com/Paikke/NSXHorizonJumpstart.

Important note

The same goes for this set of rules and script, as with VMware Flings: use with caution and test test test before going anywhere near what some call production.

– Enjoy the script for so far!

Sources: https://labs.vmware.com/flings/horizon-service-installer-for-nsx, https://powernsx.github.io/

Leave a Reply

Your email address will not be published. Required fields are marked *