Tag Archives: vsphere

What you can learn from Networking for VMware Admins

Introduction

It was not so long ago when I was searching for good resource that would uncover what is happening at the hypervisor level from network point of view and how it all clicks together to provider connectivity to ever increasing number of virtual machines. I am happy to say that I have found that resource. It is called Networking for VMware Administrators by Chris Wahl and Steve Pantol.

Networking-for-VMware-Administrators 1

The book starts by discussing the very foundation of networking, what networks is and what benefits it provides. Continuing with with common models and protocol stacks like ISO OSI and TCP/IP and the concepts of layering.

Comparing ISO OSI to TCP/IP

Comparing ISO OSI to TCP/IP

Diving more deeply into the individual layers authors start with physical layer. Ethernet technology is explained in great detail as well as common physical connectivity options like copper or fiber. You will also gain some knowledge about most used network connectors such as RJ-45 and modules like older GBIC or SFP.

10Gbps Twinax Cable used for short interconnections

10Gbps Twinax Cable used for short connections

The chapters build on top of each other and after the foundation and physical network properties next chapter covers data-link operations in great detail. You learn about switching and common network challenges like preventing network loops with spanning tree or increasing network through put by utilizing link aggregation technologies.

Another layer that could not be forgotten is Layer 3 or Network layer. In this chapter IP addressing and routing is explained in detail. Other common services such as automatic address configuration thought DHCP or name resolution with DNS are well touched giving you as a reader better overall perspective.

With the foundation lied down in first 5 chapters the book continues to touch popular converged network infrastructures. Concept of stateless computing from Cisco is explained – the Unified Computing System as well as the HP’s Blade Chassis C7000. Both are compared to give you better insight on one over the other.

Cisco Unified Computing System

Cisco Unified Computing System

The true discussion on virtual networking begins with Chapter 7: How Virtual Switching Differs from Physical Switching. This is an excellent entry point chapter, which describes similarities and differences between both. It touches on common virtual vSwitch terms such as virtual machines’s NIC cards (vNIC), Port-Group, physical uplinks (pNIC), VM kernel ports (vmk) and generally how does the virtual architecture fits with physical.

vSwitch Architecture

vSwitch Architecture

vswitch-logic

vSwitch Forwarding Logic

Better yet, this chapter outlines various configuration options on vSwitch like number of uplinks, MTU and Security Settings. Last but not least trunking and VLAN tagging options are explained.

Chapter 9 focus on vSphere Distributed Switch which is commonly found in enterprise environments. It explains how it differs from Standard vSwitch in control and data plane operations. And elaborates on many extra features it provides. You can expect to gain knowledge on link discovery protocols CDP and LLDP, exporting traffic flows with NetFlow, monitoring traffic in virtual environment using Port Mirroring, segmenting traffic using VLANs and Private VLANs and finally Load Based teaming and Network IO Control for intelligent traffic management.

After you gain this strong foundation, you are free to enter to realm of third party virtual switch. Cisco Nexus 1000V is the topic of next chapter. Authors explain the reasons why you might consider using this third party switch from Cisco in your environment. It touches on core architecture concepts like Virtual Supervisor Module (VSM) and Virtual Ethernet Module (VEM) and various modes of deployment options.

Nexus 1000V deployment options

Nexus 1000V deployment options

If you are more practical type of person, you will definitely like the lab scenarios that authors put together. A step by stem approach is outlined how to build a basic vSphere environment using Cisco UCS as main computing platform. In later chapters you will also discover how to migrate workloads from standard virtual switch to distributed virtual switch without causing downtime.

After discussing general networking technologies with relevant examples, Chapter 14 moves our direction toward IP based storage, starting with iSCSI. General uses cases are explained as well the idea of initiators and targets. Best practices for setting up iSCSI storage adapters are also well explained giving you good confidence when planning in production environment.

The storage topics are then closed by discussing NFS based storage and its uses cases. I especially like the right depth of topics around storage. Practical demonstration at the end of the chapter is also a huge benefit to better put things together.

The next to last chapter deals with additional vSwitch design options, showing many different scenarios with or without IP based storage in place and using 1 Gbps or 10 Gbps network adapters.

One of many vSwitch design options

One of many vSwitch design options

Finally, the last chapter discusses additional design options when dealing with heavy load vMotion migrations. You will learn how to design multiple VM kernel adapters for moving workloads around in case you need to. Network IO Control is also revisited in relation of egress traffic shaping and protecting v host from traffic overload, in case of multiple hosts decide to migrate loads onto same destination hypervisor.

Although I am primarily a network guy I must admin I enjoyed this well written book from the first page to last. It gave exactly what I was looking for, a good foundation of vSphere networking which is the base for advanced technologies like virtual overlays with VXLAN.

Advertisements

Cisco ASAv firewall HA Pair

Introduction

In previous post I have introduced and demonstrated the ASA in virtual form factor. This post will built on top of previous that one and will show you how to setup redundant high available pair of these firewalls.

