Tag Archives: security

Cisco ASAv firewall REST API: Bulk Requests

Introduction

Continuing on the same track with ASA REST API we are going to explore how to be more efficient when firing up the json code toward our firewalls. In previous example we created a small number of service and network objects and groups, today we are going to experiment with larger number of objects created by smaller number of calls. Lets get the ball rolling.

Bulk service object creation

To create a bulk request we need to adjust some parameters such as API endpoint URL. As you recall, when we created a new service object we were pointing to this URL: https://<management-ip>/api/objects/networkservices.

Now we are going to redesign the call a little bit and will always point to same endpoint regardless of object type. We will simply use https://<management-ip>/api and the more specific resource URI will be part request body. This allows us for example create bulk of service and network objects in one call.

[
  {
    "resourceUri": "/api/objects/networkservices",
    "data": {     
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-21",
  "value": "tcp/21"
}, "method": "Post" }, { "resourceUri": "/api/objects/networkservices",    "data": {
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-22",
  "value": "tcp/22"
}, "method": "Post" }, { "resourceUri": "/api/objects/networkservices",    "data": {
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-23",
  "value": "tcp/23"
}, "method": "Post" }, { "resourceUri": "/api/objects/networkservices", "data": {
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-24",
  "value": "tcp/24"
}, "method": "Post" }
]

If everything is hunky dory you will receive a Status Code 200 OK and response body will contain additional details.

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

Ideally your deployment script would examine the response and capture the self links that can be used to un-deploy this call. Also the message details are important to verify if objects were successfully created.

Now we are going to look at error handling by creating another request that will have one already existing object and one new in it.

[
  {
    "resourceUri": "/api/objects/networkservices",
    "data": {     
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-24",
  "value": "tcp/24"
}, "method": "Post" }, { "resourceUri": "/api/objects/networkservices", "data": {
  "kind": "object#TcpUdpServiceObj",
  "name": "TCP-25",
  "value": "tcp/25"
}, "method": "Post" }
]

The response header will contain 400 Bad Request status code and body will reveal some clues.

{
"entryMessages":
[
     {
     "resourceUri":"/api/objects/networkservices",
     "method":"POST",
     "messages":
     [
         {
         "level":"Error",
         "code":"DUPLICATE",
         "context":"objectId",
         "details":"TCP-24"
         }
     ]
     },
     {
     "resourceUri":"/api/objects/networkservices",
     "method":"POST"
     }
],
"commonMessages":[]
}

The result result is that even the second object did not exists it was not created. When you reverse the object order in request, it will not help either. This means that the entire request need to create unique objects otherwise it will fail. So watch for return codes.

I have tried to create 103 unique objects in one request and I have found that the upper limit for single request is 100 entries.

{
"commonMessages":
[
     {
     "level":"Error",
     "code":"MAX-ENTRIES-LIMIT-EXCEEDED",
     "details":"The number of entries found are, 103. The bulk entries limit:100"
     }
]
}

Lets go back to our first four service objects and undeploy them using four unique DELETE Requests. The resource URIs are as follows:

Note: So far I have not found way of performing multiple object removal in single request. It seems that bulk operation only supports POST method toward service objects at the moment. The following below did not work.

[
  {
    "resourceUri": "/api/objects/networkservices/TCP-21",
    "method": "Delete"
  },
  {
    "resourceUri": "/api/objects/networkservices/TCP-21",
    "method": "Delete"
  }
]

Response had status code 400 Bad Request even if those URI are indeed valid and you can query them with GET request.

{
"entryMessages":
[
     {
     "resourceUri":"/api/objects/networkservices/TCP-21",
     "method":"DELETE",
     "messages":
     [
         {
         "level":"Error",
         "code":"INVALID-INPUT",
         "details":"Invalid resourceUri:/api/objects/networkservices/TCP-21"
         }
     ]
     },
     {
     "resourceUri":"/api/objects/networkservices/TCP-21",
     "method":"DELETE",
     "messages":
     [
         {
         "level":"Error",
         "code":"INVALID-INPUT",
         "details":"Invalid resourceUri:/api/objects/networkservices/TCP-21"
         }
     ]
     }
],
"commonMessages":[]
}

