Cloud Provider Pod - Get-PodFirewall PowerShell cmdlet


Cloud Provider Pod - Get-PodFirewall PowerShell cmdlet

The VMware Cloud Provider Pod Designer produces a bunch of documentation which is really useful (even if you don’t use the Deployer to actually, err… deploy). One of the options in the Designer is to forgo having NSX deployed in the management stack. Instead, we leave a load of dangling VLANs and let you connect them together with your own external network/security stack. The “icing on the cake” would be if you could not only find the network topology in the Designer downloads (which you can), but also the firewall policies necessary to make the whole shebang work (which you can’t).

Fortunately, all the information we need is inside the configData.cfg file in the Designer bundle, but not in a very friendly format. What we need is a slick tool to extract the firewall policy data and present it in a neat way. Sadly, we don’t have that, but what we do have is a PowerShell script/cmdlet that I wrote to do the job instead…

If you’re the sort who thinks RTFM is for wimps, you can jump straight to the code here.

Background

This post has been sitting in Drafts for a while now. My VMware colleagues who needed to extract copies of the Pod Designer firewall had access to the PowerShell script and tested it in the real world. However, the world has moved on, and the Cloud Provider Pod is destined for bigger and better things now, so the useful shelf-life of this particular script is already past its sell-by date. However, partly as there are some useful bits of PowerShell which I’m sure will come in handy at some point, and partly in case anyone should actually need it, I decided to quietly release the post. If I can get github to work, I’ll make the code available from there too.

I started to write this in rusty Python and PowerShell at the same time. I wanted to use the challenge to learn a little PowerShell but fully expected to complete the tool in Python which I had much more experience with. However, along the journey I discovered some typically MicroSoft style capabilities which made the PowerShell version far more useful with much less effort. I find that if you want to do what Microsoft intended, their tools can be brilliant. But, if you want to go your own way and Microsoft didn’t think that likely, their tools often put up a great deal of resistance. I liked PowerShell so I guess I fell into line with its developers, or they had a broad enough set of use cases that my tiny one was covered.

The cmdlet

The Cmdlet needs PowerShell Core 6.23 or later to run it. It won’t work on the version of PowerShell which comes with Windows Desktop/Server. I used a couple of features from PS Core as I thought I’d get shouted at if I used the Windows-only version of PS anyway, and they made some of the importing much easier.

The code