The HA setup is ideal in situations where you are building virtual infrastructure hosted on private or public cloud that needs to be available all the time, surviving failure of one of the firewalls that run as virtual machines. Standard vSphere VM placement best practices should be also considered, such as anti-affinity rules and resource allocation. Consult these with you VMware administrators.

The following diagram outlines the final setup. My home lab only has one ESXi hosts, so everything is running over there.

ASAv HA Setup

Active Firewall rollout

Start with the deployment of first firewall which will be the active one. After downloading the OVA package from Cisco go to vSphere\Virtual Machines\Right Click on Cluster\Deploy OVF Template.

asav-ha-step1

After browsing and selecting the OVA package, I am using asav931.ova, you will be ask to accept the extra configuration options and estimated disk size requirements.

asav-ha-step2

Next, accept the license agreement and and click next. You will have an option to select the name of the new primary ASA which will be ASAv03-Active and the location of the VM.

asav-ha-step3

You will now have a choice to select deployment size, from 1vCPU Standalone all the way up to 4vCPU. If you are deploying in production, you should consult the deployment guide for the right flavor. I am deploying in lab, therefore I have selected 1vCPU HA Primary.

asav-ha-step4

After selecting the deployment size, we need to specify the resource that ASAv will consume. If you select a cluster DRS can automatically place the VM to least utilized hypervisor. You can also specify certain ESXi hosts. I have just one ESXi host, so the choice will be obvious.

asav-ha-step5

To same some storage space, change the default virtual disk format from Thick Provisioned to Thin Provision.

On the next page, we need to configure network mapping. ASAv has by default 10 vNIC adapters which first of them is the Management and the last Gig0/8 is used by HA Heartbeat. Remaining interfaces can be used for production traffic. We leave unused interface in DMZ for now.

asav-ha-step6

Now you have an option to Customize the template by typing configuration parameters such as Management Interface Settings, Device Manager IP Settings and HA Connection Settings.

The Management address of Primary Unit will be 172.16.2.1/24 and Secondary will be 172.16.2.2/24. The default gateway will not be required at this moment, our management station sits on the same virtual switch. To allow remote access from day 1, specify that the allowed management subnet is 172.16.2.0/24

The Primary Unit HA address will be 172.16.3.1/24 and the Secondary will be 172.16.3.2/24.

asav-ha-step7

In Ready to Complete page, you get the summary of all configuration options, and you will have a choice to Power VM after deployment. Congratulations you just deployed your first HA Pair Firewall. After first power on, ASAv will perform initial configuration and reboot.

If everything worked as expected, you should be able to log in from management station via SSH.

asav-ha-step8

By default, however, not username was configured in template therefore it is still needed to jump to virtual console and create one and point the AAA authentication for SSH to local user database.

It is also worth to mention that although ASDM https access was enable, it would still need to have an account and aaa authentication configured properly to work.

ciscoasa(config)# username admin password cisco privilege 15
ciscoasa(config)# enable password cisco
ciscoasa(config)# aaa authentication ssh console LOCAL

Now you can actually connect to the ASA remotely. If you examine the configuration a little bit you find that it has setup the failover interface and peer and currently shows that its mate is down/unknown.

ciscoasa# sh failover
Failover On
Failover unit Primary
Failover LAN Interface: fover GigabitEthernet0/8 (up)
Unit Poll frequency 1 seconds, holdtime 15 seconds
Interface Poll frequency 5 seconds, holdtime 25 seconds
Interface Policy 1
Monitored Interfaces 1 of 61 maximum
MAC Address Move Notification Interval not set
Version: Ours 9.3(1), Mate Unknown
Last Failover at: 10:16:56 UTC Feb 20 2015
        This host: Primary – Active
                Active time: 873 (sec)
                slot 0: empty
                  Interface management (172.16.2.1): Unknown (Waiting)
        Other host: Secondary – Failed
                Active time: 0 (sec)
                  Interface management (172.16.2.2): Unknown (Waiting)
 

ciscoasa# show failover state

State          Last Failure Reason      Date/Time
This host  –   Primary
Active         None
Other host –   Secondary
Failed         Comm Failure             10:17:13 UTC Feb 20 2015

====Configuration State===
====Communication State===

Standby Firewall rollout

Before we are going to configure the other interfaces, lets set up the secondary unit. Again we are going to start by deploying a template from .OVA. To save some space, I will only show difference from deploying the primary unit.

The VM name will be set to ASAv03-Standby, and the deployment configuration will be set to 1vCPU HA Secondary. Selecting the right resource in production should be also considered to minimize that a single hypervisor failure will cause both firewalls go down. Therefore I recommended anti-affinity rules so those two VMs will never run on same machine.

The interface mapping will be exactly same as with primary unit. See the reference above. In the customization template page, enter the Management IP address and HA IP address settings for this unit.

asav-ha-step9

Deployment of this small flavor took no longer than 30 seconds, and after the initial reboot the Standby firewall is up an running.

While still setting remotely on primary unit we are going to check the failover pair state again.