The 100 objects limitations also affect how are the responses constructed. When you query the following resource https://<management-ip>/api/objects/networkservices you will see that the body contains only 100 items even if 110 exists. You can see this by examining the offset, limit and total fields on body.

{
   "kind": "collection#NetworkServiceObjects",
   "selfLink": "https://10.201.230.5/api/objects/networkservices",
   "rangeInfo":
   {
       "offset": 0,
       "limit": 100,
       "total": 110
   },

Funny enough, the list will not start with the first configure service objects, but started from TCP-100 up till TCP-200. To see other items you need to manipulate the offset value. We can demonstrate this using API Console at documentation page.

rest-api-offset

Now the item list will start from TCP-110 and will include our older objects such as TCP-21, TCP-22 etc. You can also play with the limit parameter to constrain number of returned objects. If you look at Inspector, you will see the request parameters have been modified to include our query parameters.

rest-api-offset-body

Conclusion

Bulk object creation and retrieval handling should help you build more efficient communication patters between the firewall and automation tool or network controller.

Advertisements

Cisco ASAv firewall REST API – Resource Manipulation

Introduction

After the initial article about ASAv REST API we are going to explore how we can granularity manipulate various resources such as objects and object-groups. You will learn how to create modify, verify and delete each object type.

This can be useful when building an automation tool that needs to perform various configuration changes programmatically.

Service Object

Service objects are one of the most common objects types used in firewall. They can define OSI Layer 4 TCP and UDP ports as well as other protocols such as ARP, or GRE. We are going to demonstrate some basic operations that can be carried out with this type of object. CLI reference is also provided for comparison with REST API.

Create

CLI Reference

object service UDP-88
 service udp destination eq 80

Request Format

Header:
URL: https//<management-ip>/api/object/networkservices
Method: POST

Body:

{
  "kind": "object#TcpUdpServiceObj",
  "name": "UDP-88",
  "value": "udp/80"
}

Response Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 09:52:01 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

As you can see, when we created new object we got its location URI. We will reference this address when doing changes or object removal. For service object the reference name is the object ID.

Modify

CLI Reference

object service UDP-88
 service udp destination eq 88

Request Format

Header:
URL: https//<management-ip>/api/objects/networkservices/UDP-88
Method: PATCH

Body:

{
  “kind”: “object#TcpUdpServiceObj“,
  “name”: “UDP-88“,
  “value”: “udp/88
}

Response Header Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 09:52:48 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Patch request can be used to change resource attributes such as value or name.

Retrieve

CLI Reference

show run | be object service UDP-88
 Note: As ASA CLI does not include show object id command, this was the easiest way how to list object in running configuration.

Request Format

Header:

URL: https://<management-ip>>/api/objects/networkservices/UDP-88
Method: GET

Body: Empty

Response Format

Header:
Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 158
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 09:58:14 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Body:
{
   “kind”: “object#TcpUdpServiceObj“,
   “name”: “UDP-88“,
   “value”: “udp/88“,
   “objectId”: “UDP-80
}

GET request does not require anything in request body and when referencing certain object ID such as UDP-88 it will return just single resource. To get list of all resources under parent resource just remove the ID from the end of URL.

Delete

CLI Reference

no object service UDP-88

Request Format

Header
URL: https://<management-ip>/api/objects/networkservices/TCP-88
Method: DELETE

Body: Empty

Response Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 10:02:05 GMT
Server: CiscoASARestApiServer

With REST API Delete request, rules still apply that you cannot remove an object that is being used or referenced elsewhere in configuration.

Service Object Group

As name implies service object groups glue together multiple objets. This eases the configuration and provides a little abstraction and simplification when constructing access rules.

Create

CLI Reference

object-group service krb5-udp
 description Default Kerberos UDP port
 service-object object UDP-88

Request Format

(Object within object group)

Header:
URL: https://<management-ip>/api/objects/networkservicegroups
Method: POST

Body:

{
"kind": "object#NetworkServiceGroup",
"name": "krb5-udp",
"members":
[
{
"kind": "objectRef#TcpUdpServiceObj",
"objectId": "UDP-88"
}
],
"description": "Default Kerberos UDP port"
}

Response Format

Header:
Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 124
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 10:35:10 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Request Format

(Object group within another object group)

CLI Reference

object-group service krb5-udp
 group-object krb5-udp

Header:

URL: https://<management-ip>/api/objects/networkservicegroups
Method: POST

Body:

{
"kind": "object#NetworkServiceGroup",
"name": "active-directory",
"members":
[
{
"kind": "objectRef#NetworkServiceGroup",
"objectId": "krb5-udp"
}
],
"description": "Default Active Directory ports"
}

Response Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 11:06:44 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Modify

CLI Reference

object-group service krb5-udp
 group-object krb5-udp
 group-object krb5-tcp

Request Format

(To change/add objects withing a group)

URL: https://<management-ip>/api/objects/networkservicegroups/active-directory
Method: PATCH

Body:

{
"kind": "object#NetworkServiceGroup",
"name": "active-directory",
"members":
[
{
"kind": "objectRef#NetworkServiceGroup",
"objectId": "krb5-udp"
},
{ "kind": "objectRef#NetworkServiceGroup", "objectId": "krb5-tcp" } ], "description": "Default Active Directory ports" }

Response Format

Header:
Status Code: 204 No Content
Content-Length: 0
Location: https://10.201.230.5/api/objects/networkservicegroups/active-directory
Server: CiscoASARestApiServer
Accept-Ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Date: Wed, 18 Feb 2015 11:57:32 GMT

Retrieve

CLI Reference

show object-group id active-directory

Request Format

 

URL: https://<management-ip>>/api/objects/networkservicegroups/active-directory
Method: GET

Body: Empty

Response Format

Header:

Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 512
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 12:01:52 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Body:
{
   “kind”: “object#NetworkServiceGroup“,
   “name”: “active-directory“,
   “members”:
   [
       {
           “kind”: “objectRef#NetworkServiceGroup“,
           “objectId”: “krb5-tcp
       },
       {
           “kind”: “objectRef#NetworkServiceGroup“,
           “objectId”: “krb5-udp
       }
   ],
   “description”: “Default Active Directory ports“,
   “objectId”: “active-directory
}

Delete

(Entire object group)

CLI Reference

no object-group service active-directory

Request Format

URL: https://<management-ip>/api/objects/networkservicegroups/active-directory

Method: DELETE

Body: Empty

Response Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 12:11:13 GMT
Server: CiscoASARestApiServer
(Delete Object within a object group)

CLI Reference

object-group service active-directory
 no  group-object krb5-tcp

Request Format

Header:

URL: https://<management-ip>/api/objects/networkservicegroups/active-directory
Method: PATCH

Body:

{
     “kind”: “object#NetworkServiceGroup“,
     “name”: “active-directory“,
     “members”:
     [
         {
             “kind”: “objectRef#NetworkServiceGroup“,
             “objectId”: “krb5-udp
         }
      ],
      “description”: “Default Active Directory ports
}

Note: To delete an object within an object group, you can use Put operation with all existing objects except the ones you need to delete.In this particular example I am only leaving krb5-udp in the group.

Response Format

Header:
Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 374
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 12:07:46 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Object Network

Create

CLI Reference (host)

object network win-dc-01
 host 10.0.0.10

REST Request Format (host)

 

URL: https://<management-ip>/api/objects/networkobjects

Method: POST

Body:

{
  “host”: {
    “kind”: “IPv4Address“,
    “value”: “10.0.0.10
  },
  “kind”: “object#NetworkObj“,
  “name”: “win-dc-01
}

REST Response Header Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 14:40:47 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

CLI Reference (network)

object network web-tier
 subnet 172.16.0.0 255.255.255.0

REST Request Format

Method: POST
Body:
{
  “host”: {
    “kind”: “IPv4Network“,
    “value”: “172.16.0.0/24
  },
  “kind”: “object#NetworkObj“,
  “name”: “web-tier
}

REST Response Header Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 14:48:08 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Modify

CLI Reference (host)

object network win-dc-01
 host 10.0.0.11

Request Format

(To change/add objects withing a group)

Header

URL: https://<management-ip>/api/objects/networkobjects/win-dc-01
Method: PATCH

Body:

{
  “host”: {
    “kind”: “IPv4Address“,
    “value”: “10.0.0.11
  },
  “kind”: “object#NetworkObj“,
  “name”: “win-dc-01
}

Response Format

Header:
Status Code: 204
Content-Length: 0
Location: https://10.201.230.5/api/objects/networkobjects/win-dc-01
Server: CiscoASARestApiServer
Accept-Ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Date: Wed, 18 Feb 2015 14:43:44 GMT

Retrieve

CLI Reference

show run | be object network win-dc-01

Request Format

Method: GET
Body: Empty

Response Format

Header:

Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 191
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 14:49:59 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Body:
{
   “kind”: “object#NetworkObj“,
   “name”: “win-dc-01“,
   “host”:
   {
       “kind”: “IPv4Address“,
       “value”: “10.0.0.11
   },
   “objectId”: “win-dc-01
}

Delete

CLI Reference

no object network win-dc-01
Request Format
Method: DELETE
Body: Empty

Response Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 14:52:26 GMT
Server: CiscoASARestApiServer

Network Object Group

Create

CLI Reference

object-group network dc-win-servers
 network-object object dc-win-01

REST Request Format (host)

URL: https://<management-ip>/api/objects/networkobjectgroups
Method: POST

Body:

{
     “kind”: “object#NetworkObjGroup“,
     “name”: “dc-win-servers“,
     “members”:
     [
         {
             “kind”: “objectRef#NetworkObj“,
             “objectId”: “win-dc-01
         }
     ],
     “description”: “Corporate AD Servers
}

REST Response Header Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 15:02:28 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Modify

CLI Reference (host)

object-group network dc-win-servers
 network-object object dc-win-01
 network-object object dc-win-02

Request Format

(To change/add objects withing a group)
Header:
Method: PATCH

 

Body:

{
           “kind”: “object#NetworkObjGroup“,
           “name”: “dc-win-servers“,
           “members”:
           [
               {
                   “kind”: “objectRef#NetworkObj“,
                   “objectId”: “win-dc-01
               },
               {
                   “kind”: “objectRef#NetworkObj“,
                   “objectId”: win-dc-02
               }
           ],
           “description”: “Corporate AD Servers
}

Response Format

Header:
Status Code: 204
Content-Length: 0
Location: https://10.201.230.5/api/objects/networkobjectgroups/dc-win-servers
Server: CiscoASARestApiServer
Accept-Ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Date: Wed, 18 Feb 2015 15:09:07 GMT

Retrieve

 

CLI Reference

show object-group id dc-win-servers

Request Format

 
Method: GET
Body: Empty

Response Format

Header:

Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 465
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 15:12:39 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Body:
{
   “kind”: “object#NetworkObjGroup“,
   “name”: “dc-win-servers“,
   “members”:
   [
       {
           “kind”: “objectRef#NetworkObj“,
           “refLink”: “https://10.201.230.5/api/objects/networkobjects/win-dc-01“,
           “objectId”: “win-dc-01
       },
       {
           “kind”: “objectRef#NetworkObj“,
           “refLink”: “https://10.201.230.5/api/objects/networkobjects/win-dc-02“,
           “objectId”: “win-dc-02
       }
   ],
   “description”: “Corporate AD Servers“,
   “objectId”: “dc-win-servers
}

Delete

CLI Reference

no object-group network dc-win-servers

Request Format

Header:
Method: DELETE
Body: Empty

Response Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 15:16:43 GMT
Server: CiscoASARestApiServer

To delete an object within an object group you can use the same approach with Patch operations and listing only objects that you want to keep in object group.

Access Control List

Create

CLI Reference

access-list global_access remark Allow web-tier to Domain Controllers
access-list global_access extended permit object-group active-directory object-group web-and-db-tier object-group dc-win-servers log
access-group global_access global

REST Request Format (host)

Header:
Method: POST
Body:
{
        “sourceAddress”: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “web-and-db-tier
      },
      “destinationAddress”: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “dc-win-servers
      },
      “sourceService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “active-directory
      },
      “destinationService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “active-directory
      },
      “permit”: true,
      “active”: true,
      “remarks”: [“Allow web-tier to Domain Controllers“],
      “ruleLogging”: {
        “logInterval”: 300,
        “logStatus”: “Informational
      }
}
To create another line in same global ACL just modify the Request body and a new line will be added in the end of ACL. A reference value will be returned.

