0

I am attempting to utilize Duo MFA's - Admin API. It requires Date and Authorization headers to have a signed canonical string which I am having trouble with.

My current code:

import base64, email, hmac, hashlib, urllib, requests

url = "admin api link"
ikey = "secret"
skey = "secret"

def sign(method, host, path, params, skey, ikey):
    """
    Return HTTP Basic Authentication ("Authorization" and "Date") headers.
    method, host, path: strings from request
    params: dict of request parameters
    skey: secret key
    ikey: integration key
    """

    # create canonical string
    now = email.Utils.formatdate()
    canon = [now, method.upper(), host.lower(), path]
    args = []
    for key in sorted(params.keys()):
        val = params[key]
        if isinstance(val, unicode):
            val = val.encode("utf-8")
        args.append(
            '%s=%s' % (urllib.quote(key, '~'), urllib.quote(val, '~')))
    canon.append('&'.join(args))
    canon = '\n'.join(canon)

    # sign canonical string
    sig = hmac.new(skey, canon, hashlib.sha1)
    auth = '%s:%s' % (ikey, sig.hexdigest())

    # return headers
    return {'Date': now, 'Authorization': 'Basic %s' % base64.b64encode(auth)}


headers = {
    'Date': ?,
    'Authorization': ?,
    }

response = requests.request("GET", url, headers=headers)
print(response.text)

How can I set the headers to use the sign functions return Date and Authorization?

I have tried sign(Date) and sign(Authorization) with no luck. I believe I am missing some fundamental/rudimentary python logic on using the returns from functions.

mcspadden
  • 95
  • 3
  • 9

1 Answers1

0

You should reference the sign definition (after where it's declared) and then you can add the host to the headers dictionary after the sign function returns the Date and hmac-sha1 signature.

Link to explanation on adding a new key,value pair to a dictionary that was previously declared: How can I add new keys to a dictionary?

The sign definition returns a dictionary.

Referencing a definition: https://docs.python.org/3/reference/compound_stmts.html#function-definitions

In order for the request to succeed all of the parameters in the sign definition must be referenced due to the duo admin api authentication section (https://duo.com/docs/adminapi#authentication) stating that it's important to add the following sections to the required hmac signature:

  • date (in RFC 2822 format)
  • http request method
  • host
  • path
  • params
APIHostname = "api-xxxxxxxx.duosecurity.com"
...
auth = sign('GET', APIHostname, path_to_resource, params, skey, ikey)
headers = auth
headers['Host'] = APIHostname
Ola B.
  • 1
  • 1