Beginning configuration replication: Sending to mate.
ciscoasa# show failover
Failover On
Failover unit Primary
Failover LAN Interface: fover GigabitEthernet0/8 (up)
Unit Poll frequency 1 seconds, holdtime 15 seconds
Interface Poll frequency 5 seconds, holdtime 25 seconds
Interface Policy 1
Monitored Interfaces 1 of 61 maximum
MAC Address Move Notification Interval not set
Version: Ours 9.3(1), Mate 9.3(1)
Last Failover at: 10:16:56 UTC Feb 20 2015
        This host: Primary – Active
                Active time: 2111 (sec)
                slot 0: empty
                  Interface management (172.16.2.1): Normal (Monitored)
        Other host: Secondary – Standby Ready
                Active time: 0 (sec)
                  Interface management (172.16.2.2): Normal (Waiting)

ciscoasa# sh failover state

               State          Last Failure Reason      Date/Time
This host  –   Primary
               Active         None
Other host –   Secondary
               Standby Ready  Comm Failure             10:17:13 UTC Feb 20 2015

====Configuration State===
        Sync Done
====Communication State===
        Mac set

====VM Properties Compatibility===
vCPUs – This host:  1
        Other host: 1
Memory – This host:  2048 Mhz
         Other host: 2048 Mhz
Interfaces – This host:  9
             Other host: 9

Looking much better now. To see failover in action, lets first complete the configuration of other interfaces to get some traffic flowing through the firewall

prompt hostname priority state
!
interface GigabitEthernet0/0
 description OUTSIDE
 nameif outside
 security-level 0
 ip address 10.0.2.91 255.255.255.0 standby 10.0.2.92
!
interface GigabitEthernet0/1
 description INSIDE
 nameif inside
 security-level 100
 ip address 172.16.0.1 255.255.255.0 standby 172.16.0.2
!
interface GigabitEthernet0/2
 description DMZ
 nameif dmz
 security-level 50
 ip address 172.16.1.1 255.255.255.0 standby 172.16.1.2
!
monitor-interface outside
monitor-interface inside
monitor-interface dmz
!
route outside 0 0 10.0.2.1
!
policy-map global_policy
 class inspection_default
  inspect icmp

My outside router does not have static routes to these private network behind ASA so a object NAT will help to mitigate that.

object network inside_net
 subnet 172.16.0.0 255.255.255.0
nat (inside,outside) source dynamic inside_net interface

Now we should have connectivity from inside host to Internet. We get verify that by pulling google web page from client and also checking the NAT or connection table.

ciscoasa# sh nat detail
Manual NAT Policies (Section 1)
1 (inside) to (outside) source dynamic inside_net interface
    translate_hits = 12, untranslate_hits = 0
    Source – Origin: 172.16.0.0/24, Translated: 10.0.2.91/24

Now start continuous ping from inside machine and power off the primary firewall.

root@deb01:~# ping -c 100 8.8.8.8
100 packets transmitted, 85 received, 15% packet loss, time 99250ms
rtt min/avg/max/mdev = 10.771/11.988/21.956/2.426

From the output, I examined that from 100 packets, 15 was lost during switchover. With default pool and hold times it was not amazingly fast. We can do better.

failover polltime unit 1 holdtime 3
failover polltime interface 1 holdtime 5

Repeat the 100 ping test again and examine the results.

Now with adjusted timers, from 100 packets we lost 4 during switchover. Getting better :-). Lets see how this HA pair will cope with TCP sessions.

We are going to initiate a large file download from inside host and then shutdown the secondary (now active) ASA and examine the result on traffic flow.

The primary ASA took back the role of Active Firewall, but the TCP session has died. There is one another parameter that we need to tweak for HTTP sessions and to explicitly enable them.

ciscoasa/pri/act(config)# failover replication http
Now initiate the download again, and check that it will be re-established after failover.

Conclusion

After tweaking some default settings you have a highly available firewall cluster running in fully visualized environment.

s

Cisco ASAv firewall REST API

Introduction to API

The evolution of application programming interface is gaining significant importance in the adoption of software defined networking. Many vendors realized that the next step after releasing their hardware products as virtual machines is to provide a new programmatic way of configuring for their devices.

The traditional way to configure switches, routers, firewalls and many other network gear is to use Command Line Interface either directly on console or remotely via SSH. As network devices became more complex and capable new ways of emerged like Graphical User Interface running on device itself or centrally allowing to manage multiple boxes from one place.

Applications and services have radically changed in last few years and they become more complex and are composed of many different components that are often interconnected by underlying network infrastructure. This means that the network configuration is often complex, time consuming and often prone to human error.

There is a better way to program the network infrastructure. One of the popular methods is through an API interface. The idea is that during an application deployment, when virtual machines are build and configured according the blueprint, the same configuration templates would be used to deploy objects and rules within the firewall according the application security requirements. This would allow quick application deployment and un-deployment without any human intervention.

What you gain by utilizing this deployment approach is that you have a model where you once define and build the base application rules – objects, services, acls and you can reuse it many times by changing variables such as number of virtual machines or stacks. This level of automation is needed for the next-generation data centers to services its clients.

ASA REST API

To support the idea outlined here, Cisco has recently released a REST API client that can be used as another method of configuration of their popular firewall product line. The ASA uses small plugin that is uploaded into device flash memory, much like ASDM and then activated from CLI. This allows a client to perform certain elementary operations such as Create, Read, Update, Delete on ASA resources such as network objects or ACL. After the right API call has been executed ASA will respond with a status code such as 201 Object Created.

The high level architecture of this model looks like this:

rest-api-arch

If you compare this style of configuration to traditional way through CLI you see that we can achieve the same things but in programmatic matter.

Note: REST stands for Representational State Transfer and it is a software architecture style. You refer the full article at http://en.wikipedia.org/wiki/Representational_state_transfer

 

API Requests

To support the basic object operations such as create or delete, ASA support the following requests that can be fired toward the firewall from REST API client.

  • GET – used when retrieving data from an object, for example list of all existing service objects
  • PUT – used when adding information to a specific object if it exists, if not it will create the object, for example a network object group
  • POST – similar to previous, used when adding information to an existing object
  • DELETE – used when deleting an object
  • PATCH – used when partially modifying an object for example updating destination TCP port in service object

API Response

Usually when you fire a request you will get a response back if the operation was successful. If you think about it is similar with HTTP protocol. You request a web resources by GET operation and get a response code 200 OK or 500 Internal Server Error. ASA supports these responses:

  • LOCATION – when POST method is used and a new resource is created, the location will hold its unique URI which represents the resource. This object can be used later when removing the object with DELETE request.

  • CONTENT-TYPE – similar to HTTP describes what content is being encoded, whether it is a JSON, XML or text representation. This helps to format the response.

Each response also contain HTTP status coded that outlines if the operation was successful or an error happened. We can categories these codes into the following groups:

  • 20x – indicates successful operations, such as:

    • 200 OK – Standard response when request was successfully completed – e.g. list all objects within an object group or saving a configuration
    • 201 Created – Standard response when request was successfully completed – e.g. object created, static route added
    • 202 Accepted – Request has been accepted, but it is still being processed
    • 204 No Content – Request has been accepted, but no content is being returned, e.g. when you query and empty object.
  • 4xx – indicates a client side error, for example
    • 400 Bad Request – Indicated that there were missing or invalid parameters in request, e.g. you tried to create a network object with an invalid range.
    • 404 Not Found – The object that you trying to list is does not exist or its unavailable. e.g. querying a previously deleted object
    • 405 Method not Allowed – happens when you try to delete and object which is in use or when modifying a read only only object.
  • 5xx – Indicates a server-side error

When an error is returned it would be handy to know what went wrong and learn from it. Lucky for us ASA will just do that in an intuitive manner and easy to read format. For example I have tried to delete object named UDP-123 that was used within a service object group ntp and I have received a status code of 500 and the response body would contain the following message. Status codes are great way how to quickly determine the response and can be used by a deployment applications to track any errors in the script.

{
  “messages”: [
    {
      “level”: “Error“,
      “code”: “OBJECT-USED“,
      “details”: “Usages:[Service Groups: ntp,]
    }
  ]
}

We can break down the error message into these generic sections

  • message – lists of the the warnings
  • level – lists the info code such as Error, Warning, Info
  • code – lists the type of an error
  • details – lists additional details if available, gives use more clues

Practical Example

You should now have some basic level of understanding why REST API is important in the world of SDN and also gained some familiarity with requests and responses that ASA REST implementation is using. To put some meat into discussion we are going to remonstrate a real world usage of this new interface.

We will have a server farm with multiple web VM accepting connections from outside network and retrieving resources from back end database server. The management VM will reside on a different network.

The policy will be simple, where we allow any source going to web servers on port TCP 80 and from web servers to database servers on port TCP 3306. We will also enable TCP 80 and 443 from web servers to Internet.

 asav-rest
 

Getting the code

REST API client is available both for a physical ASA as well as ASAv. I using the later one which can be downloaded from Cisco. Refer to this post on how to setup ASAv from scratch in vSphere.

You will need the following REST API Agent from Cisco download page: asa-restapi-101.lfbff-k8.SPA.

I have also update the my virtual ASAv from version asa931-smp-k8.bin to latest available version asa932-200-smp-k8.bin

 rest-client-asa

After uploading the client to flash memory, there are several steps that needs to be completed before we can fire our first request. To avoid frustration with corrupted files I suggest to run md5 sum after the files landed on flash.

verify /md5 boot:asa932-200-smp-k8.bin
verify /MD5 (boot:/asa932-200-smp-k8.bin) = 2679aefdf9017a5845f3fcc9321d4a1d
verify /md5 boot:asa-restapi-101-lfbff-k8.SPA
verify /MD5 (boot:/asa-restapi-101-lfbff-k8.SPA) = 76b3496b930018b1cda30fdd407cd041

Initial Configuration

If you are happy with the sums, continue with configuring the management interface, HTTPS server and REST Server plugin.

