DNAC API, curl and jq

I'm reviewing the DEVASC exam topics. Here I share some quick notes about curl, jq and Cisco DNA API.

Base64 and newline

Let's start with authentication. DNAC uses basic authentication. Credentials are encoded with base64.

The process is simple. We encode the credentials with base64 and use the encoded string to get a token. The token will be used to query the API.

The credentials must be encoded in this format:

1username:password

Most Linux distributions include a base64 encoder/decoder:

1echo "devnetuser:Cisco123!" | base64
2  
3ZGV2bmV0dXNlcjpDaXNjbzEyMyEK

It looks fine right? We get the same original string piping the encoded output to decode it:

1echo "devnetuser:Cisco123!" | base64 | base64 --decode
2devnetuser:Cisco123!

Let's try to get the token now:

1  curl -s -X POST \
2  https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token \
3  -H "Authorization: Basic ZGV2bmV0dXNlcjpDaXNjbzEyMyEK"
4
5  {"error":"Authentication has failed. Please provide valid credentials."}
Warning

Authentication has failed.

The problem is we used echo to encode the credentials but echo silently adds a newline at the end of the string.

Let's check the echo man page and try again using the -n flag that prevents echo from adding the newline:

1echo -n "devnetuser:Cisco123!" | base64
2  
3ZGV2bmV0dXNlcjpDaXNjbzEyMyE=

Notice the encoded string is different now. If we try the encode/decode pipe again the newline will not be printed:

1echo -n "devnetuser:Cisco123!" | base64 | base64 --decode
2devnetuser:Cisco123!

Now we can try again to get the token, now using the correct credentials:

1curl -s -X POST \
2https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token \
3-H "Authorization: Basic ZGV2bmV0dXNlcjpDaXNjbzEyMyE="
Info

Success! Now we got the token.

A final note for this section: we can use variables to avoid the long curl strings. This is the command to assign to a variable named auth the value of the encoded credentials:

1auth=$(echo -n "devnetuser:Cisco123!" | base64)

Here's the same curl with the variable:

1curl -s -X POST \
2https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token \
3-H "Authorization: Basic $auth"

We can do the same for the url:

1tokenurl="https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token"
2
3curl -s -X POST \
4$tokenurl \
5-H "Authorization: Basic $auth"

Introducing jq

Curl output is not always easy to read when working with API. Piping to jq can improve the experience.

1curl -s -X POST \
2https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token \
3-H "Authorization: Basic $auth" \
4| jq
5
6{
7  "Token": "eyJ0eXAiOiJKV1jZDQ3ZTAwNGM2N2RkMGUiLCJhdXRoU291c"
8}

We can use jq to extract the token from the output of curl and assign it to a variable:

1token=$(curl -s -X POST https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token -H "Authorization: Basic $auth" | jq -r ".Token")

Let's see the token

1echo $token

Get network devices

Cisco DNAC API can be used to get the list of the network devices:

1curl -s -X GET \
2https://sandboxdnac.cisco.com/dna/intent/api/v1/network-device \
3-H "X-Auth-Token: $token" | jq

The output is long and maybe we're not interested in all of it, jq can help to filer only some values:

 1curl -s -X GET https://sandboxdnac.cisco.com/dna/intent/api/v1/network-device \
 2-H "X-Auth-Token: $token" \
 3| jq ".response | .[] | {hostname:.hostname, platform:.platformId, serial:.serialNumber, ip:.managementIpAddress}"
 4
 5{
 6  "hostname": "cat_9k_1",
 7  "platform": "C9300-24UX",
 8  "serial": "FCW2136L0AK",
 9  "ip": "10.10.22.66"
10}
11{
12  "hostname": "cat_9k_2",
13  "platform": "C9300-24UX",
14  "serial": "FCW2140L039",
15  "ip": "10.10.22.70"
16}

Wrap up

That's all folks! Hope you enjoyed the post and will use is to start learning more about API.

Links