REST Response Header Format

Header:
Status Code: 201 Created
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 15:35:20 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept

Modify

CLI Reference

access-list global_access remark Allow Domain Controllers to Web-Tier
access-list global_access extended permit object-group active-directory object-group dc-win-servers object-group web-and-db-tier log
access-group global_access global

Request Format

(To change/add objects withing a group)
Header:
URL: https://<management-ip>/api/access/global/rules/3028343169
Method: PATCH

Body:

{
        “sourceAddress“: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “dc-win-servers
      },
      “destinationAddress“: {
        “kind”: “objectRef#NetworkObjGroup“,
        “objectId”: “web-and-db-tier
      },
      “sourceService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “active-directory
      },
      “destinationService”: {
        “kind”: “objectRef#NetworkServiceGroup“,
        “objectId”: “active-directory
      },
      “permit”: true,
      “active”: true,
      “remarks”: [“Allow Domain Controllers to Web Tier“],
      “ruleLogging”: {
        “logInterval”: 300,
        “logStatus”: “Informational
      }
}

Response Format

Header:
Status Code: 204
Content-Length: 0
Location: https://10.201.230.5/api/access/global/rules/2372118638
Server: CiscoASARestApiServer
Accept-Ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Date: Wed, 18 Feb 2015 15:44:50 GMT