You can grab the code from GitHub using the usual methods, but if you want to browse the code first, here it is.

  1<#
  2
  3 .Notes
  4 ==============================================================================
  5    Written by:    Steve Dockar
  6    Organization:  VMware 
  7    Twitter:       @SteveDockar
  8    Blog:          notthe.blog
  9    Version:       20191119 - Pretty PortList on PS Object, -strict switch
 10                              and PortsFile.json to override port desc text
 11    Version:       20191112 - Default output now PowerShell objects
 12 ==============================================================================
 13
 14 .Synopsis
 15 Produces firewall policy output from VMware Cloud Provider Pod Designer "configData.cfg" file
 16
 17 .Description
 18 Extracts IP addresses, netmasks and other sundry variables and outputs PSCustomObject for each rule or a text-based firewall policy (using -AsText) for use when deploying non-SDN based Pods.
 19
 20 .Parameter ConfigFile
 21 Absolute or relative path to configData.cfg from Designer Zip file.
 22 .Parameter PortsFile
 23 Absolute or relative path to json file containing port description output overrides.
 24 .Parameter PxeRangeRp00
 25 PXE/TFTP Range for ESXi boot/config
 26 .Parameter North
 27 Output North Edge/Firewall policy
 28 .Parameter South
 29 Output South Edge/Firewall policy
 30 .Parameter AsText
 31 Change output from PowerShell objects to simple (slightly) formatted text.
 32 .Parameter Strict
 33 Change output ports from default Deployer "Any" to Application specific ones.
 34 .Example 
 35 # Default full text-based output
 36 Get-PodFirewall /path/to/configData.cfg "192.168.1.1-192.168.1.99" -AsText
 37 .Example
 38 # Pass Pxe range as subnet
 39 Get-PodFirewall /path/to/configData.cfg "192.168.1.0/24"
 40 .Example
 41 # Output only North Edge/Firewall policy as text.
 42 Get-PodFirewall /path/to/configData.cfg "192.168.1.1-192.168.1.99" -North -AsText
 43 .Example
 44 # Output entire policy as CSV
 45 Get-PodFirewall /path/to/configData.cfg "192.168.1.1-192.168.1.99" | Export-CSV /path/to/output.csv
 46 .Example
 47 # Output entire policy as JSON ( and redirect to file)
 48 Get-PodFirewall /path/to/configData.cfg "192.168.1.1-192.168.1.99" | ConvertTo-JSON >/path/to/output.json
 49 .Example
 50 # Override port descriptions with external ports.json file
 51 Get-PodFirewall /path/to/configData.cfg [-PortsFile] /path/to/ports.json [-PxeRangerp00] "192.168.1.1-192.168.1.99"
 52#>
 53
 54<#
 55    ===================================================================================================================
 56    If you want to replace the text in the Port descriptions, copy the JSON/text below, from "{" to "}" inclusive, into a ports.json file. Edit the "<SVC> (nnn/xxx)" on the right hand side of each line to suit your requirements, and then add -PortsFile '/path/to/ports.json' when you call the script. Your descriptions will then override the built in ones. Don't change the left hand side or the script won't match them. You can also edit $AppIDs in this script directly of course, but you'll lose those changes if you update the script to a newer version.
 57
 58    The examples below have the extra ">" so that you can see -PortsFile has worked before you edit it yourself.
 59
 60    -----8<-----
 61
 62    { 
 63        "dnsudp": ">DNS (53/UDP)",
 64        "http": ">HTTP (80/TCP)",
 65        "https": ">HTTPS (443/TCP)",
 66        "ntp": ">NTP (123/UDP)",
 67        "icmpecho": ">ICMP (Echo/Reply)",
 68        "smtp": ">SMTP (25/TCP)",
 69        "ssh": ">SSH (22/TCP)",
 70        "ftp": ">FTP (20/TCP, 21/TCP)",
 71        "rmq1": ">RMQ (5671/TCP)",
 72        "rmq2": ">RMQ (5672/TCP, 5672/UDP)",
 73        "psql": ">PSQL (5432/TCP)",
 74        "nfs": ">NFS (111/TCP, 111/UDP)",
 75        "cas": ">CAS (9042/TCP)",
 76        "syslog": ">Syslog (514/UDP, 514/TCP, 1514/TCP, 6514/TCP)",
 77        "esx": ">ESX (623/UDP, 5988/TCP, 5989/TCP, 6500/TCP, 8000/TCP, 8001/TCP)",
 78        "902": ">(902/TCP, 902/UDP",
 79        "902T": ">902/TCP",
 80        "903T": ">903/TCP",
 81        "920": ">(920/TCP, 920/UDP",
 82        "8443": "8443/TCP"
 83        "61611T": ">61611/TCP",
 84        "61616T": ">61616/TCP",
 85        "tftp": ">Any(tftp)"
 86        "any": ">Any"
 87    }
 88
 89    ----->8-----
 90    ==================================================================================================================
 91#>
 92
 93Param  (
 94    # Path to Config File
 95    [Parameter(Mandatory=$true)] [string] $ConfigFile,
 96    # Path to Port override file
 97    [Parameter(Mandatory=$false)] [string] $PortsFile,
 98    # PXE Ports (subnet/range)
 99    [Parameter(Mandatory=$false)] [string] $PxeRangeRp00 = "'pxe/tftp range'",
100    # Optional Switches
101    [Parameter(Mandatory=$false)] [switch] $North = $false,
102    [Parameter(Mandatory=$false)] [switch] $South = $false,
103    [Parameter(Mandatory=$false)] [switch] $AsText = $false,
104    [Parameter(Mandatory=$false)] [switch] $Strict = $false
105)
106
107$Config = Get-Content -Path $ConfigFile | ConvertFrom-Json -AsHashtable
108$DhcpRangeRp00 = @( $PxeRangeRp00 ) # Turn param string into array for $Rule(src|dst)
109
110$PSObject = (-not $AsText) 
111
112$In = "    " # Centralise indent for write-rule
113$InSize= $In.Length # Save checking on every Send-Rule
114
115$Firewall = ""
116
117$VcdCellsIp = @( $Config.vcdCellRp0001Ip, $Config.vcdCellRp0002Ip)
118
119# Lookup table to convert AppId to more descriptive text
120if ($PortsFile) {
121    # Write-Host "Importing Port Descriptions"
122    $AppIds = Get-Content -Path $PortsFile | ConvertFrom-Json -AsHashtable  
123} else {
124    $AppIds = @{ 
125        "dnsudp" = "DNS (53/UDP)";
126        "http" = "HTTP (80/TCP)";
127        "https" = "HTTPS (443/TCP)";
128        "ntp" = "NTP (123/UDP)";
129        "icmpecho" = "ICMP (Echo/Reply)";
130        "smtp" = "SMTP (25/TCP)";
131        "ssh" = "SSH (22/TCP)";
132        "ftp" = "FTP (20/TCP, (21/TCP)";
133        "rmq1" = "RMQ (5671/TCP)";
134        "rmq2" = "RMQ (5672/TCP, 5672/UDP)";
135        "psql" = "PSQL (5432/TCP)";   # PostgreSQL
136        "nfs" = "NFS (111/TCP, 111/UDP)";
137        "cas" = "CAS (9042/TCP)";  # Cassandra DB
138        "syslog" = "Syslog (514/UDP, 514/TCP, 1514/TCP, 6514/TCP)";
139        "esx" = "ESX (623/UDP, 5988/TCP, 5989/TCP, 6500/TCP, 8000/TCP, 8001/TCP)";
140        "902" = "(902/TCP, 902/UDP)";
141        "902T" = "902/TCP";
142        "903T" = "903/TCP";
143        "920" = "(920/TCP, 920/UDP)";
144        "8443" = "8443/TCP";
145        "61611T" = "61611/TCP";
146        "61616T" = "61616/TCP";
147        "tftp" = "Any";
148        "any" = "Any"
149    }
150}
151
152function Get-CidrMask {
153    # Pass in "Dotted Quad" mask and get back CIDR length
154    param (
155        [string]$dotMask
156    )
157    
158    $mask = ([ipaddress] $dotMask).Address
159    for ($ml = 0; $mask -ne 0; $ml++) {
160        $mask = $mask -band ($mask -1)
161    }
162    return $ml
163}
164
165function Get-ClusterCount {
166    param (
167        $rpNo = 0
168    )
169    return $Config.$("rp"+ ([string]$rpNo).PadLeft(2, "0") + "ClusterCount")    
170}
171
172function Get-HostCount {
173    param (
174        [string]$clNo = 1
175    )
176
177    return $Config.$("rp00Rc"+ ([string]$clNo).PadLeft(2, "0") + "HostCount")
178    
179}
180
181function Get-HostInfo {
182    param (
183        [Int32]$rp = 0,
184        [Int32]$rc = 0,
185        [Int32]$hostNo = 1,
186        # Valid infoType(s) are: Ip, VsanIp, Mac, VmotionIp, Name, Password, VxlanIp, IpStorageIp
187        [String]$infoType = "Ip"
188    )
189    
190    return $Config.("esxiRp" + ([string]$rp).PadLeft(2,"0") + "Rc" + ([string]$rc).PadLeft(2,"0") + ([string]$hostNo).PadLeft(2,"0") + $infoType) 
191}
192
193function Get-ResourceEsxiRanges {
194    $hostRanges = @()
195    for ( $rc=0; $rc -lt (Get-ClusterCount); $rc++) {
196        $hostRanges += ( $(Get-HostInfo 0 $rc 1 "Ip") + "-" + $(Get-HostInfo 0 $rc (Get-HostCount "1") "Ip") )
197    }
198    return $hostRanges
199}
200
201$ResourceEsxiHosts = Get-ResourceEsxiRanges
202
203# Output related functions
204
205function Get-PrettyPorts {
206    param (
207        [array]$ports
208    )
209    
210    # Build "pretty" ports list
211    $portList = @()
212    foreach ($id in $ports) {
213        if ( $AppIds.ContainsKey($id) ) {
214            $portList += $AppIds.$id
215        } else {
216            $portList += $id
217        }
218    }
219    return $portList
220}
221
222function Write-Rule {
223    param (
224        [string]$description,
225        [array]$srcIps,
226        [array]$dstIps,
227        [array]$ports
228    )
229
230    $portList = Get-PrettyPorts $ports
231        
232    Write-Host -Object ($description)
233    Write-Host -Object ($In + "Source      [" + ( $srcIps -join ", ") + "]" )
234    Write-Host -Object ($In + "Destination [" + ( $dstIps -join ", ") + "]" )
235    Write-Host -Object ($In + "Ports       [" + ( $portList -join ", ") + "]" )
236}
237
238function New-RuleObject {
239    param (
240        # For now each RuleObject holds which fw N/S and the rule number as well as the rule data.
241        [string] $fwNS,
242        [int32] $ruleNo,
243        [string] $description,
244        [array] $srcIps,
245        [array] $dstIps,
246        [array] $ports
247    )
248    
249    $portList = Get-PrettyPorts $ports
250    
251    # Create a custom object
252    $ruleObject = [PSCustomObject]@{
253        RuleId = ($fwNS + "-" + [string]$ruleNo);
254        Firewall = $fwNS;
255        RuleNo = $ruleNo;
256        Description = $description;
257        Source = ( $srcIps -join ", " );
258        Destination = ($dstIps -join ", " );
259        Ports = ($portList -join ", " )
260    }
261    return $ruleObject
262}
263
264function Send-Rule {
265    if ($PSObject) {
266        # Create a FWRule custom object and add to RuleArray
267        New-RuleObject $Firewall $RuleCount $RuleDesc $RuleSrc $RuleDst $RulePorts     
268    } else {
269        # Convenience wrapper as we're using global variables. 'Send' rule vars to 'Write-Rule'
270        $ruleNo = ([string]$script:RuleCount + ".").PadRight($InSize)
271        Write-Rule ($ruleNo + $RuleDesc) $RuleSrc $RuleDst $RulePorts
272    }
273    $Script:RuleCount += 1
274}
275
276# --------------------------------------------- Rules -------------------------------------------
277# For each rule populate Desc, Src, Dst and Ports the call Send-Rule
278
279function Get-NorthFirewall {
280    # Rule 1
281    $RuleDesc = "Outgoing traffic common for all machines in the network"
282    $RuleSrc = @( ($Config.mgmtVcdDmzNetwork + "/" + $(Get-CidrMask $Config.mgmtVcdDmzSubnet)), 
283        ($Config.mgmtVcdNetwork +"/" + $(Get-CidrMask  $Config.mgmtVcdSubnet)),
284        ($Config.mgmtInternalNetwork +"/" + $(Get-CidrMask  $Config.mgmtInternalSubnet)),
285        ($Config.rp00Rc00MgiNetwork +"/" + $(Get-CidrMask  $Config.rp00Rc00MgiSubnet)) )
286    $RuleDst = @( "any" )
287    $RulePorts = @( "dnsudp", "http", "https", "ntp", "icmpecho", "smtp")
288    Send-Rule
289
290    # Rule 2
291    $RuleDesc = "vCD cell server to cassandra database nodes"
292    $RuleSrc = @( $Config.vcdCellRp0001Ip , $Config.vcdCellRp0002Ip )
293    $RuleDst = @( ($Config.vcdPfdbRp0001Ip + "-" + $Config.vcdPfdbRp0004Ip) )
294    $RulePorts = @( "any" ) # Deployer
295    if ($Strict) { $RulePorts = @( "cas" ) } # Actual Ports
296    Send-Rule
297
298    # Rule 3
299    $RuleDesc = "vCD cell server to postgreSQL database"
300    $RuleSrc = $VcdCellsIp
301    $RuleDst = @( $Config.vcdDbRp0001Ip)
302    $RulePorts = @( "any" )
303    if ($Strict) { $RulePorts = @( "psql" ) }
304    Send-Rule
305
306    # Rule 4
307    $RuleDesc = "vCD cell server to Rabbit MQ loadbalancer"
308    $RuleSrc = $VcdCellsIp
309    $RuleDst = @( $Config.vcdRabbLbsRp00Ip )
310    $RulePorts = @( "any" )
311    if ($Strict) { $RulePorts = @( "61611T", "61616T", "rmq2" ) }
312    Send-Rule
313
314    # Rule 5
315    $RuleDesc = "vCD cell server to VCSA Resource Pod"
316    $RuleSrc = $VcdCellsIp
317    $RuleDst = @( $Config.vcsaRp0001Ip )
318    $RulePorts = @( "any" )
319    if ($Strict) { $RulePorts = @( "https", "902T", "903T" ) }
320    Send-Rule
321
322    # Rule 6 - Need to calculate ESXi cluster numbers and sizes for this - See Get-ClusterCound & Get-HostCount!
323    $RuleDesc = "vCD cell server to ESXi hosts Resource Pod"
324    $RuleSrc = $VcdCellsIp
325    $RuleDst = $ResourceEsxiHosts
326    $RulePorts = @( "any" )
327    if ($Strict) { $RulePorts = @( "https", "902T", "903T" ) }
328    Send-Rule
329
330    # Rule 7
331    $RuleDesc = "vCD cell server to NSX Manager Resource Pod"
332    $RuleSrc = $VcdCellsIp
333    $RuleDst = @( $Config.nsxMgrRp0001Ip )
334    $RulePorts = @( "any" )
335    if ($Strict) { $RulePorts = @( "https" ) }
336    Send-Rule
337
338    # Rule 8
339    $RuleDesc = "vRealize Operations Tenant App to vRealize Operations Manager"
340    $RuleSrc = @( $Config.vropsMg0101TenantIp )
341    $RuleDst = @( $Config.vropsMg0101Ip )
342    $RulePorts = @( "any" )
343    if ($Strict) { $RulePorts = @( "https" ) }
344    Send-Rule
345
346    # Rule 9
347    $RuleDesc = "Rabbit MQ nodes to vRealize Orchestrator"
348    $RuleSrc = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip) )
349    $RuleDst = @( $Config.vroMg0101Ip )
350    $RulePorts = @( "any" )
351    if ($Strict) { $RulePorts = @( "rmq2" ) }
352    Send-Rule
353
354    # Rule 10
355    $RuleDesc = "Rabbit MQ nodes to vCloud Director"
356    $RuleSrc = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip) )
357    $RuleDst = $VcdCellsIp
358    $RulePorts = @( "any" )
359    if ($Strict) { $RulePorts = @( "rmq2" ) }
360    Send-Rule
361
362    # Rule 11
363    $RuleDesc = "vRealize Orchestrator to virtual machines and appliances"
364    $RuleSrc = @( $Config.vroMg0101Ip )
365    $RuleDst = $VcdCellsIp
366    $RulePorts = @( "any" )
367    if ($Strict) { $RulePorts = @( "https" ) }
368    Send-Rule
369
370    # Rule 12
371    $RuleDesc = "CPOD install server to vCD cell server and NFS transfer"
372    $RuleSrc = @( $Config.vcppInstallIp )
373    $RuleDst = $VcdCellsIp + $Config.vcdNfsRp0001Ip
374    $RulePorts = @( "any" )
375    if ($Strict) { $RulePorts = @( "https", "nfs", "920" ) }
376    Send-Rule
377
378    # Rule 13
379    $RuleDesc = "CPOD vRealize Orchestrator to vCD cell server and NFS transfer"
380    $RuleSrc = @( $Config.vroMg0101Ip )
381    $RuleDst = $VcdCellsIp + $Config.vcdNfsRp0001Ip
382    $RulePorts = @( "any" )
383    if ($Strict) { $RulePorts = @( "https", "nfs", "920" ) }
384    Send-Rule
385
386    # Rule 14
387    $RuleDesc = "vCD cell server to cpod install"
388    $RuleSrc = $VcdCellsIp
389    $RuleDst = @( $Config.vcppInstallIp )
390    $RulePorts = @( "any" )
391    if ($Strict) { $RulePorts = @( "https" ) }
392    Send-Rule
393        
394    # Rule 15
395    $RuleDesc = "Incoming to vCD LBS UI"
396    $RuleSrc = @( "any" )
397    $RuleDst = @( $Config.mgmtDmzVcdUiIp )
398    $RulePorts = @( "https" )
399    Send-Rule
400
401    # Rule 16
402    $RuleDesc = "Incoming to vCD LBS Console"
403    $RuleSrc = @( "any" )
404    $RuleDst = @( $Config.mgmtDmzVcdConsoleIp )
405    $RulePorts = @( "8443" )
406    Send-Rule
407
408    # Rule 17
409    $RuleDesc = "Incoming to vCD tenant App"
410    $RuleSrc = @( "any" )
411    $RuleDst = @( $Config.mgmtDmzVropsTenantIp )
412    $RulePorts = @( "https" )
413    if ($Strict) { $RulePorts = @( "http", "https" ) }
414    Send-Rule
415
416    # Rule 18
417    $RuleDesc = "vCD cell server to cpod install"
418    $RuleSrc = $VcdCellsIp
419    $RuleDst = @( $Config.vrliMg0101Ip )
420    $RulePorts = @( "any" )
421    if ($Strict) { $RulePorts = @( "https" ) }
422    Send-Rule
423
424    # [Rule 19] 
425    if ($Config.vropsMg0101Deploy -eq "true") {
426        $RuleDesc = "vROPS tenant app to RabbitMQ"
427        $RuleSrc = @( $Config.vropsMg0101TenantIp )
428        $RuleDst = @( $Config.vcdRabbLbsRp00Ip )
429        $RulePorts = @( "any" )
430        if ($Strict) { $RulePorts = @( "rmq2" ) }
431        Send-Rule
432    }
433}
434
435function Get-SouthFirewall {
436    # Rule 1
437    $RuleDesc = "Outgoing traffic common for all machines in the network"
438	$RuleSrc = @( ($Config.mgmtVcdDmzNetwork + "/" + $(Get-CidrMask $Config.mgmtVcdDmzSubnet)) , 
439        ($Config.mgmtVcdNetwork +"/" + $(Get-CidrMask  $Config.mgmtVcdSubnet)) ,
440        ($Config.mgmtInternalNetwork +"/" + $(Get-CidrMask  $Config.mgmtInternalSubnet)) ,
441        ($Config.rp00Rc00MgiNetwork +"/" + $(Get-CidrMask  $Config.rp00Rc00MgiSubnet)) )
442    $RuleDst = @( "any" )
443    $RulePorts = @( "dnsudp", "http", "https", "ntp", "icmpecho", "smtp")
444    Send-Rule
445
446    # Rule 2
447    $RuleDesc = "FTP traffic for Centos machines to CPOD deployer"
448    $RuleSrc = @( ($Config.vcdPfdbRp0001Ip + "-" + $Config.vcdPfdbRp0004Ip),
449		($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip),
450		($Config.vcdCellRp0001Ip + "-" + $Config.vcdCellRp0002Ip),
451		$Config.vcdNfsRp0001Ip,
452		$Config.vcdDbRp0001Ip ) 
453	$RuleDst = @( $Config.vcppInstallIp )
454	$RulePorts = @( "ftp" )
455    Send-Rule
456    
457    # Rule 3
458    $RuleDesc = "vCD cell server to cassandra database nodes"
459    $RuleSrc = $VcdCellsIp
460    $RuleDst = @( $Config.vcdPfdbRp0001Ip + "-" + $Config.vcdPfdbRp0004Ip )
461    $RulePorts = @( "any" )
462    if ($Strict) { $RulePorts = @( "cas" ) }
463    Send-Rule
464
465    # Rule 4
466    $RuleDesc = "vCD cell server to postgreSQL database"
467    $RuleSrc = $VcdCellsIp
468    $RuleDst = @( $Config.vcdDbRp0001Ip)
469    $RulePorts = @( "any" )
470    if ($Strict) { $RulePorts = @( "psql" ) }
471    Send-Rule
472
473    # Rule 5
474    $RuleDesc = "vCD cell server to Rabbit MQ loadbalancer"
475    $RuleSrc = $VcdCellsIp
476    $RuleDst = @( $Config.vcdRabbLbsRp00Ip )
477    $RulePorts = @( "any" )
478    if ($Strict) { $RulePorts = @( "61611T", "61616T", "rmq2" ) }
479    Send-Rule
480
481    # Rule 6
482    $RuleDesc = "vCD cell server to VCSA Resource Pod"
483    $RuleSrc = $VcdCellsIp
484    $RuleDst = @( $Config.vcsaRp0001Ip)
485    $RulePorts = @( "any" )
486    if ($Strict) { $RulePorts = @( "https", "902T", "903T" ) }
487    Send-Rule
488
489    # Rule 7
490    $RuleDesc = "vCD cell server to ESXi hosts Resource Pod"
491    $RuleSrc = $VcdCellsIp
492    $RuleDst = $ResourceEsxiHosts
493    $RulePorts = @( "any" )
494    if ($Strict) { $RulePorts = @( "https", "902T", "903T" ) }
495    Send-Rule
496
497    # Rule 8
498    $RuleDesc = "vCD cell server to NSX Manager Resource Pod"
499    $RuleSrc = $VcdCellsIp
500    $RuleDst = @( $Config.nsxMgrRp0001Ip )
501    $RulePorts = @( "any" )
502    if ($Strict) { $RulePorts = @( "https" ) }
503    Send-Rule
504
505    # Rule 9
506    $RuleDesc = "vRealize Operations Tenant App to vRealize Operations Manager"
507    $RuleSrc = @( $Config.vropsMg0101TenantIp )
508    $RuleDst = @( $Config.vropsMg0101Ip )
509    $RulePorts = @( "any" )
510    if ($Strict) { $RulePorts = @( "https" ) }
511    Send-Rule
512
513    # Rule 10
514    $RuleDesc = "Rabbit MQ nodes to vRealize Orchestrator"
515    $RuleSrc = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip) )
516    $RuleDst = @( $Config.vroMg0101Ip )
517    $RulePorts = @( "any" )
518    if ($Strict) { $RulePorts = @( "rmq2" ) }
519    Send-Rule
520
521    # Rule 11
522    $RuleDesc = "Rabbit MQ nodes to vCloud Director"
523    $RuleSrc = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip) )
524    $RuleDst = $VcdCellsIp
525    $RulePorts = @( "any" )
526    if ($Strict) { $RulePorts = @( "rmq2" ) }
527    Send-Rule
528
529    # Rule 12
530    $RuleDesc = "vRealize Orchestrator to virtual machines and appliances"
531    $RuleSrc = @( $Config.vroMg0101Ip )
532    $RuleDst = $VcdCellsIp
533    $RulePorts = @( "any" )
534    if ($Strict) { $RulePorts = @( "https" ) }
535    Send-Rule
536
537    # Rule 13
538    $RuleDesc = "CPOD install server to vCD cell server and NFS transfer"
539    $RuleSrc = @( $Config.vcppInstallIp )
540    $RuleDst = $VcdCellsIp + $Config.vcdNfsRp0001Ip
541    $RulePorts = @( "any" )
542    if ($Strict) { $RulePorts = @( "https", "nfs", "920" ) }
543    Send-Rule
544
545    # Rule 14
546    $RuleDesc = "CPOD vRealize Orchestrator to vCD cell server and NFS transfer"
547    $RuleSrc = @( $Config.vroMg0101Ip )
548    $RuleDst = $VcdCellsIp + $Config.vcdNfsRp0001Ip
549    $RulePorts = @( "any" )
550    if ($Strict) { $RulePorts = @( "https", "nfs", "920" ) }
551    Send-Rule
552
553    # Rule 15
554    $RuleDesc = "vCenter resource pod to ESXi hosts Resource Pod"
555    $RuleSrc = @( $Config.vcsaRp0001Ip)
556    $RuleDst = $ResourceEsxiHosts
557    $RulePorts = @( "any" )
558    if ($Strict) { $RulePorts = @( "http", "https", "902", "esx" ) }
559    Send-Rule
560
561    # Rule 16
562    $RuleDesc = "NSX Manager resource pod to ESXi hosts Resource Pod"
563    $RuleSrc = @( $Config.nsxMgrRp0001Ip)
564    $RuleDst = $ResourceEsxiHosts
565    $RulePorts = @( "any" )
566    if ($Strict) { $RulePorts = @( "https", "902T" ) }
567    Send-Rule
568
569    # Rule 17
570    $RuleDesc = "Cpod vRO to ESXi hosts Resource Pod"
571    $RuleSrc = @( $Config.vroMg0101Ip)
572    $RuleDst = $ResourceEsxiHosts
573    $RulePorts = @( "any" )
574    if ($Strict) { $RulePorts = @( "ssh", "https" ) }
575    Send-Rule
576
577    # Rule 18
578    $RuleDesc = "CPOD install server to linux VMs mgmtVcdNetwork and new CPOD install server"
579    $RuleSrc = @( $Config.vcppInstallIp)
580    $RuleDst = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip),
581 		($Config.vcdPfdbRp0001Ip + "-" + $Config.vcdPfdbRp0004Ip),
582         $Config.vcppInstallRp00Rc00Ip )
583    $RulePorts = @( "any" )
584    if ($Strict) { $RulePorts = @( "ssh" ) }
585    Send-Rule
586
587    # Rule 19
588    $RuleDesc = "CPOD vRO to virtual machines and appliances and new CPOD install server"
589    $RuleSrc = @( $Config.vroMg0101Ip)
590    $RuleDst = @( ($Config.vcdRabbRp0001Ip + "-" + $Config.vcdRabbRp0002Ip),
591 		($Config.vcdPfdbRp0001Ip + "-" + $Config.vcdPfdbRp0004Ip),
592 		$Config.vcppInstallRp00Rc00Ip,
593         $Config.vcdDbRp0001Ip )
594    $RulePorts = @( "any" )
595    if ($Strict) { $RulePorts = @( "https" ) }
596    Send-Rule
597
598    # Rule 20
599    $RuleDesc = "NSX controller cluster rp00 to NSX manager rp00"
600    $RuleSrc = @( ($Config.nsxCtrlRp0001Ip + "-" + $Config.nsxCtrlRp0003Ip) )
601    $RuleDst = @( $Config.nsxMgrRp0001Ip) 
602    $RulePorts = @( "any" )
603    if ($Strict) { $RulePorts = @( "https" ) }
604    Send-Rule
605
606    # Rule 21 
607    $RuleDesc = "ESXi hosts resource pod to vRNI proxy"
608    $RuleSrc = $ResourceEsxiHosts
609    $RuleDst = @( $Config.vrniMg0101ProxyIp)
610    $RulePorts = @( "any" )
611    if ($Strict) { $RulePorts = @( "https" ) }
612    Send-Rule
613
614    # Rule 22
615    $RuleDesc = "RP00 Hosts to cpod-install for TFTP"
616    $RuleSrc = $ResourceEsxiHosts
617    $RuleDst = @( $Config.vcppInstallIp )
618    $RulePorts = @( "any" )
619    if ($Strict) { $RulePorts = @( "tftp" ) }
620    Send-Rule
621
622    # Rule 23
623    $RuleDesc = "RP00 ip range to cpod-install for TFTP"
624    $RuleSrc = $DhcpRangeRp00 # dhcp range used for TFTP/PXE boot
625    $RuleDst = @( $Config.vcppInstallIp )
626    $RulePorts = @( "any" )
627    if ($Strict) { $RulePorts = @( "tftp" ) }
628    Send-Rule
629
630    # Rule 24
631    $RuleDesc = "vCD cell server to cpod install"
632    $RuleSrc = $VcdCellsIp
633    $RuleDst = @( $Config.vcppInstallIp )
634    $RulePorts = @( "any" )
635    if ($Strict) { $RulePorts = @( "https" ) }
636    Send-Rule
637
638    # Rule 25
639    $RuleDesc = "RP00 Hosts to RP00 NSX Manager"
640    $RuleSrc = $ResourceEsxiHosts
641    $RuleDst = @( $Config.nsxMgrRp0001Ip)
642    $RulePorts = @( "any" )
643    if ($Strict) { $RulePorts = @( "rmq1" ) }
644    Send-Rule
645
646    # Rule 26
647    $RuleDesc = "RP00 Hosts to rp00 VCSA"
648    $RuleSrc = $ResourceEsxiHosts
649    $RuleDst = @( $Config.vcsaRp0001Ip )
650    $RulePorts = @( "any" )
651    if ($Strict) { $RulePorts = @( "http", "https", "902", "esx" ) }
652    Send-Rule
653
654    # Rule 27
655    $RuleDesc = "RP00 Hosts to vRealize Log Insight"
656    $RuleSrc = $ResourceEsxiHosts
657    $RuleDst = @( $Config.vrliMg0101Ip )
658    $RulePorts = @( "any" )
659    if ($Strict) { $RulePorts = @( "syslog" ) }
660    Send-Rule
661
662    # Rule 28
663    $RuleDesc = "vRNI Proxy to RP00 NSX Controller"
664    $RuleSrc = @( $Config.vrniMg0101ProxyIp )
665    $RuleDst = @( ($Config.nsxCtrlRp0001Ip + "-" + $Config.nsxCtrlRp0003Ip) )
666    $RulePorts = @( "any" )
667    if ($Strict) { $RulePorts = @( "https" ) }
668    Send-Rule
669
670    # Rule 29
671    $RuleDesc = "vCD cell server to vRealize Log Insight"
672    $RuleSrc = $VcdCellsIp
673    $RuleDst = @( $Config.vrliMg0101Ip )
674    $RulePorts = @( "any" )
675    if ($Strict) { $RulePorts = @( "syslog" ) }
676    Send-Rule
677
678    # Rule 30
679    if ($Config.vropsMg0101Deploy -eq "true") {
680        $RuleDesc = "vROPS tenant app to RabbitMQ"
681        $RuleSrc = @( $Config.vropsMg0101TenantIp )
682        $RuleDst = @( $Config.vcdRabbLbsRp00Ip )
683        $RulePorts = @( "any" )
684        if ($Strict) { $RulePorts = @( "rmq2" ) }
685        Send-Rule
686    }
687}
688
689# Switch Logic
690# When N/S both still false (no switch) print both.
691# If N -xor S print the true one
692# If both are true print both.
693
694# If xor returns false print both (-xor has precedence over -not)
695if ( -not $North -xor $South ) {
696    $North = $true
697    $South = $true
698}
699if ($North) {
700    $RuleCount = 1
701    $Firewall = "North"
702    if (-not $PSObject) { Write-Host -Object ("`nNorth Firewall Rulebase`n") }
703    Get-NorthFirewall
704}
705if ($South) {
706    $RuleCount = 1
707    $Firewall = "South"
708    if (-not $PSObject) { Write-Host -Object ("`nSouth Firewall Rulebase`n") }
709    Get-SouthFirewall
710}

The cmdlet holds a sanitized version of the production code which configures the NSX environment, in particular the two Edge firewall policies. I converted the original into a more readable format and hacked together some code to extract the variables from the configData file and output it either to screen, or as a PowerShell object. That latter is quite handy if you want to pipe the result into another cmdlet to do something even more useful with the data.

There are two firewalls in the ProviderPod topology, and we have cmdlet switches (and some embedded logic) to decide which of them you want to output. There’s also an option to swap the terms used in the descriptions of the flows. You can copy the example out of the code, save and edit it, and then have the cmdlet read it in and replace the descriptions with your own.

Caveat Emptor

This is in no way a PowerShell tutorial. There may be better, more PowerShelly was of doing things, and even I could have made the code more compact and less verbose. But, I thought I might have to come and revisit it every time we changed the policy in ProviderPod. So, following PEP20 I went with the ‘readability counts’ philosophy otherwise I’d have no chance of remembering how it all worked!

Feel free to share this post...

comments powered by Disqus