Introduction to the NSX-T Policy API

In NSX-T version 2.4 VMware introduced a new API to configure and manage our virtual network environment. VMware refers to the new API as the Policy API. The Policy API does not replace the more traditional API available in the previous versions of NSX-T. We refer to the old API as the management plane API. Any existing script or automation programmed against the management plane API will still work, but now a new and more modern approach to automate the NSX network is also available.

So why did VMware introduce this new API? The reason was to provide an easier and more efficient way to push configurations to NSX. To appreciate the benefits of the new Policy API we first need to introduce two concepts that describe different approaches to infrastructure programmability: imperative APIs, and declarative APIs.

When we use an imperative API, such as the NSX -T Management Plane API, we need to specify any required action and modification of the system needed to achieve the desired final state. In this scenario, the order of the modifications we perform on the system is also important.

When we use a declarative API instead, such as the new NSX-T Policy API, we only have to specify the desired final state. The system will reconcile the current state with the final state performing all the required modifications in the correct order without requiring the end-user to understand the minutia and the dependencies of the different objects.

In summary, the key characteristics of the NSX Policy API are the following.

  • It is Outcome-driven, meaning it reduces the number of configuration steps by allowing the user to describe the desired end-goal and letting the system figure out “how” to achieve it.
  • It is order independent, it means you can create/update/delete objects in any order and always arrive at the same outcome.
  • It is prescriptive, meaning it reduces the potential for user error with built-in dependency checks.

As an example, we can consider performing the required configuration to micro-segment a simple multi-tier application. Using the imperative API we would need to perform the following API calls in the right sequence:

  1. Create a security group for each application tier.
  2. Retrieve the IDs of any existing service we want o use in our firewall rule.
  3. Create any new custom service we need.
  4. Create a firewall policy.

You can see that even for such a simple use case we need to perform an extensive list of API calls, some of them dependent on the result of a previous one, while if we used the declarative API a single PATCH call would have been sufficient.
Below you can see an example of an actual Policy API call that performs micro-segmentation for a test multi-tier application.

microseg

PATCH: https://{{policy-ip}}/policy/api/v1/infra/

