cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1996
Views
2
Helpful
1
Comments
yawming
Cisco Employee
Cisco Employee

The purpose of this document is to provide a smooth and quick, easy start for newcomers to SD-WAN vManage API.

If you are not familiar with REST APIs, you can learn about them in the "Coding & APIs - Fundamentals" section.

To proceed, we kindly request that you have some knowledge of Python, as we will be programming with Python.

Two resource we must have in order to work on vManage API:

  • Cisco SD-WAN vManage API Docs
  • Cisco SD-WAN vManage server.

You can access Cisco SD-WAN vManage API Docs from here.

Regarding the Cisco SD-WAN vManage server, we will be using DevNet SD-WAN always on sandbox for the API call in this documentation. However, you can utilize any vManage server which you have access.

Authentication is necessary for most APIs, as it verifies the identity of the user or application initiating the API request. Various authentication methods are available, and once we understand the authentication process for the specific API we are working with, we will be ready to proceed.

Let’s break the API call process into 2 simple steps:

  1. Authentication
  2. Make API request

As you can see from the following picture, we will mainly access theses 2 places( Authentication and API Reference) in the API document to work on our API calls.

sd-wan-auth.png

1.Authentication – How to authenticate ?

The authentication section of the API document basically tells us that we need tokens in order to make an API request.

  • The first token is  in the response HTTP cookie, ‘JSESSIONID=xxxxxxx…’. This token is needed for every API calls.
  • How to obtain this token ?  By place a POST request –‘post ../j_security_check’ with {'j_username' : USERNAME, 'j_password' : PASSWORD} in the request 'data' parameter (NOT in the 'headers').

Before we compose the Python code, we need the following information: the vManage server's DNS or IP address, as well as the username and password.

vManage server : “sandbox-sdwan-2.cisco.com

USERNAME="devnetuser"

PASSWORD="RG!_Yw919_83" 

*Note: The login and password may change from time to time. If you encounter any issues, please check the SD-WAN always on Sandbox site for updated information.

Once we have this information we can  start the Python code to obtain the token.

import requests

# We will use Python requests module for all API request

requests.packages.urllib3.disable_warnings()

#disable InsecureRequestWarning for the Unverified HTTPS request - because we 'verify=False' in the request

USERNAME="devnetuser"

PASSWORD="RG!_Yw919_83"

login_url = 'https://sandbox-sdwan-2.cisco.com/j_security_check'

login_data = {'j_username' : USERNAME, 'j_password' : PASSWORD}

response = requests.post(url=login_url, data=login_data, verify=False)

In the document it says: If a user is successfully authenticated, the response body is empty.  You can check it from  "response.content"

print ("response body:",response.content)

And you should see the output like this if it’s empty:

response body: b''

If it is empty, then we are good to proceed with obtaining the token.

We know that the token is present in the response HTTP cookie. So, how and where we can obtain it ? There are couple of ways to do so.

Method 1.

The sample codes in this authentication section show us that we can obtain it in the response headers. Let’s take a look by printing it out :

print (response.headers)

output:

{'Server': 'nginx/1.13.12', 'Date': 'Thu, 11 May 2023 19:51:28 GMT', 'Content-Length': '0', 'Connection': 'keep-alive', 'set-cookie': 'JSESSIONID=lqzrS4LuAhNj1_438EBQi91VP4LD1d7asL73JZtH.81ac6722-a226-4411-9d5d-45c0ca7d567b; path=/; secure; HttpOnly', 'x-xss-protection': '1; mode=block', 'pragma': 'no-cache', 'x-frame-options': 'DENY', 'vary': 'Accept-Encoding', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'x-content-type-options': 'nosniff', 'Last-Modified': 'Thursday, 11-May-2023 19:51:28 UTC', 'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'}

We can see the cookie in the "Set-Cookie: JSESSIONID=..." header, so it's just a matter of parsing it.

cookies = response.headers["Set-Cookie"]