#Configure and enable management interface
interface Management0/0
 management-only
 ip address 10.201.230.1 255.255.255.0
 no shut
#Create a local user, privilege 15 is needed to invoke PUT/POST and DELETE #operations. Lower level privilege accounts can be used for monitoring-only #purpose. For example level 3 can request monitoring requests while level5 or #greater can invoke GET request.
 
username restclient password restpassword privilege 15
enable secret area51devs
 
#Configure and enable HTTPS server
 
http server enable

http 0.0.0.0 0.0.0.0 management

 
#Configure HTTP authentication to query local database
 
aaa authentication http console LOCAL
#Enable and configure REST API Agent
 
rest-api image boot:/as-restapi-101-lfbff-k8.SPA

rest-api agent

And that is all that is needed to have basic REST API agent up and running, really easy to deploy, thanks to Cisco developers.

Installing REST Client

Now the 2nd part of the equation is to get a REST API client. I am using Firefox therefore I have downloaded the browser plugin from here. After installation the browser will restart and a new icon will appear in the upper left corner. Simple click on it and you will be presented by the following clean interface.

rest-client

Now to test that everything works as expected, initiate your first GET operation against the following URL: https://<management-ip>/api/monitoring/device/components/version

The first time request will require authentication so enter credentials you created in local database. If you are successful, you should receive a response similar to this:

rest-server-headers

The Response Headers tab will shows you the status code that has been returned while the Response Body (Highlights) will show you the actual contents which displays the software version, mode and other system related information.

rest-server-json

You might wonder, how did I know what object to call to get the version of the virtual ASA. And the answers is that ASA contains a awesome documentation that is located on device itself. Simple point your browser to the following URL https://<management-ip>/doc/ . You will be presented by the API main documentation page.

rest-server-doc

The online documentation is an excellent resource for learning about API calls and ASA resources. As you can see it is divided in to several sections and it even contains an integrated API console where you can execute the calls. Huge number of examples will give you head start while developing your scripts.

The operations can be even exported into common scripting language such as JavaScript, Python or Perl and part of a large deployment script. For example the previous call in Javacript would look like this:

/*
 * Generated ASA REST API sample script - Javascript
 * Uses node.js
 */

var https = require('https');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

var data = {};

var server = "10.201.230.5";

// Default credentials
var username = "restclient";
var password = "restpassword";

// process arguments
// process.argv[0] == node
// process.argv[1] == filename
process.argv.forEach(function(val, index) {
    if (index == 2) {
        username = val;
    }
    else if (index == 3) {
        password = val;
    }
});

var api_path = "/api/monitoring/device/components/version";    // param


var options = {
    host: server,
    path: api_path,
    method:"GET",
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + new Buffer(username + ':' + password).toString('base64')
    }
};

var req = https.request(options, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);

    res.on('data', function(d) {
        process.stdout.write(d);
    });
});
req.end();

req.on('error', function(e) {
    console.error(e);
});
This file can be than saved as .js file and run using program called nodejs available here.

If you use a developer tool such as Inspector to see the actual GET request, you can see that part of header is an Authorization field with value of “Basic cmVzdGNsaWVudDpyZXN0cGFzc3dvcmQ=”. Which is nothing else than username:password encoded in Base64. You can verify it here. Every request contains this field for proper authorization.

Configuring Network Interfaces

Now that we have the basic REST API client up and running lets configure the remaining three network interfaces. Back in client change the method from GET to PUT and point it to the first physical interface located at the following URL http://<management-ip/api/interfaces/physical/GigabitEthernet0_API_SLASH_0

 

Since this is the first time that we are putting something in the request body, we need to change the default content type in REST Client from text/plain to application/json. Otherwise the ASA will not understand what we are asking from it to do.

rest-client-content-type

Back to the client the body need to contain the following code:

{
  “securityLevel”: 100,
  “kind”: “object#GigabitInterface“,
  “channelGroupMode”: “active“,
  “flowcontrolLow”: -1,
  “name”: “outside“,
  “duplex”: “auto“,
  “forwardTrafficSFR”: false,
  “hardwareID”: “GigabitEthernet0/0“,
  “mtu”: 1500,
  “lacpPriority”: -1,
  “flowcontrolHigh”: -1,
  “ipAddress”: {
    “ip”: {
      “kind”: “IPv4Address“,
      “value”: “10.0.2.90
    },
    “kind”: “StaticIP“,
    “netMask”: {
      “kind”: “IPv4NetMask“,
      “value”: “255.255.255.0
    }
  },
  “flowcontrolOn”: false,
  “shutdown”: false,
  “interfaceDesc”: “Outside Network“,
  “managementOnly”: false,
  “channelGroupID”: “”,
  “speed”: “auto“,
  “forwardTrafficCX”: false,
  “flowcontrolPeriod”: -1
}

After successfully firing the request you should receive the return code 204 which means request has been accepted but no content is being returned.

rest-server-interface

