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:

username:password

Most Linux distributions include a base64 encoder/decoder:

echo "devnetuser:Cisco123!" | base64
  
ZGV2bmV0dXNlcjpDaXNjbzEyMyEK

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

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

Let’s try to get the token now:

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

  {"error":"Authentication has failed. Please provide valid credentials."}

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:

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

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

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

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

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

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:

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

Here’s the same curl with the variable:

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

We can do the same for the url:

tokenurl="https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token"

curl -s -X POST \
$tokenurl \
-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.

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

{
  "Token": "eyJ0eXAiOiJKV1jZDQ3ZTAwNGM2N2RkMGUiLCJhdXRoU291c"
}

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

token=$(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

echo $token

Get network devices

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

curl -s -X GET \
https://sandboxdnac.cisco.com/dna/intent/api/v1/network-device \
-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:

curl -s -X GET https://sandboxdnac.cisco.com/dna/intent/api/v1/network-device \
-H "X-Auth-Token: $token" \
| jq ".response | .[] | {hostname:.hostname, platform:.platformId, serial:.serialNumber, ip:.managementIpAddress}"

{
  "hostname": "cat_9k_1",
  "platform": "C9300-24UX",
  "serial": "FCW2136L0AK",
  "ip": "10.10.22.66"
}
{
  "hostname": "cat_9k_2",
  "platform": "C9300-24UX",
  "serial": "FCW2140L039",
  "ip": "10.10.22.70"
}

Wrap up

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

Links