Featured image of post How to use Postman for Cisco ACI?

How to use Postman for Cisco ACI?

Postman allows for easy API Calls to Cisco ACI, in this post you learn how to use Postman together with Cisco ACI!

Home / Posts / How to use Postman for Cisco ACI?

What is Postman?

Postman started as an API Client to allow for easy testing and working with APIs. You could compare it to a Browser that you use for accessing traditional webpages, but for APIs. Instead of having to write code, you can leverage Postman to do the first interaction with the target API.

With new versions of Postman, their focus shifted a bit, and now it’s advertised as “an API platform for building and using APIs”. For the sake of this Guide, we focus on the API client functionality.

Auvik - Monitor Everything on your Network

What is Postman used for?

With Postman, you can generate and test API calls against your favorite API. Compared to writing code, Postman provides much faster iteration & development cycles.

I use it in the prototyping & early development phase to better understand the API I’m working with. It further helps me to test the different API endpoints and options that are available.

What is the REST API in Cisco ACI?

Cisco ACI is built with an API first approach, everything you see and do in the GUI is an API call in the end. The GUI is just another API client itself!

Compared to more traditional Cisco products, which offer a limited API in most cases, in ACI you can do everything through API. This allows for powerful automation of all aspects in the ACI fabric.

Basics of the REST API

There are two concepts that are important to understand, Classes & Objects. The whole ACI fabric is made up of different objects and all of them are based on different classes. This is the abstraction that was used by Cisco to represent the configuration to the user.

Let’s look at an example to better understand the difference and how it matters. For example, an ACI Tenant is represented through the fvTenant class. An instance of this class would be a Tenant object, for example tn-TEST, which is a tenant called Test.

dMIT and the hierarchy of objects

The distributed management information tree (dMIT) of ACI hosts the whole configuration. As the name suggest, the configuration is built in a tree like hierarchy.

  • Objects have parents/children
  • Objects can reference other objects
  • Depending on the type, objects can be reused

Each of this object also have a unique and absolute identifier, called DN or Distinguished Name. This DN also shows the path of the object in the dMIT. If we look back at our tenant, it’s DN would be uni/tn-TEST, this tells us that a tenant is directly attached to the root (uni is the root).

How to use Postman with Cisco ACI?

First you need to grab Postman, do it through Brew brew install postman or grab it from the official page. Fire it up a first time, and you are welcomed by this screen.

First start

Initial startup of Postman

What I would recommend, is to create a Collection for everything ACI related. This helps to have the ACI API related requests together.

Create a new collection in Postman for ACI

You can name the collection in any way that make sense to you, I went for the simple “ACI”.

Add a first request to our new Postman collection

After we have created our collection, it’s time to create the first Postman request. First thing we need is to login to the APIC, which grants us a Cookie for the further calls we plan to do.

Login

Alright, so I created a new request, and we need to add some stuff to make the login to ACI API work.

Login request in Postman

I named the request itself “Login”, but you are again free to use whatever suits you.

The request type hast to be POST and the URL is https://<IP_OR_HOSTNAME>/api/aaaLogin.json.

For the body you go first for raw and then change the Text dropdown to JSON. Then you use the following JSON and change the user & password according to your settings.

1
2
3
4
5
6
7
8
{
  "aaaUser" : {
    "attributes" : {
      "name" : "admin",
      "pwd" : "password"
    }
  }
}

With these parameters and configuration in place, you can trigger the first Postman call to the API. This can result in an SSL error, if your APIC just have a self-signed certificated.

If this is the case you can make sure that the SSL cert is valid or Disable SSL Verfication to make sure that the call go through.

Postman is pretty smart and directly handles cookies for us, so we don’t need to save any information from the response. The further calls will directly include the cookie we got returned and are therefore permitted on the ACI API.

First Call

To a class

With the cookie in place from the login call, we can now start with our real requests to the API.

Create another Request in the Postman GUI

The calls to the API of ACI have two main categories

  • Calls to a specific object through a DN
  • Calls to a class through the class identifier

We start with a call to a class and check what we get as a return. For now, we got with the tenant class, which is fvTenant.

Return of the fvTenant call

The URL format for class based requests is always in the pattern of <base-url>/class/<class-name>.<json/xml>?<optional-parameters>. For our Tenant example this means https://<IP_OR_HOSTNAME>/api/class/fvTenant.json.

The return has always the same structure, you get a Dictionary with 2 keys

  • totalCount
  • imdata

totalCount informs you how many items matched your request, so in my case we have 7 Tenants total. This information can be especially useful if you work with filters and pagination.

imdata is the data itself, so we get one dict inside the imdata list for each object returned.

To a DN

Now we can do the same thing for a DN, the URL format is a little different. <base-url>/mo/<dn-path>.<json/xml>?<optional-parameters>. I did the call for the infra Tenant, so my URL looked like this https://<IP_OR_HOSTNAME>/api/mo/uni/tn-infra.json. This returns now just a single object, but the object itself looks the same so far.

API call to a DN

It’s important to always use the full DN as it appears in the object.

Optional Parameters

Often you want maybe a bit more information in the responses you get from the API. Or you want to filter the request to just return object that matches a specific pattern. We won’t cover all the possible options in this blog post, but I want to show you some of the most important parameters for the Cisco ACI API.

  • rsp-prop-include=config-only

    • With this option set, the response only include properties that are configurable. Really useful if you want to fetch an object, change part of the configuration and repost it.
  • rsp-subtree=children

    • Return not only the requested DN/Class but also all the children of the returned object.
  • rsp-subtree=full

    • Return not only the requested DN/Class but also all the children, grandchildren and so on. The whole subtree beneath the requested DN/Class.

These two are the ones that I use by far the most, some more advanced stuff like filtering will be covered in another Blog post.

If we now rerun on of the earlier calls, we get a different result. Let’s use the DN example and add the rsp-subtree option. https://<IP_OR_HOSTNAME>/api/mo/uni/tn-infra.json?rsp-subtree=children

Now you will see all sorts of children in the return, for example the Bridge Domains (fvBD), EPGs (fvAEPg) and a lot more.

Post Call

Alright, so far we did some basic fetching of objects through the Cisco ACI API, now we start with the really fun stuff, object creation!

There is one additional important concept here, you have to specify the path to which you want to POST your object. You could use different paths in your requests and then go for relative paths in the object description, but I would advise against it.

My recommendation is to always post against api/mo.json and specify the full path in the object data

To make a bit more clear what I mean by that, let’s create some objects through the API.

Create an object

We create another request in our Postman application and then change the type to POST, for the URL we use https://<IP_OR_HOSTNAME>/api/mo.json. As we want to create an object, we need to provide a Body with the JSON data (I don’t cover XML… ;-)) of our new object.

POST call to create a Tenant

In the data you have only to specify the fields that you want to configure, in our case we could leave descr away, and it would work fine as well.

But you always need to specify the full DN

1
2
3
4
5
6
7
8
{
    "fvTenant": {
        "attributes": {
            "descr": "TEST Tenant by API",
            "dn": "uni/tn-TEST"
        }
    }
}

Another important point here is, that you are not allowed to post any of the properties that are not configurable. This is the reason why the rsp-prop-include=config-only parameter can be really helpful to only get the properties that are configurable.

If you now check the GUI, you will see your Postman created Tenant there!

Your first Postman created object

Delete an object

Now we want to clean-up our new Tenant again, this can also be done through the API. There are two approaches here:

  • Use a DELETE call to the DN
  • Specify the "status": "deleted" attribute in your POST call

DELETE Method

The first way is straight forward, you use the same pattern as we used in our get call to a dn but instead of method GET we used DELETE. We then don’t need a body, as the DELETE method combined with the DN in the URL is enough for ACI to understand our intent.

Delete call for our Tenant TEST

Be careful with these calls, if you by accident leave part of the DN, you maybe delete a Parent which wasn’t intended

"status": "deleted" attribute

Here we work again with the same approach as in the create an object chapter. So we use again the POST method and a JSON body, which only needs to include the DN and the "status": "deleted" attribute.

1
2
3
4
5
6
7
8
{
    "fvTenant": {
        "attributes": {
            "dn": "uni/tn-TEST",
            "status": "deleted"
        }
    }
}

Delete an object through attribute

The outcome is the same for both ways, personally I tend more to the "status": "deleted" variation, but I guess this is personal preference.

Examples of Postman with Cisco ACI

So far we covered the most important methods and ways to get data from the Cisco ACI API with Postman. But all the calls could also be done through CURL, a Python script or any other tools out there :)

In this last chapter I want to provide you with some calls that are helpful and hopefully make starting out easier for you.

Create an EPG with Static Bindings

Let’s say you have to deploy a new EPG that is mapped to all the server ports. This task can be easily done through the API and the call is reusable for additional EPG’s in the future.

We stay with the URL in the format https://<IP_OR_HOSTNAME>/api/mo.json and then have a bit a bigger body for this call. The assumption here is that the Tenant already exists and has the required VRF & BD configuration in place.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
    "fvAEPg": {
        "attributes": {
            "dn": "uni/tn-TEST/ap-NM/epg-EPG-1"
        },
        "children": [
            {
                "fvRsPathAtt": {
                    "attributes": {
                        "encap": "vlan-101",
                        "tDn": "topology/pod-1/paths-101/pathep-[eth1/1]"
                    }
                }
            },
            {
                "fvRsPathAtt": {
                    "attributes": {
                        "encap": "vlan-101",
                        "tDn": "topology/pod-1/paths-102/pathep-[eth1/1]"
                    }
                }
            },
            {
                "fvRsDomAtt": {
                    "attributes": {
                        "tDn": "uni/phys-phys"
                    }
                }
            },
            {
                "fvRsBd": {
                    "attributes": {
                        "tnFvBDName": "BD"
                    }
                }
            }
        ]
    }
}

The EPG object can be extended according to your requirements, but I think it should give a good idea how to structure the overall call.

Of course, you can also add more fvRsPathAtt objects (Static Bindings) or some different children (e.g. Contracts).

Create an BD + EPG pair

This can be seen as an alternative/extension of the Create an EPG with Static Bindings approach. We create not only an EPG, but also a BD. This makes sense for setups that use a 1:1 mapping between EPG and BD.

URL will stay again the same https://<IP_OR_HOSTNAME>/api/mo.json, data in this case would be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
    "fvTenant": {
        "attributes": {
            "dn": "uni/tn-TEST"
        },
        "children": [
            {
                "fvBD": {
                    "attributes": {
                        "name": "BD-1"
                    }
                }
            },
            {
                "fvAp": {
                    "attributes": {
                        "name": "NM"
                    },
                    "children": [
                        {
                            "fvAEPg": {
                                "attributes": {
                                    "name": "EPG-1"
                                },
                                "children": [
                                    {
                                        "fvRsBd": {
                                            "attributes": {
                                                "tnFvBDName": "BD-1"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Here one difference is that the EPG now only contains a name and no longer a DN, as the DN is relative to the Tenant itself.

Create a new VPC policy

If most of your VPC policies look the same, then this is a great opportunity to use automation to create all the different VPC policies that you need.

This simple example shows how you could use a template to create VPC policies that look all the same, here just with CDP & LLDP configured. So you can easily extend it as needed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
    "infraAccBndlGrp": {
        "attributes": {
            "dn": "uni/infra/funcprof/accbundle-VPC-L101-E-1-01"
        },
        "children": [
            {
                "infraRsCdpIfPol": {
                    "attributes": {
                        "tnCdpIfPolName": "CDP-ON"
                    }
                }
            },
            {
                "infraRsLldpIfPol": {
                    "attributes": {
                        "tnLldpIfPolName": "LLDP-RxON-TxON"
                    }
                }
            },
        ]
    }
}

Get the Audit messages for a specific date

Sometimes you want to check only part of the Audit log history, maybe you know a date range for which you would like to get some details. This can be done with some additional filtering, which we didn’t cover so far.

A simple GET request to the URL will do the job: https://<IP_OR_HOSTNAME>/api/node/class/aaaModLR.json?query-target-filter=bw(aaaModLR.created, "2022-10-19", "2022-10-20")

Replace the dates with ones that fit your request, and you get a filtered ACI Audit Log in return.

Get the Event messages for a specific date

The same we did with the audit log, can be done for the Event log. But depending on the fabric, this can still be a lot of output.

https://<IP_OR_HOSTNAME>/api/node/class/eventRecord.json?query-target-filter=bw(eventRecord.created, "2022-10-19", "2022-10-20")

It’s also possible to use Hours in the filter, this would look like this: https://<IP_OR_HOSTNAME>/api/node/class/eventRecord.json?query-target-filter=bw(eventRecord.created, "2022-10-20T07:00:00", "2022-10-20T08:00:00")

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy