174174import six .moves .urllib
175175
176176from . import client
177+ from .logs .telephony import Telephony
177178import six
178179import warnings
179180import time
180181import base64
181- from datetime import datetime , timedelta
182+ from datetime import datetime , timedelta , timezone
182183
183- USER_STATUS_ACTIVE = ' active'
184- USER_STATUS_BYPASS = ' bypass'
185- USER_STATUS_DISABLED = ' disabled'
186- USER_STATUS_LOCKED_OUT = ' locked out'
184+ USER_STATUS_ACTIVE = " active"
185+ USER_STATUS_BYPASS = " bypass"
186+ USER_STATUS_DISABLED = " disabled"
187+ USER_STATUS_LOCKED_OUT = " locked out"
187188
188- TOKEN_HOTP_6 = 'h6'
189- TOKEN_HOTP_8 = 'h8'
190- TOKEN_YUBIKEY = 'yk'
189+ TOKEN_HOTP_6 = "h6"
190+ TOKEN_HOTP_8 = "h8"
191+ TOKEN_YUBIKEY = "yk"
191192
192193VALID_AUTHLOG_REQUEST_PARAMS = [
193- ' mintime' ,
194- ' maxtime' ,
195- ' limit' ,
196- ' sort' ,
197- ' next_offset' ,
198- ' event_types' ,
199- ' reasons' ,
200- ' results' ,
201- ' users' ,
202- ' applications' ,
203- ' groups' ,
204- ' factors' ,
205- ' api_version'
194+ " mintime" ,
195+ " maxtime" ,
196+ " limit" ,
197+ " sort" ,
198+ " next_offset" ,
199+ " event_types" ,
200+ " reasons" ,
201+ " results" ,
202+ " users" ,
203+ " applications" ,
204+ " groups" ,
205+ " factors" ,
206+ " api_version" ,
206207]
207208
208- VALID_ACTIVITY_REQUEST_PARAMS = [
209- 'mintime' ,
210- 'maxtime' ,
211- 'limit' ,
212- 'sort' ,
213- 'next_offset'
214- ]
209+ VALID_ACTIVITY_REQUEST_PARAMS = ["mintime" , "maxtime" , "limit" , "sort" , "next_offset" ]
215210
216211
217212class Admin (client .Client ):
@@ -598,12 +593,12 @@ def get_activity_logs(self, **kwargs):
598593 "value" : <int: total objects in the time range>
599594 }
600595 }
601- },
596+ }
602597
603598 Raises RuntimeError on error.
604599 """
605600 params = {}
606- today = datetime .utcnow ( )
601+ today = datetime .now ( tz = timezone . utc )
607602 default_maxtime = int (today .timestamp () * 1000 )
608603 default_mintime = int ((today - timedelta (days = 180 )).timestamp () * 1000 )
609604
@@ -622,8 +617,6 @@ def get_activity_logs(self, **kwargs):
622617 if 'limit' in params :
623618 params ['limit' ] = str (int (params ['limit' ]))
624619
625-
626-
627620 response = self .json_api_call (
628621 'GET' ,
629622 '/admin/v2/logs/activity' ,
@@ -634,41 +627,64 @@ def get_activity_logs(self, **kwargs):
634627 row ['host' ] = self .host
635628 return response
636629
637- def get_telephony_log (self ,
638- mintime = 0 ):
630+ def get_telephony_log (self , mintime = 0 , api_version = 1 , ** kwargs ):
639631 """
640632 Returns telephony log events.
641633
642634 mintime - Fetch events only >= mintime (to avoid duplicate
643- records that have already been fetched)
644-
645- Returns:
635+ records that have already been fetched)
636+ api_version - The API version of the handler to use.
637+ Currently, the default api version is v1, but the v1 API
638+ will be deprecated in a future version of the Duo Admin API.
639+ Please migrate to the v2 api at your earliest convenience.
640+ For details on the differences between v1 and v2,
641+ please see Duo's Admin API documentation. (Optional)
642+
643+ v1 Returns:
646644 [
647- {'timestamp': <int:unix timestamp>,
648- 'eventtype': "telephony",
649- 'host': <str:host>,
650- 'context': <str:context>,
651- 'type': <str:type>,
652- 'phone': <str:phone number>,
653- 'credits': <str:credits>}, ...
645+ {
646+ 'timestamp': <int:unix timestamp>,
647+ 'eventtype': "telephony",
648+ 'host': <str:host>,
649+ 'context': <str:context>,
650+ 'type': <str:type>,
651+ 'phone': <str:phone number>,
652+ 'credits': <str:credits>}
654653 ]
654+
655+ v2 Returns:
656+ {
657+ "items": [
658+ {
659+ 'context': <str>,
660+ 'credits': <int: credits used>,
661+ 'phone': <str:phone number>,
662+ 'telephony_id': <str:UUID>,
663+ 'ts': <str:ISO timestamp>,
664+ 'txid': <str:UUID>,
665+ 'type': <str:"sms" or "phone">,
666+ 'eventtype': <str:"telephony">,
667+ 'host': <str:application hostname>
668+ }
669+ ],
670+ "metadata": {
671+ "next_offset": <str: comma seperated ts and offset value>
672+ "total_objects": {
673+ "relation" : <str: relational operator>
674+ "value" : <int: total objects in the time range>
675+ }
676+ }
677+ }
655678
656679 Raises RuntimeError on error.
657680 """
658- # Sanity check mintime as unix timestamp, then transform to string
659- mintime = str (int (mintime ))
660- params = {
661- 'mintime' : mintime ,
662- }
663- response = self .json_api_call (
664- 'GET' ,
665- '/admin/v1/logs/telephony' ,
666- params ,
667- )
668- for row in response :
669- row ['eventtype' ] = 'telephony'
670- row ['host' ] = self .host
671- return response
681+
682+ if api_version not in [1 ,2 ]:
683+ raise ValueError ("Invalid API Version" )
684+
685+ if api_version == 2 :
686+ return Telephony .get_telephony_logs_v2 (self .json_api_call , self .host , ** kwargs )
687+ return Telephony .get_telephony_logs_v1 (self .json_api_call , self .host , mintime = mintime )
672688
673689 def get_users_iterator (self ):
674690 """
0 commit comments