{
  "resource_type": "Infra",
  "children": [
    {
      "resource_type": "ChildService",
      "marked_for_delete": "false",
      "Service": {
        "service_entries": [
          {
            "l4_protocol": "TCP",
            "source_ports": [
              
            ],
            "destination_ports": [
              "8443"
            ],
            "resource_type": "L4PortSetServiceEntry",
            "id": "tcp_8443",
            "display_name": "TCP 8443"
          }
        ],
        "resource_type": "Service",
        "id": "tcp_8443",
        "display_name": "tcp_8443"
      }
    },
    {
      "resource_type": "ChildDomain",
      "marked_for_delete": false,
      "Domain": {
        "id": "default",
        "resource_type": "Domain",
        "marked_for_delete": false,
        "children": [
          {
            "resource_type": "ChildSecurityPolicy",
            "marked_for_delete": "false",
            "SecurityPolicy": {
              "id": "webapp",
              "resource_type": "SecurityPolicy",
              "display_name": "webapp",
              "description": "webapp Policy",
              "rules": [
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-01",
                  "description": "webapp-rule-01",
                  "display_name": "Management Outbound",
                  "sequence_number": 50,
                  "source_groups": [
                    "ANY"
                  ],
                  "destination_groups": [
                    "/infra/domains/default/groups/MGMT"
                  ],
                  "services": [
                    "ANY"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "ALLOW",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                },
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-02",
                  "description": "webapp-rule-02",
                  "display_name": "Management Inbound",
                  "sequence_number": 60,
                  "source_groups": [
                    "/infra/domains/default/groups/MGMT"
                  ],
                  "destination_groups": [
                    "ANY"
                  ],
                  "services": [
                    "ANY"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "ALLOW",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                },
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-03",
                  "description": "webapp-rule-03",
                  "display_name": "LB to WEB",
                  "sequence_number": 70,
                  "source_groups": [
                    "/infra/domains/default/groups/LB"
                  ],
                  "destination_groups": [
                    "/infra/domains/default/groups/WEB"
                  ],
                  "services": [
                    "/infra/services/HTTPS"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "ALLOW",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                },
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-04",
                  "description": "webapp-rule-04",
                  "display_name": "WEB to APP",
                  "sequence_number": 80,
                  "source_groups": [
                    "/infra/domains/default/groups/WEB"
                  ],
                  "destination_groups": [
                    "/infra/domains/default/groups/APP"
                  ],
                  "services": [
                    "/infra/services/tcp_8443"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "ALLOW",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                },
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-05",
                  "description": "webapp-rule-05",
                  "display_name": "APP to DB",
                  "sequence_number": 90,
                  "source_groups": [
                    "/infra/domains/default/groups/APP"
                  ],
                  "destination_groups": [
                    "/infra/domains/default/groups/DB"
                  ],
                  "services": [
                    "/infra/services/HTTP"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "ALLOW",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                },
                {
                  "resource_type": "Rule",
                  "id": "webapp-rule-06",
                  "description": "webapp-rule-06",
                  "display_name": "Block the rest",
                  "sequence_number": 100,
                  "destination_groups": [
                    "ANY"
                  ],
                  "source_groups": [
                    "ANY"
                  ],
                  "services": [
                    "ANY"
                  ],
                  "profiles": [
                    "ANY"
                  ],
                  "action": "DROP",
                  "logged": "true",
                  "scope": [
                    "/infra/domains/default/groups/WEBAPP"
                  ]
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": "false",
              "id": "MGMT",
              "display_name": "MGMT",
              "expression": [
                {
                  "ip_addresses": [
                    "192.168.100.1/32",
                    "192.168.110.10/32"
                  ],
                  "resource_type": "IPAddressExpression",
                  "marked_for_delete": "false"
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": "false",
              "id": "WEBAPP",
              "display_name": "WEBAPP",
              "expression": [
                {
                  "member_type": "VirtualMachine",
                  "key": "Tag",
                  "operator": "EQUALS",
                  "value": "webapp|",
                  "resource_type": "Condition",
                  "marked_for_delete": "false"
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": false,
              "id": "LB",
              "display_name": "LB",
              "expression": [
                {
                  "member_type": "VirtualMachine",
                  "key": "Tag",
                  "operator": "EQUALS",
                  "value": "webapp|lb",
                  "resource_type": "Condition",
                  "marked_for_delete": false
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": false,
              "id": "WEB",
              "display_name": "WEB",
              "expression": [
                {
                  "member_type": "VirtualMachine",
                  "key": "Tag",
                  "operator": "EQUALS",
                  "value": "webapp|web",
                  "resource_type": "Condition",
                  "marked_for_delete": false
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": false,
              "id": "APP",
              "display_name": "APP",
              "expression": [
                {
                  "member_type": "VirtualMachine",
                  "key": "Tag",
                  "operator": "EQUALS",
                  "value": "webapp|app",
                  "resource_type": "Condition",
                  "marked_for_delete": false
                }
              ]
            }
          },
          {
            "resource_type": "ChildGroup",
            "Group": {
              "resource_type": "Group",
              "marked_for_delete": false,
              "id": "DB",
              "display_name": "DB",
              "expression": [
                {
                  "member_type": "VirtualMachine",
                  "key": "Tag",
                  "operator": "EQUALS",
                  "value": "webapp|db",
                  "resource_type": "Condition",
                  "marked_for_delete": false
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

3 thoughts on “Introduction to the NSX-T Policy API

  1. Great goods from you, man. I have take note your stuff
    previous to and you’re simply too excellent. I really like what you’ve obtained
    here, certainly like what you are stating and the best way in which
    you are saying it. You are making it entertaining and you continue to take care of to keep it sensible.
    I cant wait to read far more from you. This is really a great website.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s