With the release of PowerCLI 12.6, a new module VMware.Sdk.Nsx.Policy was added to provide PowerShell binding for NSX Policy Manager APIs. This new module is auto generated from the NSX Policy API spec exposing all the features related to policy objects in NSX. The module also exposes cmdlets to Create/Edit/Delete NSX objects. This blog explains the use of PowerCLI NSX module, goes through all the different ways new cmdlets can be found and shows how to view documentation on the cmdlets with examples.
Navigating the new cmdlets
Along with the cmdlets to connect, disconnect and modify the NSX objects, there are a few helper cmdlets that make looking up new relevant cmdlets very easy.
The first one is Get-NsxOperation. This is a new feature in VMware.Sdk.Nsx.Policy and is ideal with you need to find the PowerCLI command that corresponds to an API operation and vice versa. You can also narrow down the search result using Where-Object and Select-Object filters.
Example:
1 |
Get-NsxOperation -Method GET -Path '/infra/segments' |
Since the cmdlets by default returns all paths that start with /infra/segments you can also limit the search to exact match with client-side filter:
1 |
Get-NsxOperation -Method get -Path '/infra/segments' | Where-Object {$_.Path -eq '/infra/segments'} |
Also remember that -Path parameter has autocomplete feature which makes it easier to navigate through the URLs. This is probably the most useful parameter. You can either enter the known URI path of the object or better yet, use the autocomplete feature to find one.
A sample run of the above command:
The Name corresponds to the name of the operation. This can typically be used with an Invoke-<Name> operation. The Parameters contains only a subset of the full list. The full list can be obtained by doing the Get-Help Invoke-<Name> operation. All the values returned in the above output is autogenerated from the API spec.
Once the cmdlet is known, full details about the cmdlet can be found using the Get-Help command.
As seen, the help includes the full list of parameters, description and when used with -Full or -Example parameter provides code snippets.
What if you know the object you are working on but are not sure of the cmdlets available for that object? Then, the Get-Command provided by PowerShell is your friend. Pass in VMware.Sdk.Nsx.Policy as the module and you can do a regular expression search.
Example:
1 |
Get-Command –Module VMware.Sdk.Nsx.Policy -name Invoke-*Tier0* |
To list all the cmdlets, aliases, functions, filters, scripts and applications in the module, just do a
1 |
Get-Command –Module VMware.Sdk.Nsx.Policy |
Note that the result of the above command can take a couple of seconds to return.
Authentication
New cmdlets are available to connect to NSX. To connect to an On-Prem NSX:
1 |
Connect-NsxServer -Server 192.168.10.10 -User admin -Password myNSXPassword!@# |
To connect to NSX in a VMConAWS environment:
1 2 3 4 5 6 7 8 |
$apiToken = 'hr68qyp.......KSNycF4Rmm4KLxFpn4' $sddcName = 'pcli-aws-group-1' $vmcServer = Connect-VmcServer -ApiToken $apiToken $accessToken = $vmcServer.GetAccessToken() $org = Get-VmcOrganization $sddc = Get-VmcSddc -Name $sddcName Connect-NsxVmcServer -AccessToken $accessToken -OrgId $org.Id -SddcId $sddc.Id |
Cmdlet Usage
Cmdlet usage is best understood with a usecase. Consider a 3-tier routing topology with security. The topology will include a Tier-0 Gateway connected to a Tier-1 Gateway. To keep things simple, add a single Segment attached to the Tier-1 Gateway. Micro-Segmentation can be achieved by creating dynamic NSX Groups and Distributed Firewall Rules. The section below explains how all the components are created
Creating a Tier-0 Gateway:
To find the suitable cmdlet, use the Get-Command helper cmdlet:
You can see that there is an Invoke-PatchTier0 cmdlet. To find out the full usage of this cmdlet, use the Get-Help cmdlet:
Next, a new Tier-0 object needs to be created. There are two steps to this. First an input object is created on the client side using the Initialize-<Object> command. This input object will contain all the attributes of a Tier-0 object. Once the required attributes are set, the object is created on the server using the Invoke-Patch<Object> or Invoke-CreateOrPatch<Object> commands.
Just like before, use the Get-Command helper cmdlet to find the right cmdlet for Tier0
In this case, the Initialize-Tier0 is the cmdlet to use. Using the Get-Help Initialize-Tier0 -Full cmdlet, all the required and optional parameters can be found.
Now, all the information needed to create a Tier-0 Gateway is available. Putting it together, the following code snippet will create a new Tier-0 Gateway:
1 2 |
$t0 = Initialize-Tier0 -ArpLimit 5000 -DisplayName $T0GatewayName $createdT0 = Invoke-PatchTier0 -Tier0Id $T0GatewayName -Tier0 $t0 |
Creating a Tier-1 Gateway
Using the Get-Command, Get-NsxOperation and Get-Help helper cmdlets, the cmdlets we need to create a Tier-1 Gateway are Invoke-PatchTier1 and Initialize-Tier1. Just like above, creating a Tier-1 Gateway can be done with:
1 2 3 4 |
$t0s = Invoke-ListTier0s $t0 = $t0s.Results | where {$_.DisplayName -eq $T0GatewayName} $t1 = Initialize-Tier1 -ArpLimit 5000 -DisplayName $T1GatewayName -Tier0Path $t0.Path $createdT1 = Invoke-PatchTier1 -Tier1Id $T1GatewayName -Tier1 $t1 |
But let’s add one requirement that the Tier-1 Gateway has to be deployed on a specific Edge Cluster with display name $edgeClusterName.
Based on response body of the API GET /policy/api/v1/global-infra/tier-1s/<tier-1-id>/locale-services/<locale-services-id>, the Edge Cluster association is done by assigning the Edge Cluster Path to the default Locale Service that associated with the Tier-1 Gateway.
Falling back on the Get-Command helper cmdlets for this, a query to search for all List cmdlets on the Edge Clusters can be done. Filtering out specific keywords gives the following list:
From the list, the correct cmdlet to use is Invoke-ListEdgeClustersForEnforcementPoint.
Snippet to get the correct Edge Cluster information:
1 2 |
$edgeClusters = Invoke-ListEdgeClustersForEnforcementPoint -SiteId default -EnforcementPointId default $edgeCluster = $edgeClusters.Results | where {$_.Displayname -eq $edgeClusterName} |
Now, Create a new client-side object for LocaleService with Edge Cluster Path.
1 |
$localeService = Initialize-LocaleServices -EdgeClusterPath $edgeCluster.Path -DisplayName default -Id default |
To reflect this change on the server side, a PATCH call needs to be made.
1 |
Invoke-PatchTier1LocaleServices -Tier1Id $createdT1.Id -LocaleServices $localeService -LocaleServicesId default |
Creating a Segment
Creation of a Segment follows a similar pattern. A new Segment requires a Transport Zone to be specified and a Subnet assigned to it. Again, based on the API GET /policy/api/v1/infra/sites/<site-id>/enforcement-points, Transport Zones are represented in Policy as an Enforcement Point. So, get the Transport Zone details using:
1 2 |
$tzs = Invoke-ListTransportZonesForEnforcementPoint -EnforcementpointId "default" -SiteId "default" $tz = $tzs.Results | where {$_.DisplayName -eq $TransportZone} |
A Segment also needs a Subnet allocation. For this, a new Subnet object is first initialized and then the Segment client object is created. Finally, the Segment is created on NSX using the Invoke-PatchInfraSegment
1 2 3 4 5 6 7 8 |
$subnet = Initialize-SegmentSubnet -GatewayAddress $GatewayCIDR $t1s = Invoke-ListTier1 $t1 = $t1s.Results | where {$_.DisplayName -eq $T1GatewayName} $segment = Initialize-Segment -DisplayName $SegmentName -TransportZonePath $tz.Path ` -Subnets $subnet -ConnectivityPath $t1.Path $createdSegment = Invoke-PatchInfraSegment -Segment $segment -SegmentId $SegmentName |
In the above example, a flexible Segment will be created. However, In the case of NSX with VMConAWS, a fixed Segment needs to be created. For this, the Invoke-PatchSegment can be used.
Similarly to list the flexible segments, Invoke-ListInfraSegment and to list fixed Segments, Invoke-ListSegment can be used.
Dynamic Groups
Next is creation of Dynamic Groups in NSX. For this, Groups are created with specific membership criteria.
The following code snippet will create a dynamic group with a conditional membership criteria.
1 2 3 4 5 6 7 8 |
$cond = Initialize-Condition -ResourceType Condition -Id $GroupName ` -MemberType $MemberType -Value $Value -Key $Key ` -Operator $Operator $group = Initialize-Group -DisplayName $GroupName -Expression @($cond) $createdGroup = Invoke-PatchGroupForDomain -DomainId default ` -Group $group -GroupId $GroupName |
Note that a new Condition object is created but is passed in as the Expression. This is because, the NSX API defines Expression as the base data structure and Condition as the child data structure.
The following tree helps represent the parent-child relation between the Expression and Conditions:
With this, to create a Condition or a PathExpression or any of the other objects, you need to do the Initialize-<ChildObject> instead of doing an Initialize-Expression to use with Groups.
Distributed Firewall Policy
As with the rest of the objects, creation of distributed security policy is straight forward. Depending on the rule to be created, lookup of Groups and/or Services may be required. The below code snippet shows the lookup and creation of policy and rules. As per the API guide, Groups are under a domain object. For an on-prem NSX, there is only the default domain. Also, the Rule object expects the Service and Group as a list of object paths.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
$allServices = Invoke-ListServicesForTenant $ServicePathList = @() foreach ($serv in $ServiceList) { $s = $alls.Results | where {$_.DisplayName -eq $serv} $ServicePathList += $s.Path } $allGroups = Invoke-ListGroupForDomain -DomainId default $SourceGroupList = @() foreach ($gp in $SourceGroups) { if ($gp -eq "ANY") { $SourceGroupList += "ANY" } else { $g = $AllGroups.Results | where {$_.DisplayName -eq $gp} $SourceGroupList += $g.Path } } $DestinationGroupList = @() foreach ($gp in $DestinationGroups) { if ($gp -eq "ANY") { $DestinationGroupList += "ANY" } else { $g = $AllGroups.Results | where {$_.DisplayName -eq $gp} $DestinationGroupList += $g.Path } } $rule = Initialize-Rule -DisplayName $ruleName -Id $ruleName -SourceGroups $SourceGroupList ` -DestinationGroups $DestinationGroupList -Services $ServicePathList -Action $Action $securityPolicy = Initialize-SecurityPolicy -DisplayName $policyName -Rules @($rule) $createdSecurityPolicy = Invoke-PatchSecurityPolicyForDomain -DomainId default -SecurityPolicyId $policyName ` -SecurityPolicy $securityPolicy |
What about Gateway Security Policy? And what if its for VMConAWS? In that case, the structure is still going to be the same:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$mgwDomainGroups = Invoke-ListGroupForDomain -DomainId 'mgw' $mgwDomainGroup = $mgwDomainGroups.results | Where-Object -FilterScript { $_.DisplayName -eq $groupName } $services = Invoke-ListServicesForTenant $httpsService = $services.results | Where-Object -FilterScript { $_.DisplayName -eq $serviceName } $firewallRuleProperties = @{ 'SequenceNumber' = 0 'SourceGroups' = @('ANY') 'DestinationGroups' = @($mgwDomainGroup.path) 'DisplayName' = $ruleName 'Services' = @($httpsService.path) 'Action' = $allow } $firewallRule = Initialize-Rule @firewallRuleProperties $createdFirewallRule = Invoke-CreateOrReplaceGatewayRule -DomainId 'mgw' -GatewayPolicyId $gatewayPolicyId ` -RuleId $ruleId -Rule $firewallRule |
Conclusion
Putting everything together creates all the required routing objects and the required firewall rules quite easily. The more the cmdlets are used, the usage of Get-Help or Get-Command or Get-NsxOperation will reduce making writing quite fast and easy. Just like creating objects, all deletes can be done using the Invoke-Delete<Object> command. The full code can also be found on the NSX Samples GitHub page. I’ll leave writing a cleanup script to remove the objects created above as an exercise for the reader.
Comments
0 Comments have been added so far