jsessionid = cookies.split(";")

# split to list

token1=jsessionid[0]

Put them together:

#executable code snippet
import requests

requests.packages.urllib3.disable_warnings()
#disable InsecureRequestWarning for the Unverified HTTPS request - because we 'verify=False' in the request

USERNAME="devnetuser"
PASSWORD="RG!_Yw919_83"


login_url = 'https://sandbox-sdwan-2.cisco.com/j_security_check'

login_data = {'j_username' : USERNAME, 'j_password' : PASSWORD}

response = requests.post(url=login_url, data=login_data, verify=False)

if response.content != b'':
    print ("Authentication fail !")
    exit()

cookies = response.headers["Set-Cookie"]
jsessionid = cookies.split(";")
# split to list
token1=jsessionid[0]
print ('token1=',token1)

*Note: With the DevNet always on Sandbox you can execute the "executable code snippet" here in real time.

Method 2

The first method is getting cookie from the response headers. Where else can we get a cookie ? In the cookie Jar ? Yes, we can get it from response CookieJar object .

print(response.cookies.get_dict())

output:

{'JSESSIONID': 'A93C6XqHNhH-dQ39C_xlPOMwDo_iuW_im0Uhx3hD.81ac6722-a226-4411-9d5d-45c0ca7d567b'}

So we can get our token in this way:

token1='JSESSIONID='+response.cookies.get_dict()['JSESSIONID']

Put them together:

#executable code snippet
import requests

requests.packages.urllib3.disable_warnings()
#disable InsecureRequestWarning for the Unverified HTTPS request - because we 'verify=False' in the request

USERNAME="devnetuser"
PASSWORD="RG!_Yw919_83"

login_url = 'https://sandbox-sdwan-2.cisco.com/j_security_check'
login_data = {'j_username' : USERNAME, 'j_password' : PASSWORD}
response = requests.post(url=login_url, data=login_data, verify=False)
if response.content != b'':
    print ("Authentication fail !")
    exit()
token1='JSESSIONID='+response.cookies.get_dict()['JSESSIONID']
print ('token1=',token1)

If you compare two outputs, you should see that they are the same. Either one will do the job, just pick the one you prefer.

Wait, you may need another token !

There is another token, a cross-site request forgery prevention token, which is required for most POST call.

How can you obtain it ? By making a request to ‘GET ../dataservice/client/token’ with the headers  “content-type’ :‘application/json’ and  'Cookie': ‘JSESSIONID=xxxxxxx’, where ‘JSESSIONID=xxxxxxx’ represents the value of the first token obtained from the response HTTP cookie.

The URL for this API request:

token_url='https://sandbox-sdwan-2.cisco.com/dataservice/client/token'

And need to place the first token in the headers

headers = {'Cookie': token1,'content-type':'application/json'}

Then you make the API call.

response = requests.get(url=token_url, headers=headers, verify=False)

The token is in the content of the response, in Unicode.

token2=response.text

print ("token2=",token2)

Output:

token2= AFD7EB2XXXXXXXXXXXXX

Put all the code together.

#executable code snippet
import requests

requests.packages.urllib3.disable_warnings()
#disable InsecureRequestWarning for the Unverified HTTPS request - because we 'verify=False' in the request

USERNAME="devnetuser"
PASSWORD="RG!_Yw919_83"

login_url = 'https://sandbox-sdwan-2.cisco.com/j_security_check'
login_data = {'j_username' : USERNAME, 'j_password' : PASSWORD}
response = requests.post(url=login_url, data=login_data, verify=False)
if response.content != b'':
    print ("Authentication fail !")
    exit()
token1='JSESSIONID='+response.cookies.get_dict()['JSESSIONID']
print ('token1=',token1)

token_url='https://sandbox-sdwan-2.cisco.com/dataservice/client/token'
headers = {'Cookie': token1,'content-type':'application/json'}
response = requests.get(url=token_url, headers=headers, verify=False)
token2=response.text
print ('token2=',token2)

