cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
2339
Views
1
Helpful
9
Replies

API Help with Bash Script

Ben_Holmes
Level 1
Level 1

Howdy All,

First let me admit my ignorance with APIs, and assume that I know nothing.

#!/bin/bash -u

FORM=“Content-Type: application/x-www-form-urlencoded”
NOW=$(date -R)

#get these from the Duo Admin interface
INT=“obfuscated integration key from admin page”
KEY=“obfuscated secret key from admin page”
API=“■■■■■■■■■■■■■■■■■■■■■■■

URL="/auth/v2/check"
#URL="/admin/v1/users"
REQ="$NOW\nGET\n$API\n$URL\n"

#could also use awk here, or the --binary mode as suggested elsewhere
HMAC=$(echo -n “$REQ” | openssl sha1 -hmac “$KEY” | cut -d" " -f 2)

AUTH=$(echo -n “$INT:$HMAC” | base64 -w0)

curl -s -H “Date: $NOW” -H $FORM -H “Authorization: Basic $AUTH” https://$API$URL

gives me this error:
{“code”: 40301, “message”: “Access forbidden”, “message_detail”: “Wrong integration type for this API.”, “stat”: “FAIL”}

If i change it to the “admin” url i get this error
{“code”: 40103, “message”: “Invalid signature in request credentials”, “stat”: “FAIL”}

Basically i want to pull a user l list via the API, but i can’t even get past the authentication piece.

Any help here is much appreciated.

9 Replies 9

jonblac
Cisco Employee
Cisco Employee

Hello,

I cannot vouch for the code, but you have to use the integration keys for Auth API application in the Duo console when using the auth/vs/check. it sound like you might have just the admin API defined.

Adding our Rep Taylor so she can see.

I have both the Admin and the Auth API keys.

Just need some help on making the HMAC SH1 string and then basic authentication.

i.e. It would be nice to this broken into more steps

https://duo.com/docs/authapi#api-details

HenryEgal
Level 1
Level 1

Have you found the answer to this? I am getting the same thing and have followed the documentation.

Maybe try not concatenating the request with that newline character?

Like instead of:

REQ="$NOW\nGET\n$API\n$URL\n"

Try:

REQ="$NOW
GET
$API
$URL
"

When I try what you have posted here I get actual \n in the request (I am on a Mac though right now).

ETA: I saw a StackOverflow post tagged with Linux and bash where someone noted that \n was inserting whitespace, which would also throw off the signature.

Duo, not DUO.

It did not work for me.ANyone had any shell script that worked for the Duo Admin API

I haven’t got it working with Bash either. But I did have someone get it working in Python, but I can’t use that.

The support shown for this kind of stuff here is…

They provide some simple PoC code based on unit tests and from there on, you’re on your own. No functional-ready-to-copy-paste code that you can use.

I managed to build a wrapper shell script against the nodejs module they provide, so I have, so far (I’m just adding commands as we need them):

Anyway it should be easy (I think) too for python wrapping a shell script against this basic command structure:

python -m duo_client.client --ikey nnn --skey nnn --host nnn --path /admin/blah/blah limit=200 --method GET/POST/DELETE

(I don’t know how you specify the parameters there sorry, maybe just in the way the “limit” is specified above).

Regards.

I know this is a fairly old thread, but it was the hint I needed to figure out how to use bash to successfully make requests via curl so here goes.

Personal note: I didn’t have much luck with the var=$(command) notation for executing and capturing output to variables. So I used var=`command` notation instead. May be my system or that I am just dense and missing something so take that with a grain of sand.

So here is what I had to change to get this working from a bash script
1> You are not including a blank line in your request where parameters would go if you had any.
2> I used the ${var} notation to make sure that bash didn’t have any ambiguity issues when building strings from variables
3> Lastly you didn’t need to base64 encode the auth string, using --basic with -u ikey:hmac curl will take care of the encoding

So here is my example bash code to talk to the admin api

#!/usr/bin/bash
type='Content-Type: application/x-www-form-urlencoded'
now=`/usr/bin/date -R`
method="GET"
ikey='####################'
skey='########################################'
host='■■■■■■■■■■■■■■■■■■■■■■■■■■■■'
path='/admin/v1/users'
params=''
req="${now}
${method}
${host}
${path}
${params}"
hmac=`/usr/bin/echo -n "${req}" | /usr/bin/openssl sha1 -hmac ${skey} | /usr/bin/cut -d" " -f 2`

/usr/bin/curl -s -H "Date: ${now}" -H "${type}" -u "${ikey}:${hmac}" --basic https://${host}${path}

Just in case anyone is looking for examples of using the api to post updates. Here is the snippet I added to the system setup script I use for building new VMs. It does assume that there is a pam_duo.conf.skel file in the same location as the setup script.

## ------------------- DUO MFA ------------------- ##
## use duo api to generate host specific 'app' for use in setting up pam_duo
## gather timestamp and host for header and request body
myhost=`hostname -s`
duonow=`/usr/bin/date -R`
## set content type header and http method
duoctype="Content-Type: application/x-www-form-urlencoded"
duomethod="POST"

## set vars for message signing, authentication, host, and path  obtained from duo
## should really be pulled from a secure repository of some sort
duoikey="####################"
duoskey="########################################"
duohost="■■■■■■■■■■■■■■■■■■■■■■■■■■■■"
duopath="/admin/v1/integrations"

## build params string
duoparams="groups_allowed=####################&name=${myhost}&type=unix&username_normalization_policy=Simple"

## build request for generating hmac sig
duoreq="${duonow}
${duomethod}
${duohost}
${duopath}
${duoparams}"

## generate sig for auth
duohmac=`/usr/bin/echo -n "${duoreq}" | /usr/bin/openssl sha1 -hmac ${duoskey} | /usr/bin/cut -d" " -f 2`

## make call and capture json response
duoresponse=`/usr/bin/curl -s -H "Date: ${duonow}" -H "${duoctype}" -u "${duoikey}:${duohmac}" -X POST --basic https://${duohost}${duopath}?${duoparams}`

## capture new ikey and skey
ikey=`/usr/bin/echo ${duoresponse} | /usr/bin/jq -j '.response.integration_key'`
skey=`/usr/bin/echo ${duoresponse} | /usr/bin/jq -j '.response.secret_key'`

## set up /etc/duo/pam_duo.conf
/usr/bin/cp ./pam_duo.conf.skel /etc/duo/pam_duo.conf
/usr/bin/sed -i "s/.*ikey.*/ikey = ${ikey}/" /etc/duo/pam_duo.conf
/usr/bin/sed -i "s/.*skey.*/skey = ${skey}/" /etc/duo/pam_duo.conf
/usr/bin/sed -i "s/.*host.*/host = ${duohost}/" /etc/duo/pam_duo.conf
/usr/bin/echo -e '/etc/duo/pam_duo.conf configured'
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