Multiple Token Assignments in Duo using Python and Admin API

This is a Python script for assigning hardware tokens to multiple users.


Pre-Requisites:
  • Source file token_assign.csv which will contain the following columns: tokenserial, username, type. This CSV file will contain the list of users and the hardware token serial number that will be assigned to them.
  • Python Modules: pytz, colorama
  • Assuming you have already installed the Duo Admin API
  • The file my_duo_keys is where you have your Duo Admin API credentials. Check this article if you need help in how to obtain the integration keys: My Duo Keys for Admin API using Python.

#import needed modules
import duo_client
import pytz
from pytz import timezone
from datetime import datetime, timedelta
from colorama import init
from colorama import Fore, Back, Style
import csv
import sys


# imports IKEY, SKEY, and API Hostname stored in another file
from my_duo_keys import *
admin_api = duo_client.Admin(
   ikey=DUO_IKEY,
   skey=DUO_SKEY,
   host=DUO_APIHOSTNAME
)
init()
print(" ")
tz_PST = timezone('US/Pacific')
sa_time = datetime.now(tz_PST)
current_time = (sa_time.strftime('%Y-%m-%d %H:%M:%S') + " " + str(tz_PST))
print(Fore.CYAN + "-------------------------------------------------------------------")
print(Fore.GREEN + "************ ASSIGNING HARDWARE TOKENS ************")
print(Fore.GREEN + "Time Started: " + current_time)
print(Fore.CYAN + "-------------------------------------------------------------------")
# open the CSV file and read from it line-by-line until the end of the file
with open('token_assign.csv') as csvfile:
    # create the file object to read from
    reader = csv.reader(csvfile)
    next(reader, None)
    count = 1
    success=0
    failed=0
    # begin to iterate through the remainder rows to assign tokens to usernames
    for row in reader:
        tokenserial=row[0]
        username=row[1]
        tokentype=row[2]         
        try:         
            user_id = admin_api.get_users_by_name(username=username)            
            for a in user_id:
                user_id = a['user_id']		
            token_id = admin_api.get_tokens_by_serial(type=tokentype,serial=tokenserial)#[0]['token_id']            
            for b in token_id:
                token_id=b['token_id']		
            # assign the token based on the values obtained previously
            admin_api.add_user_token(user_id=user_id, token_id=token_id)  
            # if we have gotten to this point the token was assigned successfully
            # prints out the message in CSV format            
            print(Fore.CYAN + "(" + str(count) + ") SN: " + tokenserial + " | User: " + username + " ...SUCCESS!")
            count += 1
            success += 1
        except Exception as e:
            # if something went wrong print the token and username that had the problem
            print(Fore.RED + "(" + str(count) + ") SN: " + tokenserial + " | User: " + username + " ...FAILED!")
            count += 1
            failed += 1
            
tz_PST = timezone('US/Pacific')
sa_time = datetime.now(tz_PST)
current_time = (sa_time.strftime('%Y-%m-%d %H:%M:%S') + " " + str(tz_PST))
print(Fore.CYAN + "-------------------------------------------------------------------")
print(Fore.GREEN + "Tokens Successfully Assigned: " + str(success))
if failed > 0:
    print(Fore.RED + "Tokens Failed to be Assigned: " + str(failed))
    print(Fore.RED + "** Please check username or SN for errors.")
print(Fore.GREEN + "Time Finished: " + current_time)
print(Fore.CYAN + "-------------------------------------------------------------------")

 

Sample Output:
Output will tell you how many successful assignments happened, and if ever there are failed.

 


References for Python Modules

* Colorama
* PYZT