*Please note that, for the sake of simplicity, all the code snippet provided here does not include any error handling.

2.Make API request

Once we have obtained the two tokens we are good to make any API request.

In order to know which APIs we can use and how to use them, we have to have the API reference. 

Let’s use this “GET /device” API as an example - Display all devices in the overlay network that are connected to the vManage instance.

It’s in the “Monitoring – Device Details” section of API Reference.

The root URL is ‘https://{vmanage-ip-address}/dataservice/. (Please refer to https://developer.cisco.com/docs/sdwan/#!summary/base-uri ) So our request URL is ‘https://{vmanage-ip-address}/dataservice/device’.

The document says: (In https://developer.cisco.com/docs/sdwan/#!authentication/how-to-authenticate “Make an API request” section)

  • For non-whitelisted endpoints, the user needs to provide an API token as a cookie: JESSIONID={session hash}.
  • For POST requests, the user also needs to provide the matching XSRF token.

sd-wan-token.png

* Please refer to the Cisco SD-WAN vManage API document page for detail, as the picture is not clear and only provides a general reference.

To simplify things, let's always include two tokens in the headers.

We will also add "import json" because we will be using  the json.dump() function from the json module to make the output look nicer and easier to read. This import statement is unrelated to the API functionality.

The following code will be added for making '/device' API request:

import json

headers = {'Content-Type': "application/json",'Cookie': token1, 'X-XSRF-TOKEN': token2}
request_url='https://sandbox-sdwan-2.cisco.com/dataservice/device'
response = requests.get(url=request_url,headers=headers,verify=False)
print (response.status_code)
print(json.dumps(response.json(),indent=4))

Please note that two tokens have been included in headers:

headers = {'Content-Type': "application/json",'Cookie': token1, 'X-XSRF-TOKEN': token2}

Let's put all of them together:

#Executable code snippet

import requests
import json

requests.packages.urllib3.disable_warnings()
#disable InsecureRequestWarning for the Unverified HTTPS request - because we 'verify=False' in the request

USERNAME="devnetuser"
PASSWORD="RG!_Yw919_83"

login_url = 'https://sandbox-sdwan-2.cisco.com/j_security_check'
login_data = {'j_username' : USERNAME, 'j_password' : PASSWORD}
response = requests.post(url=login_url, data=login_data, verify=False)
if response.content != b'':
    print ("Authentication fail!")
    exit()
token1='JSESSIONID='+response.cookies.get_dict()['JSESSIONID']
print ('token1=',token1)
token_url='https://sandbox-sdwan-2.cisco.com/dataservice/client/token'
headers = {'Cookie': token1,'content-type':'application/json'}
response = requests.get(url=token_url, headers=headers, verify=False)
token2=response.text
print ('token2=',token2)

headers = {'Content-Type': "application/json",'Cookie': token1, 'X-XSRF-TOKEN': token2}
request_url='https://sandbox-sdwan-2.cisco.com/dataservice/device'
response = requests.get(url=request_url,headers=headers,verify=False)
print ("status:",response.status_code)
print (json.dumps(response.json(),indent=4))

That's it! You have made your first Cisco SD-WAN vManage API call !

Other than accessing the Cisco SD-WAN vManage API Docs from the Cisco Developer web portal, you can also access them from the Cisco SD-WAN vManage UI. The Cisco Developer web portal hosts different versions of API reference, allowing you to find the version you are working with. If you have your own Cisco SD-WAN vManage server, you can access the API reference at https://{vmanage-ip-address}/apidocs

For example, if server you are using is sandbox-sdwan-2.cisco.com, you should be able to access the API reference at https://sandbox-sdwan-2.cisco.com/apidocs/.

If you like to learn more of SD-WAN in general, here are the useful resources :

 

Comments

Thanks a lot for sharing this useful document @yawming 

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community:

Quick Links