NSX-V SpoofGuard via API
SpoofGuard is a feature of NSX that provides administrative control of IP and Mac address assignment for VM’s. The two benefits of Spoofguard are to (1) control virtual machine access to virtual network switches, and (2) protect against unauthorized IP address and MAC address changes by virtual machine OS administrators and users.
Like other capabilities of NSX, SpoofGuard administrative control can be accessed via the NSX API…
A quick summary of SpoofGuard capabilities before we dive into the API:
SpoofGuard Policies
A SpoofGuard Policy describes the type of administrative action that should be applied to vCenter virtual networks. The three modes of operation for SpoofGuard for any network is Disabled/Inactive (DISABLE), Trust On First Use (TOFU), and Manually Inspect and Approve IP Assignment (MANUAL).
The default policy in SpoofGuard is called “Default Policy” and its Operation Mode is Disabled.
Updating the Default Policy or adding a new SpoofGuard Policy allows you to apply a SpoofGuard Operation Mode to specific vSphere vCenter networks to allow for administrative control of network access.
All vSphere network types can be used in a SpoofGuard policy including vSphere Standard Switch (VSS) Port Groups, vSphere Distributed Switch (VDS) Port Groups, and NSX Logical Switches.
SpoofGuard enforcement is on the vNIC of each virtual machine at one of the first slots or tap points before the NSX Distributed Firewall.
The following screen capture shows the status of NSX SpoofGuard from the vSphere Web UI:
Query all SpoofGuard Policies via API
Via the NSX-V REST API and with appropriate REST headers (Auth and Content-Type), the following call to NSX Manager will return the defined SpoofGuard Policies:
GET https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/policies/
The response status code will be:
200 OK
The Response Body will be an XML listing of current SpoofGuard Policies:
<?xml version="1.0" encoding="UTF-8"?> <spoofguardPolicies> <spoofguardPolicy> <policyId>spoofguardpolicy-2</policyId> <name>WebAppDB Policy</name> <operationMode>MANUAL</operationMode> <enforcementPoint> <id>virtualwire-2</id> <name>Web-Tier-01-A</name> <type>VirtualWire</type> </enforcementPoint> <enforcementPoint> <id>virtualwire-3</id> <name>App-Tier-01-A</name> <type>VirtualWire</type> </enforcementPoint> <enforcementPoint> <id>virtualwire-4</id> <name>DB-Tier-01-A</name> <type>VirtualWire</type> </enforcementPoint> <publishedOn>2016-07-28 21:51:35.493</publishedOn> <publishedBy>root</publishedBy> <allowLocalIPs>true</allowLocalIPs> <publishPending>false</publishPending> <defaultPolicy>false</defaultPolicy> </spoofguardPolicy> <spoofguardPolicy> <policyId>spoofguardpolicy-1</policyId> <name>Default Policy</name> <operationMode>DISABLE</operationMode> <publishedOn>2016-07-29 03:40:42.428</publishedOn> <publishedBy>root</publishedBy> <allowLocalIPs>true</allowLocalIPs> <publishPending>false</publishPending> <defaultPolicy>true</defaultPolicy> </spoofguardPolicy> </spoofguardPolicies>
In the above example, two SpoofGuard Policies WebAppDB Policy and Default Policy are listed –
The WebAppDB Policy is applied to Logical Switches Web-Tier-01A, App-Tier-01A, and DB-Tier-01A with the Operation Mode of MANUAL. This ensures any virtual machines connected to these networks cannot obtain network connectivity until they are “approved” by SpoofGuard.
The Default Policy has an Operation Mode of DISABLE which ensures virtual machines connected to other networks in this environment do not have SpoofGuard policy applied.
Querying a Specific SpoofGuard Policy
Querying information about a specific SpoofGuard Policy requires knowledge of the policies Object ID. This would normally be derived programmatically at time of creation. Since we queried all SpoofGuard Policies in my lab, we know that object id spoofguardpolicy-1 and spoofguardpolicy-2 are defined.
The following NSX-v REST call will list the detail of spoofguardpolicy-2:
GET https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/policies/spoofguardpolicy-2
A successful response status code will be:
200 OK
The Response Body will be an XML listing of the selected SpoofGuard Policy. Note the additional statistics detail on policy usage included in the response detailing the status of VM IP address approvals for the policy:
<?xml version="1.0" encoding="UTF-8"?>
<spoofguardPolicy>
<policyId>spoofguardpolicy-2</policyId>
<name>WebAppDB Policy</name>
<operationMode>MANUAL</operationMode>
<enforcementPoint>
<id>virtualwire-2</id>
<name>Web-Tier-01-A</name>
<type>VirtualWire</type>
</enforcementPoint>
<enforcementPoint>
<id>virtualwire-3</id>
<name>App-Tier-01-A</name>
<type>VirtualWire</type>
</enforcementPoint>
<enforcementPoint>
<id>virtualwire-4</id>
<name>DB-Tier-01-A</name>
<type>VirtualWire</type>
</enforcementPoint>
<publishedOn>2016-07-29 04:13:05.324</publishedOn>
<publishedBy>root</publishedBy>
<allowLocalIPs>true</allowLocalIPs>
<publishPending>false</publishPending>
<statistics>
<inSync>true</inSync>
<activeCount>0</activeCount>
<inactiveCount>4</inactiveCount>
<activeSinceLastPublishedCount>0</activeSinceLastPublishedCount>
<requireReviewCount>4</requireReviewCount>
<duplicateCount>0</duplicateCount>
<unpublishedCount>0</unpublishedCount>
</statistics>
<defaultPolicy>false</defaultPolicy>
</spoofguardPolicy>
Creating a new SpoofGuard Policy
When creating a new SpoofGuard Policy, we require both the Switch Name and vCenter Managed Object Base (MOB) id for vSphere Standard Switch Port Group and vSphere Distributed Switch Port Groups. As an example:
VSS Port Group VM Network has a MOB id of network-32
VDS Port Group ComputeA_VDS – vMotion has a MOB id of dvportgroup-50
A little gotcha, for Logical Switches, we require the NSX Logical Switch name and NSX virtual wire id which is different than the vSphere MOB name for the the same switch.
NSX Logical Switch Web-Tier-01A has a virtual wire id of virtualwire-2 which is different than it’s MOB id.
vSphere SOAP API, XML scraping the vCenter MOB, or PowerCLI can be used to obtain MOB id for vCenter objects. NSX REST API can be used to find virtual wire id’s.
Using the previous REST Get verb to obtain SpoofGuard Policies, we will use one of these policies as a template to create a new SpoofGuard Policy, and we perform a REST Post request as follows:
POST https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/policies/
The XML input will be:
<spoofguardPolicy> <name>New SpoofGuard Policy</name> <description>A Test of the NSX API</description> <operationMode>TOFU</operationMode> <enforcementPoint> <id>network-32</id> <name>VM Network</name> <type>Network</type> </enforcementPoint> <allowLocalIPs>true</allowLocalIPs> </spoofguardPolicy>
A successful response status code will be:
201 Created
The Response Body will contain the id of the new SpoofGuard Policy:
spoofguardpolicy-4
Note, SpoofGuard Polcies cannot contain the same networks. An error will be returned if an attempt is made to create or update a policy with a network already defined in an existing policy.
Updating a SpoofGuard Policy
We specify the change by making a post request specifying the SpoofGuard Policy in the URI as follows:
PUT https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/policies/spoofguardpolicy-4
The XML input will include the changes to be made:
<spoofguardPolicy> <name>New SpoofGuard Policy</name> <description>A Test of the NSX API with New Description</description> <operationMode>TOFU</operationMode> <enforcementPoint> <id>network-32</id> <name>VM Network</name> <type>Network</type> </enforcementPoint> <allowLocalIPs>true</allowLocalIPs> </spoofguardPolicy>
A successful response status code will be:
204 No Content
Deleting a SpoofGuard Policy
Very easy – Just an REST request with the Delete verb specifying the SpoofGuard Policy ID on the URI as follows:
DELETE https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/policies/spoofguardpolicy-4
A successful response status code to the delete request will be:
204 No Content
SpoofGuard Policy Execution – Manual Mode
Now that we have SpoofGuard Policies in place, as virtual machines are connected to networks under SpoofGuard control, three things can happen based on the SpoofGuard Policy Operational Mode –
- Operational Mode of DISABLE, virtual machines have full access to the network switch and changes can be made to the virtual machines MAC and IP address.
- Operational Mode of TOFU, virtual machines have full access to the network, but any change to the virtual machines MAC or IP address will disable network switch access.
- Operational Mode of MANUAL, virtual machines have no access to the network switch until access is administratively approved via the SpoofGuard UI or API.
As soon as a virtual machine is created (powered off) within vCenter, SpoofGuard learns of its interfaces and MAC addresses via vCenter.
You cannot populate SpoofGuard with an IP and MAC address approval before the virtual machine has been created as SpoofGuard requires VM and vNIC MOB UUID information.
For demonstrated purposes, I cloned web-sv-02a to web-sv-03a while both virtual machines were powered off and SpoofGuard immediately identified the new web-sv-03a.
Query SpoofGuard for Virtual Machines
A slight variant of the above REST API request (policies verb removed from URI) is used to manage virtual machine MAC and IP address approvals within a SpoofGuard Policy:
GET https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/spoofguardpolicy-2?list=ACTIVE | INACTIVE | PUBLISHED | UNPUBLISHED | REVIEW_PENDING | DUPLICATE
The default is ACTIVE so any call without specifying the list= will result in a response based on list=ACTIVE
We now make a call to NSX SpoofGuard Spoofguardpolicy-2 to list inactive approvals:
GET https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/spoofguardpolicy-2?list=INACTIVE
A successful response status code to the get request will be:
200 OK
The Response Body will be an XML listing of all the inactive IP address approvals. Note the vCenter virtual machine MOB id information for VM’s listed… Note I have truncated the list to only include web-sv-02a and web-sv-03a.
As shown in the Response Body, since web-sv-03a has never been powered on, there is no IP address information for this virtual machine – Much less detail is known by SpoofGuard for web-sv-03a than for web-sv-02a.
<?xml version="1.0" encoding="UTF-8"?> <spoofguardList> <spoofguard> <id>503937d1-38ca-effa-eb26-add37826f0d7.000</id> <vnicUuid>503937d1-38ca-effa-eb26-add37826f0d7.000</vnicUuid> <nicName>web-sv-03a - Network adapter 1</nicName> <portGroupId>dvportgroup-115</portGroupId> <vmMoId>vm-135</vmMoId> <detectedMacAddress>00:50:56:b9:08:36</detectedMacAddress> </spoofguard> <spoofguard> <id>5039a79f-001e-1597-6a96-b793e4fd9b48.000</id> <vnicUuid>5039a79f-001e-1597-6a96-b793e4fd9b48.000</vnicUuid> <nicName>web-sv-02a - Network adapter 1</nicName> <portGroupId>dvportgroup-115</portGroupId> <vmMoId>vm-63</vmMoId> <approvedMacAddress>00:50:56:b9:12:ce</approvedMacAddress> <approvedBy>root</approvedBy> <approvedOn>2016-07-28 22:00:42.735</approvedOn> <publishedMacAddress>00:50:56:b9:12:ce</publishedMacAddress> <publishedBy>root</publishedBy> <publishedOn>2016-07-29 04:13:05.324</publishedOn> <detectedIpAddress> <ipAddress>172.16.10.12</ipAddress> </detectedIpAddress> <detectedMacAddress>00:50:56:b9:12:ce</detectedMacAddress> <ipDetectionTypeSet> <ipDetectionTypeSet> <string>VMTOOLS</string> </ipDetectionTypeSet> </ipDetectionTypeSet> </spoofguard> </spoofguardList>
Approving/Publishing Virtual Machine IP and MAC Address
Approving IP and MAC address assignment is a two step process. Here we perform this against web-sv-02a:
Step 1 – Assign an IP and MAC address to the VM as follows:
POST https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/spoofguardpolicy-2?action=approve
The XML input will include the virtual machine IP and MAC address approvals:
<spoofguardList> <spoofguard> <id>5039a79f-001e-1597-6a96-b793e4fd9b48.000</id> <vnicUuid>5039a79f-001e-1597-6a96-b793e4fd9b48.000</vnicUuid> <approvedIpAddress> <ipAddress>172.16.10.12</ipAddress> </approvedIpAddress> <approvedMacAddress>00:50:56:b9:12:ce</approvedMacAddress> </spoofguard> </spoofguardList>
A successful response status code will be:
200 OK
Step 2 – Publish changes to the SpoofGuard Policy as follows:
POST https://nsxmgr-l-01a.corp.local/api/4.0/services/spoofguard/spoofguardpolicy-2?action=publish
A successful response status code will be:
200 OK
Approving/Publishing a New Virtual Machine Never Previously Powered On
Using the above method, I approved and published the IP and MAC address of the new virtual machine vm-sv-03a. This was a clone of web-sv-02a and the MAC address was refreshed with a unique MAC address as part of the Cloning process, but the IP address needed to be updated via the VM console.
Once the virtual machine was powered on, updating the SUSE network configuration via yast network to match the new IP address 172.16.10.13 and I was immediately able to ping the external gateway as shown:
Via the SpoofGuard UI in vSphere vCenter, an active entry for 172.16.10.13 is shown:
This demonstrates using the NSX API, SpoofGuard approvals of new virtual machines can be performed programmatically.
Deleting Virtual Machine IP and MAC Address Approvals
Missing from the API Manual and I am working to get an update on this.
Unrelated… Connecting Virtual Machines to Logical Switches
SpoofGuard is tracking all virtual machine network interface UUID information irrespective of whether spoof guard policy is being applied or not. As such, SpoofGuard can be queried programmatically to obtain the virtual machine UUID which then can be used to connect a virtual machine to a logical switch.
Thanks for this complete tutorial!
I have found the way that NSX clears IP/MAC approvals.
The key point is that when you send the approve request, you should send all the valid IPs for a NIC in one request (In case of using more than one IP for a NIC), otherwise the latest request will override the previous IP.
So if you clear out inside of “approvedIpAddress” block, you will clear all approvals for than NIC.
Sample request:
500e653e-ec5f-3aab-16b5-fd27064c5570.000
500e653e-ec5f-3aab-16b5-fd27064c5570.000
06:d1:3e:00:06:8f