Retrieve

 

CLI Reference

show access-list global_access

Request Format

 
Method: GET
Body: Empty

Response Format

Header:

Status Code: 200 OK
Accept-Ranges: bytes
Content-Length: 2088
Content-Type: application/json; charset=UTF-8
Date: Wed, 18 Feb 2015 15:55:03 GMT
Server: CiscoASARestApiServer
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Body:
{
   “kind”: “collection#ExtendedACE“,
   “rangeInfo”:
   {
       “offset”: 0,
       “limit”: 2,
       “total”: 2
   },
   “items”:
   [
       {
           “kind”: “object#ExtendedACE“,
           “selfLink”: “https://10.201.230.5/api/access/global/rules/3028343169“,
           “permit”: true,
           “sourceAddress”:
           {
               “kind”: “objectRef#NetworkObjGroup“,
               “objectId”: “web-and-db-tier
           },
           “destinationAddress”:
           {
               “kind”: “objectRef#NetworkObjGroup“,
               “refLink”: “https://10.201.230.5/api/objects/networkobjectgroups/dc-win-servers“,
               “objectId”: “dc-win-servers
           },
           “sourceService”:
           {
               “kind”: “objectRef#NetworkServiceGroup“,
               “objectId”: “active-directory
           },
           “destinationService”:
           {
               “kind”: “objectRef#NetworkServiceGroup“,
               “objectId”: “active-directory
           },
           “active”: true,
           “remarks”:
           [
               “Allow web-tier to Domain Controllers
           ],
           “ruleLogging”:
           {
               “logInterval”: 300,
               “logStatus”: “Informational
           },
           “isAccessRule”: true,
           “position”: 1,
           “objectId”: “3028343169
       },
       {
           “kind”: “object#ExtendedACE“,
           “selfLink”: “https://10.201.230.5/api/access/global/rules/2372118638“,
           “permit”: true,
           “sourceAddress”:
           {
               “kind”: “objectRef#NetworkObjGroup“,
               “refLink”: “https://10.201.230.5/api/objects/networkobjectgroups/dc-win-servers“,
               “objectId”: “dc-win-servers
           },
           “destinationAddress”:
           {
               “kind”: “objectRef#NetworkObjGroup“,
               “objectId”: “web-and-db-tier
           },
           “sourceService”:
           {
               “kind”: “objectRef#NetworkServiceGroup“,
               “objectId”: “active-directory
           },
           “destinationService”:
           {
               “kind”: “objectRef#NetworkServiceGroup“,
               “objectId”: “active-directory
           },
           “active”: true,
           “remarks”:
           [
               “Allow Domain Controllers to Web Tier
           ],
           “ruleLogging”:
           {
               “logInterval”: 300,
               “logStatus”: “Informational
           },
           “isAccessRule”: true,
           “position”: 2,
           “objectId”: “2372118638
       }
   ]
}

