This article starts a series covering the depths of Cisco SD-WAN. This time, however, we will just scratch the surface with some basic requests.
For that, we will use the Postman software and Cisco SD-WAN 20.4 Always On sandbox
Authentication
Let’s start with the configuration of the Postman. We need to disable SSL certificate verification. This option is available in the general tab in settings.
Now, we’re ready to interact with the vManage. Let’s authenticate first.
To accomplish this, we need to send the POST request with credentials. The credentials need to be placed in the body of the request. Keys with values are listed below.
j_username: devnetuser
j_password: RG!_Yw919_83
The request URL is https://sandbox-sdwan-2.cisco.com/j_security_check
Let’s execute that!
And here we’ve got the response. The status is 200 OK, so we can assume that everything went as expected.
We’ve received the cookie, that will be used in the following requests. Postman takes care of that for us, so we don’t have to think about it.
Now, we’re ready to do something more spectacular, let’s get the complete list of devices attached to the vManage!
Devices
For this request, the URL is https://sandbox-sdwan-2.cisco.com/dataservice/device
This time, however, we’re sending the GET requests, since we want to gather something from the vManage.
The response is once again 200 OK. In the body, we can see, that we’ve received the JSON formatted information. Let’s take a closer look at what we’ve got there.
{
"header": {
[...]
},
"data": [
{
"deviceId": "10.10.1.1",
"system-ip": "10.10.1.1",
"host-name": "vmanage",
"reachability": "reachable",
"status": "normal",
"personality": "vmanage",
"device-type": "vmanage",
"timezone": "UTC",
"device-groups": [
"\"No groups\""
],
"lastupdated": 1650316204058,
"domain-id": "0",
"board-serial": "969E8292C5E64183A2563B7A3605B67D",
"certificate-validity": "Valid",
"max-controllers": "0",
"uuid": "81ac6722-a226-4411-9d5d-45c0ca7d567b",
"controlConnections": "0",
"device-model": "vmanage",
"version": "20.4.2.1",
"connectedVManages": [
"\"10.10.1.1\""
],
"site-id": "101",
"latitude": "37.666684",
"longitude": "-122.777023",
"isDeviceGeoData": false,
"platform": "x86_64",
"uptime-date": 1649774760000,
"statusOrder": 4,
"device-os": "next",
"validity": "valid",
"state": "green",
"state_description": "All daemons up",
"model_sku": "None",
"local-system-ip": "10.10.1.1",
"total_cpu_count": "2",
"testbed_mode": false,
"layoutLevel": 1
},
{
"deviceId": "10.10.1.5",
"system-ip": "10.10.1.5",
"host-name": "vsmart",
"reachability": "unreachable",
"status": "normal",
"personality": "vsmart",
"device-type": "vsmart",
"timezone": "UTC",
"device-groups": [
"\"No groups\""
],
"lastupdated": 1650293706219,
"domain-id": "1",
"board-serial": "4E500CAE354B4341B322C5DA4BD7588A",
"certificate-validity": "Valid",
"uuid": "f7b49da3-383e-4cd5-abc1-c8e97d345a9f",
"controlConnections": "--",
"device-model": "vsmart",
"version": "20.4.2",
"connectedVManages": [],
"site-id": "101",
"ompPeers": "--",
"latitude": "37.666684",
"longitude": "-122.777023",
"isDeviceGeoData": false,
"platform": "x86_64",
"uptime-date": 1641831600000,
"statusOrder": 4,
"device-os": "next",
"validity": "valid",
"state": "green",
"state_description": "All daemons up",
"model_sku": "None",
"local-system-ip": "10.10.1.5",
"total_cpu_count": "2",
"testbed_mode": false,
"layoutLevel": 2
},
{
"deviceId": "10.10.1.3",
"system-ip": "10.10.1.3",
"host-name": "vbond",
"reachability": "unreachable",
"status": "normal",
"personality": "vbond",
"device-type": "vbond",
"timezone": "UTC",
"device-groups": [
"\"No groups\""
],
"lastupdated": 1650302709355,
"board-serial": "7AC124B4AED648EB99B9900DD56A405C",
"certificate-validity": "Valid",
"uuid": "ed0863cb-83e7-496c-b118-068e2371b13c",
"controlConnections": "--",
"device-model": "vedge-cloud",
"version": "20.4.2",
"connectedVManages": [],
"site-id": "101",
"ompPeers": "--",
"latitude": "37.666684",
"longitude": "-122.777023",
"isDeviceGeoData": false,
"platform": "x86_64",
"uptime-date": 1641831840000,
"statusOrder": 4,
"device-os": "next",
"validity": "valid",
"state": "green",
"state_description": "All daemons up",
"model_sku": "None",
"local-system-ip": "10.10.1.3",
"total_cpu_count": "4",
"linux_cpu_count": "1",
"testbed_mode": false,
"layoutLevel": 3
},
[...]
I’ve cut the content of the header. Let’s look at the data section.
It’s a list of devices. Each list element is a dictionary representing a particular device. As you can see, there is a lot of information there. It’s worth highlighting the deviceId parameter, which is used by many more specific requests.
We’ve got the device list, now let’s assume that we want to get the config of a particular device, let’s pick a site2-cedge01.
Config
If we want to get the config of a particular device, we need to somehow inform a vManage in the request which device we’re interested in. Let’s take a look at the documentation.
In this request, we need to attach the device id in the parameters section. The base URL is https://sandbox-sdwan-2.cisco.com/dataservice/device/config
After execution, we’ve received the response with device configuration. It’s worth highlighting, that the response is not formatted in JSON format, unlike the previous example.
system
host-name site2-cedge01
gps-location latitude 37.411343
gps-location longitude -121.938803
system-ip 10.10.1.15
overlay-id 1
site-id 1002
port-offset 0
control-session-pps 300
admin-tech-on-failure
organization-name "DevNet Sandbox"
port-hop
track-transport
track-default-gateway
console-baud-rate 115200
vbond 10.10.20.80 port 12346
!
memory free low-watermark processor 72347
platform console serial
platform punt-keepalive disable-kernel-core
hostname site2-cedge01
username cisco privilege 15 secret 9 $9$X8t5V6eWdPoRd.$wOxXAiJ8i7jeYcH70M82cMnxDgwX.31ymh9Y18oj3eg
username developer privilege 15 secret 9 $14$/kLd$y1w2VoYGXjHbZk$VWLbkzLGIAmPESawg2hrJfBAGu9J0.5M2WqKWfCZkXU
vrf definition 1
rd 1:1
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
vrf definition Mgmt-intf
rd 1:512
address-family ipv4
exit-address-family
!
address-family ipv6
exit-address-family
!
!
no ip dhcp use class
ip route 0.0.0.0 0.0.0.0 10.10.23.13
ip route vrf Mgmt-intf 0.0.0.0 0.0.0.0 10.10.20.254
no ip source-route
ip ssh version 2
ip access-list extended meraki-fqdn-dns
!
[...]
But what happens if we forget to specify the device id? Let’s check that!
The first noticeable change is a response code, instead of 200, we’ve received the 400 Bad Request – which informs us right away, that something is wrong. In the body, we have more details.
For the last call, let’s get the list of interfaces of a site3-vedge01.
Interfaces
Since we’re interested in the specific device, we need to attach the device id here as well. The base URL is https://sandbox-sdwan-2.cisco.com/dataservice/device/interface
And we have another problem here. Let’s suppose that we’ve entered the correct device id. What could go wrong then? Let’s check the devices directly on the vManage.
The problem is clear now. Some of the attached devices are unavailable. Probably there was a problem with the SD-WAN Sandbox.
….A couple of centuries later…
All devices were brought back to life.
Let’s execute the request once again.
Now we have what we wanted. Let’s check the response.
{
"header": {
[...]
},
"data": [
{
"vdevice-name": "10.10.1.11",
"rx-errors": 0,
"tx-kbps": 0,
"if-admin-status": "if-state-up",
"ipv6-tcp-adjust-mss": "0",
"tx-pps": 0,
"tx-errors": 0,
"ifname": "Control Plane",
"interface-type": "iana-iftype-other",
"rx-pps": 0,
"if-oper-status": "if-oper-state-ready",
"ifindex": "0",
"num-flaps": "0",
"ipv4-tcp-adjust-mss": "0",
"rx-packets": 0,
"bia-address": "00:00:00:00:00:00",
"vpn-id": "0",
"vdevice-host-name": "dc-cedge01",
"mtu": "0",
"rx-drops": 0,
"tx-drops": 0,
"hwaddr": "00:00:00:00:00:00",
"speed-mbps": 10240,
"vdevice-dataKey": "10.10.1.11-0-Control Plane--00:00:00:00:00:00",
"tx-octets": 0,
"tx-packets": 0,
"rx-kbps": 0,
"rx-octets": 0,
"lastupdated": 1652367262391
},
{
"vdevice-name": "10.10.1.11",
"rx-errors": 0,
"tx-kbps": 0,
"if-admin-status": "if-state-up",
"ipv6-tcp-adjust-mss": "0",
"description": "port.sbx-mgmt",
"tx-pps": 0,
"tx-errors": 0,
"ifname": "GigabitEthernet1",
"interface-type": "iana-iftype-ethernet-csmacd",
"rx-pps": 1,
"if-oper-status": "if-oper-state-ready",
"ifindex": "1",
"num-flaps": "0",
"ipv4-tcp-adjust-mss": "0",
"rx-packets": 30680164,
"bia-address": "52:54:00:10:b1:46",
"vpn-id": "512",
"vdevice-host-name": "dc-cedge01",
"ipv4-subnet-mask": "255.255.255.0",
"mtu": "1500",
"rx-drops": 0,
"tx-drops": 0,
"hwaddr": "52:54:00:10:b1:46",
"ip-address": "10.10.20.172",
"speed-mbps": 1024,
"vdevice-dataKey": "10.10.1.11-512-GigabitEthernet1-10.10.20.172-52:54:00:10:b1:46",
"tx-octets": 75260450,
"tx-packets": 1045069,
"rx-kbps": 4,
"rx-octets": 7162907864,
"lastupdated": 1652367262391
},
{
"vdevice-name": "10.10.1.11",
"rx-errors": 0,
"tx-kbps": 18,
"if-admin-status": "if-state-up",
"ipv6-tcp-adjust-mss": "0",
"description": "GigabitEthernet2.wan-rtr01",
"tx-pps": 11,
"tx-errors": 0,
"ifname": "GigabitEthernet2",
"interface-type": "iana-iftype-ethernet-csmacd",
"rx-pps": 14,
"if-oper-status": "if-oper-state-ready",
"ifindex": "2",
"num-flaps": "0",
"ipv4-tcp-adjust-mss": "0",
"rx-packets": 128593080,
"bia-address": "52:54:00:1e:6d:d9",
"vpn-id": "0",
"vdevice-host-name": "dc-cedge01",
"ipv4-subnet-mask": "255.255.255.252",
"mtu": "1500",
"rx-drops": 0,
"tx-drops": 0,
"hwaddr": "52:54:00:1e:6d:d9",
"ip-address": "10.10.23.6",
"speed-mbps": 1024,
"vdevice-dataKey": "10.10.1.11-0-GigabitEthernet2-10.10.23.6-52:54:00:1e:6d:d9",
"tx-octets": 360525902,
"tx-packets": 116988338,
"rx-kbps": 19,
"rx-octets": 22559673069,
"lastupdated": 1652367262391
},
[...]
The JSON response structure is similar to the one with a list of devices. We have here a list of dictionaries, each representing a particular interface.
Great post!
I’m preparing Cisco Devnet Associate and your post was very helpful.
Only quick question. I like to use variables to get a dynamic code and I found an issue once try to use the variable deviceId in postman.
1/ https://sandbox-sdwan-2.cisco.com/dataservice/device/{{deviceId}}/interface
–deviceId variable is created in environment section but I’m getting this error:
Error
SessionTokenFilter: Token provided via HTTP Header does not match the token generated by the server.
Hello Alfredo!
Try those steps:
1. Send the first POST to https://sandbox-sdwan-2.cisco.com/j_security_check as written in the article
2. Send GET to https://sandbox-sdwan-2.cisco.com/dataservice/client/token with a body containing credentials as in step 1.
3. Copy the received token from the previous GET message
4. In the GET devices call add a new header in the postman with the key “X-XSRF-TOKEN” and the value of copied token from step 4.
I hope it will work for you!