Created
February 9, 2016 19:21
-
-
Save serac/52fec0e1f139c02c02d7 to your computer and use it in GitHub Desktop.
Duo Python User Query Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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