Delete

CLI Reference

no access-list global_access remark Allow Domain Controllers to Web Tier
no access-list global_access extended permit object-group active-directory object-group dc-win-servers object-group web-and-db-tier log

Request Format

Header:
Method: DELETE
Body: Empty

Response Format

Header:
Status Code: 204 No Content
Accept-Ranges: bytes
Content-Length: 0
Date: Wed, 18 Feb 2015 15:52:34 GMT
Server: CiscoASARestApiServer

Conclusion

ASA REST API is a very powerful interface, and as times goes I am sure that for customers that invested in this firewall product it will be the preferred way how to program their security policies automatically during application deployment.

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

Cisco ASAv firewall installation

Introduction

The data center networking trend is clear with every network service being slowly virtualized. Network devices that are virtual provide big advantage over their physical counterparts. First, VMs can be provisioned much more quicker and be part of a larger virtual infrastructure, you can easily scale them adding more virtual CPU or memory and you can snapshot them to save their actual state to a file and move them around.

Cisco has also introduced their virtual version of their popular firewall product ASA. It simple called ASAv and runs under popular hypervisors such as VMware vSphere or KVM. You can find the product home page here. This is different product and idea than Cisco ASA 1000V Cloud Firewall.

First you need to get hold of the ova package. You need to be entitled with Cisco to download the software from here or you can do a Google search and find it elsewhere. I had some problems with the latest release 9.3.2(200) where it would stuck at booting loop, the kernel complained about Illegal Instruction. Looks like it did not like my dual Opteron 4180 host. Therefore in this demo we are going to use release 9.3.1 which worked just fine.

Sharping the axe

Before we are going to deploy the actual virtual firewall, lets make some solid ground for it. Firewalls usually divide network into multiple security zones so first we are going to create some, and we use vSwitches for that. In my vSphere deployment I already have default vSwitch called vSwitch0, with a Portgroup called Native that has a connection to outside world.

We are going to create additional two vSwitches that will have following Portgroups: ASAv-inside and ASAv-DMZ respectively, and we are going to attach two linux instances to them. So in the end we end up with simple topology like this:

asav-network

To get started, log in to vSphere and go to Hosts\Configuration\Networking\Virtual Standard Switch, click add Add networking.

Select New Standard Switch, there is no need to assign physical adapter for breakout, we will attach this vSwitch to one of ASAv interfaces. The first port group will be called ASAv-inside with no VLAN tag. Follow the same steps for DMZ vSwitch and its ASAv-DMZ PortGroup.

asav1

Chopping the tree

Back to ASAv, after downloading, log into the vCenter and go to VMs and File\Deploy OVF Template.

Note: I tried to deploy the asav932-200.ova directly into ESXi, however I received and error that The OVF package requires support for OVF properties. Details: Line 264: Unsupported element ‘Property’

Answer the usual OVF deployment question such as name of VM, which Data Center and Cluster will be used. I only have one so it is no brainier. Deployment configuration specifies the number of vCPU that the VM will have and whether it will be part of HA pair. By default ASAv will come with 1 Management Interface Management0/0 and 9 regular interfaces GigabitEthernet0/0 – 0/8. You need to map each of them to correct port group created in previous step.

I am only really using 4 interfaces at this point, so I left the rest connected in ASAv-DMZ portgroup.

asav2

1 Mgmt Interface and 9 Regular Interfaces

Some basic configuration parameters such as IP configuration of management interface can also be entering during wizard. That makes me wonder if those parameters can be passed to template while deploying automatically via script.

asav3

Initial Configuration Options

After quick OVF deployment, you can look at default resource requirements which correspond to deployment size selected in wizard.

asav6

Resource utilization

And finally the ASAv console is available directly through vCenter.

asav3

ASAv Virtual Console

Before you can take full advantage of all ASAv features in your lab you need to license the box. If you are lucky you can ask a Cisco representative for a temporary license or *hint* do a smart Google search for a little piece of software.

Initial Configuration

To actually verify that the ASAs has indeed network connectivity, we will perform initial configuration and test reach ability to Google DNS servers.

#First virtual interface mapped to Native PortGroup
#
interface GigabitEthernet0/0
nameif outside
security-level 0
ip address dhcp
#
#Second virtual interface mapped to ASAv-inside PortGroup
#
interface GigabitEthernet0/1
nameif inside
security-level 100
ip address 192.168.1.1 255.255.255.0
#
#Management virtual interface mapped to Backend PortGroup
#
interface Management0/0
management-only
nameif management
security-level 0
ip address 10.0.1.41 255.255.255.0
#
# DNS, SSH and routing
#
dns server-group DefaultDNS
name-server 8.8.8.8
!
route outside 0.0.0.0 0.0.0.0 10.0.2.1 1
aaa authentication ssh console LOCAL
ssh 10.0.1.0 255.255.255.0 management
username cisco password

Verification

asav5

If you are currently aiming for CCIE Security this is an excellent way how to build your own virtual lab for practice. Coupled with virtual ACS server and IPS appliances it is very easy to test and learn new features, validate syntax for scripts and many more without harming your production environment.

I draw the line in the sand here and leave your imagination what you can do with multiple of these virtual firewalls bundled with couple of virtual routers and virtual machines to re-create complete data center infrastructure sandbox.

Resources

Introduction to ASAv

http://www.cisco.com/c/en/us/td/docs/security/asa/asa92/asav/quick-start/asav-quick/intro-asav.html

ASAv Product Overview

http://www.cisco.com/c/en/us/products/collateral/security/adaptive-security-virtual-appliance-asav/datasheet-c78-733399.pdf

Deploying ASAv

http://www.cisco.com/c/en/us/td/docs/security/asa/asa92/configuration/general/asa-general-cli/intro-asav.pdf

Security+ Series Part 9: Strategies to Reduce Risks

Hello and welcome back to the Security+ series. After a long awesome break we will jump straight into strategies that help reduce risks in our super secret enterprise enviroment. You will learn a bunch of new stuff about change management, user permissions, audits and other various tech controls that help keep 0100101100 secure and available. Lets get the ball rolling.

Music Recommendation for this article: Deftones – White pony

Change management

Imagine that you have a very dynamic environment where the rate of chages is huge. Server ops team is banging their heads implementing Heartbleed patch to Unix frontends, network security folks is migrating main Data Center ATM WAN links, and you are sharping your knife for next complex routing party which will change global traffic flow. Without a proper controls in place these actions carried out at same time could interfere with each other creating a mess.

Therefore there is a need to keep track of all planned changes. A change management code such as HP Service Manager helps with that. There can be multiple types of changes like easy cheese routine, normal and emergency change that need to be done asap, and the process of implement thoses changes will be different.

A typical change would go through process of planning and preparing the configuraiton scripts, scheduling the implementation date, assessing the possible risks, defining the configuration item – CI that this change will affect and other basic variables. Then you would pass it to your team mate for peer review. After that it would go through Technical Advisory Board – TAB and then Change Advisory Board – CAB. The more ciritical the environment is, the lenghtier the process is. Finally after all approval, you are allowed to carry out with the change. After succesfully implemting a change, a closure process follow. It will require information like actual implementation time, post change verification and closure comment.

HP Service Manager is what HP folks uses to plan the changes.

Incident Management

As the name implies incidement management describes the steps that are usually followed when we face a service outage. It defines how to log an incident, e.g. thorugh a service desk manually, or automatically through monitoring solution. Incidents are then assigned to a group or an individual that is trying to restore the affected service. A root cause analysist is perfomed and it determines what triggered this outage. This could be for example a power supply or module failure, or a software bug or misconfiguration after a unsuccessfull change.

To resolve future incidents quicker a lesson learned is tracked in database for teams to review and learn from them.

Incident Management Simply

User Rights and Permission Management

In a typical business there are many boring job roles, such as human resources, accounting, marketing, technical services and more. Each employee requires access to certain applications and services to perform his everyday tasks. This implies that there is some kind of separation of who can access what. I would not like your receptionist to have permission to change to core data center switches would you? No saying she would really care.

User rights help maintain the right level of permissions to resources. These controls can be found in every system that is out there. From user accounts in Windows domain, network infrastructure devices, remote access and so forth.

User Account Control makes itself heard

Routine audits

A regular security audits are mandatory everytime a company handles precious information such as health record or credit card numbers. It is carried out by internal or external team who perform a penetration testing against live system to determine if the company put enough security measures to keep the bad guys out. Audit can reveal configuration weaknesses or unpatched systems that could lead to data and reputation loss, giving a big advantage to your competition.

Me neither

Preventing Data Loss

There are many ways to prevent data loss. For example a solid rock organizationa policy could outline how the systems needs to be used securely. Technical measures such as configuration best practices and tight firewall rules can also help prevent data leaking out from our pipes. There are even technologies that specialize in this particular area. For example Checkpint has a firewall blade that can help mitigate accidential leakage of sensitive information.

And that my friends is the end of this short part of Security+ Series. If you are studying for the CompTia Security+ exam, you are one step closer to your goal.I hope you enjouyed reading it as much as I enjoyed writing it. In next one we will look what is Forensics all about and some basic terms and examples related to it.

Inside the Dark Web

I came across this very interesting documentary film by BBC which discusses important issues around Internet privacy and mass surveillance. In this film, you will learn what level of privacy we have on the Internet,  what is TOR, Dark Web, why we need Wikileaks and what makes Bit Coin digital currency so unique compared to traditional electronic money.

Security+ Series Part 8: 3rd Party Integration Risks

Our Security+ fast track continues, and in this article we will look at terms that are used in conjunction with 3rd party integration and associated risks.

Sooner or later your company grows larger and start to make business with other companies. Your business applications and data needs to be accesses by your partners and customers.

This lesson will teach you about concepts that can help you deal with data protection when such situation happens.

Lets get going.

On-boarding/Off-boarding business partners

Well the name says it all. The best practice is to have a policy or procedure defined when such event occurs. This could encompass what kind of access is needed, to what data at what circumstances. For example you can setup a secure VPN for your supplier.

There is a certain procedure when kids are being on boarded onto the school bus

Social media networks and/or applications

Social networks  are phenomenon of our time. If you use them right way they can offer you great benefits. Your marketing department can use these media for marketing company, product promotion or general feedback from customers.

There are however also some risk associated with social network missuses. If your employees are not trained well they could accidental leak private information.

Your policy should also outline how to use these media the proper way.

Starbucks using Facebook for promoting pumpkin spice latte

Interoperability agreements

There are several agreements that can be signed between two entities when they decided to work together for common goal. Here are the most often used:

There can be a lot of agreements between two parties

SLA

Service Level Agreement is a formal document between two parties that defines what service is being offered. For example when you order a MPLS VPN service to meet you branch connectivity needs, you will agree with provider what level of service you have in terms of access rates, quality of service, service availability.

BPA

Business partner agreement is yet another document that can be signed between partners when you decide to go do business together. It may contain things like profit sharing, cost sharing and so on.

MOU

A less bilateral document called Memorandum of Understanding describes a gentlemen agreement between two companies that plan to do a business together. It outlines what they are trying to accomplish together.

ISA

Interconnection security agreement is a document that mandates what actions needs to be taken when connecting or disconnecting to a business partner. It focuses on technology side of the partnership. An example can be found here.

Privacy considerations

When you have many partners and customers, you need to make sure that the data they are working with are safe and confidential. You would not like of partner A could access partners B data, or use your network as a transit.

Risk awareness

Before we can mitigate the risks we first need to aware of it. Risk awareness training is important not only for your own staff, but for partners and suppliers. They can all help you solidify the integrity of your company.

Unauthorized data sharing

When you are working with a partner make sure you are only giving access to data that are needed to complete the workflow. This way you minimize the risk of unauthorized data sharing. You also need to be clear on how your partner will protect your data within their infrastructure.

Data is slowly leaking out of your data pipes just like water.

Data ownership

When you working on a project for a customer you may often involve some of your partners to deliver sub-service. For example your company may take care of server part while your partner will deliver the network infrastructure.

In such case you need to agree where you will store project documents such as sales orders, design documents, configuration scripts and others. You also need to decide who will present these documents to end customers – this may for example affect the document form, logos, forms and so on.

Data backups

As I mentioned above, when data ownership is sorted out, it is vital to agree who will protect the data against loss. Usually the data owner is responsible for this part.

Follow security policy and procedures

As my colleagues would say, stay calm and carry on. At your company you have certain procedures how to handle data, perhaps depending on security level. Make sure that your business is also aware and follows the policy when handling the data.

Review agreement requirements to verify compliance and performance standards 

When you have everything written, make sure that you and your partner know and understand the requirements for using data that he is access. Performance standards can describe what level of resources will the partner have, for example in virtualized environments this can encompass the pool of RAM, CPU or Storage.

And we came to a very end of this article. As I always I hope you learned something useful and see you in next post in the series which will cover some strategies to reduce risks.