Skip to content

Instantly share code, notes, and snippets.

@serac
Created February 9, 2016 19:21
Show Gist options
  • Select an option

  • Save serac/52fec0e1f139c02c02d7 to your computer and use it in GitHub Desktop.

Select an option

Save serac/52fec0e1f139c02c02d7 to your computer and use it in GitHub Desktop.
Duo Python User Query Script
#!/usr/bin/env python
from os.path import basename
import sys
import base64, email, json, hashlib, hmac, httplib, urllib
if len(sys.argv) < 3:
print 'USAGE %s path/to/duo-api.properties username' % basename(sys.argv[0])
print 'Properties file should have following properties:'
print ' apiHost=api-XXXXXXXX.duosecurity.com'
print ' iKey=DIXXXXXXXXXXXXXXXXXX'
print ' sKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
sys.exit()
def apicall(method, path, params={}):
headers = sign(method, props['apiHost'], path, params, props['sKey'], props['iKey'])
body = None
if method == 'POST' or method == 'PUT':
body = urllib.urlencode(params)
headers['Content-Type'] = 'application/x-www-form-urlencoded'
else:
path += '?' + urllib.urlencode(params)
try:
conn = httplib.HTTPSConnection(props['apiHost'])
conn.request(method, path, headers=headers)
resp = conn.getresponse()
if resp.status != 200:
raise httplib.HTTPException(resp.status)
return json.loads(resp.read())
finally:
conn.close()
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)}
#================
# Main
#================
proppath = sys.argv[1]
with open(proppath, 'r') as f:
props = dict([ line.strip().split('=') for line in f.readlines() ])
# Query for the user_id of the user to be deleted
username = sys.argv[2]
print apicall('GET', '/admin/v1/users', {'username': username})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment