This is a Python script that allows you to add a phone into an existing Duo User.
Pre-Requisites:
- 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.
from __future__ import print_function
from __future__ import absolute_import
import datetime
from datetime import datetime, timedelta
import sys
import duo_client
from six.moves import input
import pytz
from pytz import timezone
from colorama import init
from colorama import Fore, Back, Style
from my_duo_keys import *
admin_api = duo_client.Admin(ikey=DUO_IKEY, skey=DUO_SKEY, host=DUO_APIHOSTNAME)
init()
tz_PST = timezone('Asia/Singapore')
sa_time = datetime.now(tz_PST)
current_time = (sa_time.strftime('%Y-%m-%d %H:%M:%S') + " " + str(tz_PST))
def drawline(): print(Fore.WHITE + '-----------------------------------------------------------')
count = 0
print("")
drawline()
print(Fore.WHITE + "Add Phone to Individual User")
print(Fore.WHITE + "Current Time: " + current_time)
drawline()
username = input("Enter Username: ")
phonenum = input("Area Code & PhoneNumber (Ex: +639191234567): ")
phonenum = phonenum.replace(" ","")
userdata = admin_api.get_users_by_name(username = username)
for x in userdata: user_id = x['user_id']
if not userdata:
drawline()
print(Fore.WHITE + 'Result: ' + Fore.RED + "User not found in Duo!!!")
print(Fore.WHITE + "* Possible Reasons:")
print(Fore.WHITE + "*** SSO Account is not yet created")
print(Fore.WHITE + "*** User is not yet synced in AD/Azure")
print(Fore.WHITE + "*** You are providing incorrect username")
drawline()
else:
drawline()
print(Fore.WHITE + "Checking User Information...")
print(Fore.WHITE + 'Result: ' + Fore.CYAN + "User found in Duo!!!")
print(Fore.WHITE + "Checking Phone Information...")
phonedata = admin_api.get_phones_by_number(number=phonenum)
if not phonedata:
print(Fore.CYAN + "** Phone not yet in Duo. Adding...")
add_phone = admin_api.add_phone(number=phonenum)
print(Fore.CYAN + "** Phone added to Duo.")
phonedata = admin_api.get_phones_by_number(number=phonenum)
for x in phonedata:
phone_id = x['phone_id']
print(Fore.WHITE + 'Phone ID: ' +Fore.CYAN + str(x['phone_id']))
print(Fore.WHITE + 'Phone No.: ' +Fore.CYAN + str(x['number']))
print(Fore.WHITE + 'Activated: ' +Fore.CYAN + str(x['activated']))
else:
for x in phonedata:
phone_id = x['phone_id']
print(Fore.WHITE + 'Phone ID: ' +Fore.CYAN + str(x['phone_id']))
print(Fore.WHITE + 'Phone No.: ' +Fore.CYAN + str(x['number']))
print(Fore.WHITE + 'Activated: ' +Fore.CYAN + str(x['activated']))
print(Fore.WHITE + 'Last Seen: ' +Fore.CYAN + str(x['last_seen']))
for y in x['users']: count += 1
if count > 0:
print(Fore.CYAN + "** Phone is already assigned to " + str(count) +" user(s).")
for x in phonedata:
for y in x['users']:
print("* " + y['username'])
print(Fore.WHITE)
proceed = input("Do you want to proceed assigning the phone? (Y/N): ")
if proceed == "Y":
admin_api.add_user_phone(user_id=user_id, phone_id=phone_id)
drawline()
print(Fore.CYAN + "** Phone assigned successfully.")
userdata = admin_api.get_users_by_name(username = username)
for z in userdata:
print(Fore.WHITE + 'Result: ' + Fore.CYAN + 'User Synced Successfully!!!')
print(Fore.WHITE + 'FullName: ' + Fore.CYAN + z['realname'])
print(Fore.WHITE + 'User ID: '+ Fore.CYAN + z['user_id'])
print(Fore.WHITE + 'Email Address: '+ Fore.CYAN + z['email'])
if(z['status'] == "active" or z['status'] == "Active"): print(Fore.WHITE + 'Status: '+ Fore.CYAN + z['status'])
else:
print(Fore.WHITE + 'Status: '+ Fore.RED + z['status'])
print(Fore.RED + "* If user is still active, please check why user is disabled in AD.")
print(Fore.WHITE + 'Enrolled: '+ Fore.CYAN + str(z['is_enrolled']))
if z['alias1']: print(Fore.WHITE + 'Alias 1: '+ Fore.CYAN + str(z['alias1']))
if z['alias2']: print(Fore.WHITE + 'Alias 2: '+ Fore.CYAN + str(z['alias2']))
if z['alias3']: print(Fore.WHITE + 'Alias 3: '+ Fore.CYAN + str(z['alias3']))
if z['alias4']: print(Fore.WHITE + 'Alias 4: '+ Fore.CYAN + str(z['alias4']))
drawline()
print(Fore.WHITE + 'Date Created (UTC): '+ Fore.CYAN +datetime.utcfromtimestamp(z['created']).strftime('%Y-%m-%d %H:%M:%S'))
if not z['last_directory_sync']: print(Fore.WHITE + 'Last Directory Sync (UTC): '+ Fore.CYAN + "Not Data")
else: print(Fore.WHITE + 'Last Directory Sync (UTC): '+ Fore.CYAN +datetime.utcfromtimestamp(z['last_directory_sync']).strftime('%Y-%m-%d %H:%M:%S'))
if not z['last_login']: print(Fore.WHITE + 'Last Login (UTC): '+ Fore.CYAN + "Not Data")
else: print(Fore.WHITE + 'Last Login (UTC): '+ Fore.CYAN +datetime.utcfromtimestamp(z['last_login']).strftime('%Y-%m-%d %H:%M:%S'))
drawline()
for phone in z["phones"]:
print(Fore.WHITE + 'Phone OS: '+ Fore.CYAN + phone['platform'])
print(Fore.WHITE + 'Phone Model: '+ Fore.CYAN + phone['model'])
print(Fore.WHITE + 'Phone Number: '+ Fore.CYAN + phone['number'])
print(Fore.WHITE + 'ID: '+ Fore.CYAN + phone['phone_id'])
drawline()
if not z["tokens"]: print(Fore.WHITE + 'No Hardware Token linked to this user.')
else:
for x in z["tokens"]:
print(Fore.WHITE + 'Token ID: '+ Fore.CYAN + x['token_id'])
print(Fore.WHITE + 'Serial Number: '+ Fore.CYAN + x['serial'])
print(Fore.WHITE + 'Token Type: '+ Fore.CYAN + x['type'])
drawline()
print(Fore.WHITE + 'Group Membership:')
if not z["groups"]: print(Fore.RED + "*** No Group Membership Found ***")
for grp in z["groups"]:
print(Fore.CYAN +grp['name'])
drawline()
print(" ")
elif proceed == "N":
print(Fore.RED + "Exiting program.")
drawline()
sys.exit()
else:
print(Fore.RED + "Invalid Input. Exiting program.")
drawline()
sys.exit()
Sample Output:
Adding a new phone to a user: If the phone is not yet existing in Duo, the script creates the phone, then adds it after user’s confirmation.

If a phone is already assigned to other users, the script will display the usernames of the existing assigned users. Script will continue upon user’s confirmation.

The script will exit if user inputs “N” (as in NO), when asked to proceed phone assignment. It also exits if an invalid character is provided.

This is a sample output if the username provided is not found in Duo.