You can log into CLI and make sure that the interface has been indeed configured according our parameters. Or you can perform a GET operation against the location of a newly configured resource. Follow the same approach for the inside and dmz interface.

rest-api-cli

Note: All our interfaces will have the same security level of 100. We will later use global ACL to control what is allowed to pass through the firewall. For this to work we also need to enable same-security-traffic permit inter-interface in global configuration mode.

Configuring static routes

To get to the Internet we also need a default gateway. This time the method is POST and it is simple as firing the following API call against this URL:  https://<management-ip>/api/routing/static

{
  “tunneled”: false,
  “kind”: “object#IPv4Route“,
  “distanceMetric”: 1,
  “tracked”: false,
  “interface”: {
    “kind”: “objectRef#Interface“,
    “name”: “outside
  },
  “gateway”: {
    “kind”: “IPv4Address“,
    “value”: “10.0.2.1
  },
  “network”: {
    “kind”: “AnyIPAddress“,
    “value”: “any4
  }
}

Again, you will receive a unique response that contains the resource URL this time has the following format: https://10.201.230.5/api/routing/static/cec906bc. If I use this URL and change the method to GET. I receive the information about this default route.

Creating Objects

So far we have configured the basics and now are are going to play a little with various objects and object groups. Lets start by creating couple of service objects. We are going to create a couple of TCP objects which will be later included in object groups.

First, we need to point the REST client to URL: https://<management-ip>/api/objects/networkservices. We will use POST method and the body will contain the following:

{
  “kind”: “object#TcpUdpServiceObj”,
  “name”: “TCP-80“,
  “value”: “tcp/80
}

The response status code should be 201 Created. The response will also include the resource URI. In this case it will be http://<mngement-ip>/api/objects/networkservices/TCP-80

Follow the same approach and create network objects TCP-443, TCP-3306. When you finish your output of GET http://<management-ip>/api/objects/networkservices should reassemble the following:

{
   “kind”: “collection#NetworkServiceObjects“,
   “rangeInfo”:
   {
       “offset”: 0,
       “limit”: 3,
       “total”: 3
   },
   “items”:
   [
       {
           “kind”: “object#TcpUdpServiceObj“,
           “selfLink”: “https://10.201.230.5/api/objects/networkservices/TCP-3306“,
           “name”: “TCP-3306“,
           “value”: “tcp/3306“,
           “objectId”: “TCP-3306
       },
       {
           “kind”: “object#TcpUdpServiceObj“,
           “selfLink”: “https://10.201.230.5/api/objects/networkservices/TCP-443“,
           “name”: “TCP-443“,
           “value”: “tcp/https“,
           “objectId”: “TCP-443
       },
       {
           “kind”: “object#TcpUdpServiceObj“,
           “selfLink”: “https://10.201.230.5/api/objects/networkservices/TCP-80“,
           “name”: “TCP-80“,
           “value”: “tcp/http“,
           “objectId”: “TCP-80
       }
   ]
}

We are also going to create a couple of hosts that will be used in network objects groups. Network objects are located at https://<management-ip>/api/networkobjects/ . Again POST method will be used.

{
  "host": {
    "kind": "IPv4Address",
    "value": "172.16.1.11"
  },
  "kind": "object#NetworkObj",
  "name": "web01",
  "objectId": "web01"
}

You can create multiple objects with same API call, for this you need to create a bulk API request again the main URL https://<mnagement-ip>/api and include the sub-paths and methods into the request body field.

[  
{
    “resourceUri”: “/api/objects/networkobjects“,
    “data”: {
      “host”: {
        “kind”: “IPv4Address“,
        “value”: “172.16.1.12
      },
      “name”: “web02
    },
    “method”: “Post
  },
  {
    “resourceUri”: “/api/objects/networkobjects“,
    “data”: {
      “host”: {
        “kind”: “IPv4Address“,
        “value”: “172.16.1.13
      },
      “name”: “web03
    },
    “method”: “Post
  }
]

The response for this request will be similar to create just one object. The status code will be 200 OK, however I have found that the Response Body (Highlight) did not contain any detail about the newly created resources URLs. This information was indeed contained in Response Body (Raw) tab. Perhaps it is just the way the Firefox REST Client works at the moment.

{
"entryMessages":
[
      {
           "resourceUri":"/api/objects/networkobjects",
           "method":"POST",
           "selfLink":"http://10.201.230.5/api/objects/networkobjects/web02",
           "messages":
           [
              {
              "level":"Info",
              "code":"201",
              "details":"Created (201) - The request has been fulfilled and resulted in a new resource being created"
              }
           ]
     },
     {
           "resourceUri":"api/objects/networkobjects",
           "method":"POST",
           "selfLink":"http://10.201.230.5/api/objects/networkobjects/web03",
           "messages":
           [
               {
               "level":"Info",
               "code":"201",
               "details":"Created (201) - The request has been fulfilled and resulted in a new resource being created"
               }
           ]
      }
],
"commonMessages":[]
}

I have created two additional network objects db01 with value 172.16.1.11 and db02 with value 172.16.1.12. After all objects are create the GET method against https://<management-ip>/api/networkobjects will return something like this:

{
   “kind”: “collection#NetworkObj”,
   “rangeInfo”:
   {
       “offset”: 0,
       “limit”: 5,
       “total”: 5
   },
   “items”:
   [
       {
           “kind”: “object#NetworkObj“,
           “selfLink”: “https://10.201.230.5/api/objects/networkobjects/db01“,
           “name”: “db01“,
           “host”:
           {
               “kind”: “IPv4Address“,
               “value”: “172.16.0.11
           },
           “objectId”: “db01
       },
       {
           “kind”: “object#NetworkObj“,
           “selfLink”: “https://10.201.230.5/api/objects/networkobjects/db02“,
           “name”: “db02“,
           “host”:
           {
               “kind”: “IPv4Address“,
               “value”: “172.16.0.12
           },
           “objectId”: “db02
       },
       {
           “kind”: “object#NetworkObj“,
           “selfLink”: “https://10.230.201.5/api/objects/networkobjects/web01“,
           “name”: “web01“,
           “host”:
           {
               “kind”: “IPv4Address”,
               “value”: “172.16.1.11
           },
           “objectId”: “web01
       },
       {
           “kind”: “object#NetworkObj“,
           “selfLink”: “https://10.230.201.5/api/objects/networkobjects/web02“,
           “name”: “web02“,
           “host”:
           {
               “kind”: “IPv4Address“,
               “value”: “172.16.1.12
           },
           “objectId”: “web02
       },
       {
           “kind”: “object#NetworkObj“,
           “selfLink”: “https://10.230.201.5/api/objects/networkobjects/web03“,
           “name”: “web03“,
           “host”:
           {
               “kind”: “IPv4Address“,
               “value”: “172.16.1.13
           },
           “objectId”: “web03
       }
   ]
}

Note: When you try to create an object that is already existing you will receive an 400 Bad Request error and the response body will contain the following error description

{
   “messages”:
   [
       {
           “level”: “Error“,
           “code”: “DUPLICATE“,
           “context”: “objectId“,
           “details”: “db01
       }
   ]
}

Creating Object Groups

Now that we have created couple of service and network objects, lets put them in their respective groups according their usage. We start with services and then with hosts. The URL for service object groups is https://<management-ip/api/objects/networkservicegroups

{
     "kind": "object#NetworkServiceGroup",
     "name": "http",
     "members":
     [
         {
             "kind": "objectRef#TcpUdpServiceObj",
             "objectId": "TCP-80"
         }
      ],
      "description": ""
}

The response will be 201 Created and Response header will also contain the object-group unique URL such as https://<management-ip>/api/objects/networkservicegroups/http

Follow the same approach for other service object groups https and mysql.

Next, we are going to great two network object groups one will be web-servers and other will be named database-servers. The targeted API resource is https://<management-ip>/api/objects/networkobjectgroups

{
  "kind": "object#NetworkObjGroup",
  "name": "web-servers",
  "members": [
    {
      "kind": "objectRef#NetworkObj",
      "objectId": "web01"
    },
    {
      "kind": "objectRef#NetworkObj",
      "objectId": "web02"
    },
    {
      "kind": "objectRef#NetworkObj",
      "objectId": "webb03:
    }
], 
"description": "Corporate web servers" 
}

We response is again a 201 Created status code with the resource URL. The object group web-servers now contain three objects. Follow the same process when creating database-servers object group.

Now that we have all needed objects created, its time to put a some security policy in place with and ACL.

Creating Access Control List

First we are going to define that web servers can talk to backend database on mysql port. The global ACL resource URL is located at https://<managment-ip>/api/access/global/rules

{
        "sourceAddress": {
        "kind": "objectRef#NetworkObjGroup",
        "objectId": "web-servers"
      },
      "destinationAddress": {
        "kind": "objectRef#NetworkObjGroup",
        "objectId": "database-servers"
      },
      "sourceService": {
        "kind": "objectRef#NetworkServiceGroup",
        "objectId": "mysql"
      },
      "destinationService": {
        "kind": "objectRef#NetworkServiceGroup",
        "objectId": "mysql"
      },
      "permit": true,
      "active": true,
      "position":1,
      "remarks": ["1 REST_PROJECT: WEB to DB"],
      "ruleLogging": {
        "logInterval": 300,
        "logStatus": "Informational"
      }
}

From web servers to Internet on web port:

{
        “sourceAddress”: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “web-servers
      },
      “destinationAddress”: {
        “kind”: “AnyIPAddress“,
        “value”: “any
      },
      “sourceService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “http
      },
      “destinationService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “http
      },
      “permit”: true,
      “active”: true,
      “position”:2,
      “remarks”: [“2 REST_PROJECT: WEB to INTERNET HTTP“],
      “ruleLogging”: {
        “logInterval”: 300,
        “logStatus”: “Informational
      }
}

From web servers to Internet on https port:

{
        “sourceAddress”: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “web-servers
      },
      “destinationAddress”: {
        “kind”: “AnyIPAddress“,
        “value”: “any
      },
      “sourceService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “https
      },
      “destinationService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “https
      },
      “permit”: true,
      “active”: true,
      “position”:3,
      “remarks”: [“3 REST_PROJECT: WEB to INTERNET HTTPS”],
      “ruleLogging”: {
        “logInterval”: 300,
        “logStatus”: “Informational
      }
}

From Internet to web servers on web port:

{
        “sourceAddress”: {
        “kind”: “AnyIPAddress“,
        “value”: “any
      },
      “destinationAddress”: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “web-servers
      },
      “sourceService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “http
      },
      “destinationService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “http
      },
      “permit”: true,
      “active”: true,
      “position”:4,
      “remarks”: [“4 REST_PROJECT: INTERNET TO WEB HTTP“],
      “ruleLogging”: {
        “logInterval”: 300,
        “logStatus”: “Informational
      }
}

You could very like fire just one bulk request that will contain all access control list entries, I will elaborate on optimizations in an upcoming article.

I found out that when you create the first global access list entry, ASA will automatically name it global_access and will apply it same way as you would enter access-group global_access global.

Saving the configuration

Once you finish playing with the ASA, do not forget to save your configuration by jumping on a CLI and typing write memory or elegantly through the following POST method against the URL https://<managemenet-ip>/api/cli. This method is called generic CLI command executer and can be used for anything that was not implemented through direct call at this point.

{
  "commands": [
    "write memory"
  ]
}

rest-server-wrmem

Verification and debugging

You have several methods to verify the applied global policy. Either use browser and test that the application is working as expected pulling data from database, or perform a quick check with packet tracer right on the ASA.

asav01# packet-tracer input dmz tcp 172.16.1.11 50006 172.16.0.11 3306

Phase: 1
Type: ACCESS-LIST
Subtype:
Result: ALLOW
Config:
Implicit Rule
Additional Information:
MAC Access list

Phase: 2
Type: ROUTE-LOOKUP
Subtype: Resolve Egress Interface
Result: ALLOW
Config:
Additional Information:
found next-hop 172.16.0.11 using egress ifc  inside

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group global_access global
access-list global_access extended permit object-group mysql object-group web-servers object-group database-servers log
access-list global_access remark 2 CHG0063555: WEB to INTERNET HTTP
object-group service mysql
 service-object object TCP-3306
object-group network web-servers
 description: Corporate web servers
 network-object object web01
 network-object object web02
 network-object object web03
object-group network database-servers
 description: Corporate db servers
 network-object object db01
 network-object object db02
Additional Information:

Phase: 4
Type: NAT
Subtype: per-session
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 6
Type: QOS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 7
Type: QOS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 8
Type: NAT
Subtype: per-session
Result: ALLOW
Config:
Additional Information:

Phase: 9
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 10
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 2344, packet dispatched to next module

Result:
input-interface: dmz
input-status: up
input-line-status: up
output-interface: NP Identity Ifc
output-status: up
output-line-status: up
Action: allow

To verify that the REST API plugin is enabled and configured, issue the following commands at CLI:

asav01# show rest-api agent
REST API agent is currently enabled.

There are also several debug options that can help you troubleshoot why it is not working:

asav01# debug rest-api ?

  agent    Rest-API Agent
  cli      Rest-API cli handling
  client   Rest-API client request handling
  daemon   Rest-API debug/syslog handling
  process  Starting/Stopping of Rest-API Agent
  <cr>

asav01# debug rest-api client
asav01# [ra client event]: rest_agent_connect: Opening TCP socket to REST API Agent succeeded.
[ra client event]: rest_agent_connect: Connecting to TCP socket succeeded.
[ra client event]: rest_agent_buf_push_and_receive: socks_proxy_csocket_send succeeded.
[ra client event]: rest_agent_buf_push_and_receive: temporarily no message received.
[ra client event]: send_response_to_rest_client: Received response message of length 424 from REST Agent.
[ra client event]: rest_agent_buf_push_and_receive: Received the entire HTTP response of length 424 – closing the connection with REST API Agent.

You can find more details on which each option does in the documentation in the end of the post. There are also API-related syslog messages that can be examined when issues arise.

Conclusion

It might seem that to accomplish such simple configuration as creating a couple of objects and adding them to global access rule takes a lot of manual writing, but bare in mind that the actual scripts in real world would be populated with the right values dynamically by the deployment script. The nice thing is that every object has its unique resource path in ASA, therefore an un-deployment script can remember these values when doing application removal.

And with that last toughs my friends this long post came to its end. I hope that you learned something new today and let me what are your feelings about this new method of configuration and if you are thinking to deploy applications in near future that would program the ASA for themselves automagically.

Resources

About the ASA REST API

http://www.cisco.com/c/dam/en/us/td/docs/security/asa/api/asapedia_rest_api.pdf

Cisco ASA REST API Quick Start Guide

http://www.cisco.com/c/en/us/td/docs/security/asa/api/qsg-asa-api.html