def _build_query(query, myarg, i, query_discovery): if not query: query = {'dataScope': 'ALL_DATA'} if myarg == 'corpus': query['corpus'] = sys.argv[i + 1].upper() allowed_corpuses = gapi.get_enum_values_minus_unspecified( query_discovery['properties']['corpus']['enum']) if query['corpus'] not in allowed_corpuses: controlflow.expected_argument_exit('corpus', ', '.join(allowed_corpuses), sys.argv[i + 1]) i += 2 elif myarg in VAULT_SEARCH_METHODS_MAP: if query.get('searchMethod'): message = f'Multiple search methods ' \ f'({", ".join(VAULT_SEARCH_METHODS_LIST)})' \ f'specified, only one is allowed' controlflow.system_error_exit(3, message) searchMethod = VAULT_SEARCH_METHODS_MAP[myarg] query['searchMethod'] = searchMethod if searchMethod == 'ACCOUNT': query['accountInfo'] = {'emails': sys.argv[i + 1].split(',')} i += 2 elif searchMethod == 'ORG_UNIT': query['orgUnitInfo'] = { 'orgUnitId': gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1])[1] } i += 2 elif searchMethod == 'SHARED_DRIVE': query['sharedDriveInfo'] = { 'sharedDriveIds': sys.argv[i + 1].split(',') } i += 2 elif searchMethod == 'ROOM': query['hangoutsChatInfo'] = {'roomId': sys.argv[i + 1].split(',')} i += 2 else: i += 1 elif myarg == 'scope': query['dataScope'] = sys.argv[i + 1].upper() allowed_scopes = gapi.get_enum_values_minus_unspecified( query_discovery['properties']['dataScope']['enum']) if query['dataScope'] not in allowed_scopes: controlflow.expected_argument_exit('scope', ', '.join(allowed_scopes), sys.argv[i + 1]) i += 2 elif myarg in ['terms']: query['terms'] = sys.argv[i + 1] i += 2 elif myarg in ['start', 'starttime']: query['startTime'] = utils.get_date_zero_time_or_full_time(sys.argv[i + 1]) i += 2 elif myarg in ['end', 'endtime']: query['endTime'] = utils.get_date_zero_time_or_full_time(sys.argv[i + 1]) i += 2 elif myarg in ['timezone']: query['timeZone'] = sys.argv[i + 1] i += 2 elif myarg in ['excludedrafts']: query['mailOptions'] = { 'excludeDrafts': gam.getBoolean(sys.argv[i + 1], myarg) } i += 2 elif myarg in ['driveversiondate']: query.setdefault('driveOptions', {})['versionDate'] = \ utils.get_date_zero_time_or_full_time(sys.argv[i+1]) i += 2 elif myarg in ['includeshareddrives', 'includeteamdrives']: query.setdefault('driveOptions', {})['includeSharedDrives'] = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 elif myarg in ['includerooms']: query['hangoutsChatOptions'] = { 'includeRooms': gam.getBoolean(sys.argv[i + 1], myarg) } i += 2 return (query, i)
def doPrintCrosDevices(): def _getSelectedLists(myarg): if myarg in CROS_ACTIVE_TIME_RANGES_ARGUMENTS: selectedLists['activeTimeRanges'] = True elif myarg in CROS_RECENT_USERS_ARGUMENTS: selectedLists['recentUsers'] = True elif myarg in CROS_DEVICE_FILES_ARGUMENTS: selectedLists['deviceFiles'] = True elif myarg in CROS_CPU_STATUS_REPORTS_ARGUMENTS: selectedLists['cpuStatusReports'] = True elif myarg in CROS_DISK_VOLUME_REPORTS_ARGUMENTS: selectedLists['diskVolumeReports'] = True elif myarg in CROS_SYSTEM_RAM_FREE_REPORTS_ARGUMENTS: selectedLists['systemRamFreeReports'] = True cd = gapi_directory.build() todrive = False fieldsList = [] fieldsTitles = {} titles = [] csvRows = [] display.add_field_to_csv_file('deviceid', CROS_ARGUMENT_TO_PROPERTY_MAP, fieldsList, fieldsTitles, titles) projection = orderBy = sortOrder = orgUnitPath = None queries = [None] noLists = sortHeaders = False selectedLists = {} startDate = endDate = None listLimit = 0 i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg in ['query', 'queries']: queries = gam.getQueries(myarg, sys.argv[i + 1]) i += 2 elif myarg == 'limittoou': orgUnitPath = gapi_directory_orgunits.getOrgUnitItem(sys.argv[i + 1]) i += 2 elif myarg == 'todrive': todrive = True i += 1 elif myarg == 'nolists': noLists = True selectedLists = {} i += 1 elif myarg == 'listlimit': listLimit = gam.getInteger(sys.argv[i + 1], myarg, minVal=0) i += 2 elif myarg in CROS_START_ARGUMENTS: startDate = _getFilterDate(sys.argv[i + 1]) i += 2 elif myarg in CROS_END_ARGUMENTS: endDate = _getFilterDate(sys.argv[i + 1]) i += 2 elif myarg == 'orderby': orderBy = sys.argv[i + 1].lower().replace('_', '') validOrderBy = [ 'location', 'user', 'lastsync', 'notes', 'serialnumber', 'status', 'supportenddate' ] if orderBy not in validOrderBy: controlflow.expected_argument_exit('orderby', ', '.join(validOrderBy), orderBy) if orderBy == 'location': orderBy = 'annotatedLocation' elif orderBy == 'user': orderBy = 'annotatedUser' elif orderBy == 'lastsync': orderBy = 'lastSync' elif orderBy == 'serialnumber': orderBy = 'serialNumber' elif orderBy == 'supportenddate': orderBy = 'supportEndDate' i += 2 elif myarg in SORTORDER_CHOICES_MAP: sortOrder = SORTORDER_CHOICES_MAP[myarg] i += 1 elif myarg in PROJECTION_CHOICES_MAP: projection = PROJECTION_CHOICES_MAP[myarg] sortHeaders = True if projection == 'FULL': fieldsList = [] else: fieldsList = CROS_BASIC_FIELDS_LIST[:] i += 1 elif myarg == 'allfields': projection = 'FULL' sortHeaders = True fieldsList = [] i += 1 elif myarg == 'sortheaders': sortHeaders = True i += 1 elif myarg in CROS_LISTS_ARGUMENTS: _getSelectedLists(myarg) i += 1 elif myarg in CROS_ARGUMENT_TO_PROPERTY_MAP: display.add_field_to_fields_list(myarg, CROS_ARGUMENT_TO_PROPERTY_MAP, fieldsList) i += 1 elif myarg == 'fields': fieldNameList = sys.argv[i + 1] for field in fieldNameList.lower().replace(',', ' ').split(): if field in CROS_LISTS_ARGUMENTS: _getSelectedLists(field) elif field in CROS_ARGUMENT_TO_PROPERTY_MAP: display.add_field_to_fields_list( field, CROS_ARGUMENT_TO_PROPERTY_MAP, fieldsList) else: controlflow.invalid_argument_exit(field, 'gam print cros fields') i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam print cros') if selectedLists: noLists = False projection = 'FULL' for selectList in selectedLists: display.add_field_to_fields_list(selectList, CROS_ARGUMENT_TO_PROPERTY_MAP, fieldsList) if fieldsList: fieldsList.append('deviceId') fields = f'nextPageToken,chromeosdevices({",".join(set(fieldsList))})'.replace( '.', '/') else: fields = None for query in queries: gam.printGettingAllItems('CrOS Devices', query) page_message = gapi.got_total_items_msg('CrOS Devices', '...\n') all_cros = gapi.get_all_pages(cd.chromeosdevices(), 'list', 'chromeosdevices', page_message=page_message, query=query, customerId=GC_Values[GC_CUSTOMER_ID], projection=projection, orgUnitPath=orgUnitPath, orderBy=orderBy, sortOrder=sortOrder, fields=fields) for cros in all_cros: _checkTPMVulnerability(cros) if not noLists and not selectedLists: for cros in all_cros: if 'notes' in cros: cros['notes'] = cros['notes'].replace('\n', '\\n') if 'autoUpdateExpiration' in cros: cros['autoUpdateExpiration'] = utils.formatTimestampYMD( cros['autoUpdateExpiration']) for cpuStatusReport in cros.get('cpuStatusReports', []): tempInfos = cpuStatusReport.get('cpuTemperatureInfo', []) for tempInfo in tempInfos: tempInfo['label'] = tempInfo['label'].strip() display.add_row_titles_to_csv_file( utils.flatten_json(cros, listLimit=listLimit), csvRows, titles) continue for cros in all_cros: if 'notes' in cros: cros['notes'] = cros['notes'].replace('\n', '\\n') if 'autoUpdateExpiration' in cros: cros['autoUpdateExpiration'] = utils.formatTimestampYMD( cros['autoUpdateExpiration']) row = {} for attrib in cros: if attrib not in set([ 'kind', 'etag', 'tpmVersionInfo', 'recentUsers', 'activeTimeRanges', 'deviceFiles', 'cpuStatusReports', 'diskVolumeReports', 'systemRamFreeReports' ]): row[attrib] = cros[attrib] if selectedLists.get('activeTimeRanges'): timergs = cros.get('activeTimeRanges', []) else: timergs = [] activeTimeRanges = _filterTimeRanges(timergs, startDate, endDate) if selectedLists.get('recentUsers'): recentUsers = cros.get('recentUsers', []) else: recentUsers = [] if selectedLists.get('deviceFiles'): device_files = cros.get('deviceFiles', []) else: device_files = [] deviceFiles = _filterCreateReportTime(device_files, 'createTime', startDate, endDate) if selectedLists.get('cpuStatusReports'): cpu_reports = cros.get('cpuStatusReports', []) else: cpu_reports = [] cpuStatusReports = _filterCreateReportTime(cpu_reports, 'reportTime', startDate, endDate) if selectedLists.get('diskVolumeReports'): diskVolumeReports = cros.get('diskVolumeReports', []) else: diskVolumeReports = [] if selectedLists.get('systemRamFreeReports'): ram_reports = cros.get('systemRamFreeReports', []) else: ram_reports = [] systemRamFreeReports = _filterCreateReportTime( ram_reports, 'reportTime', startDate, endDate) if noLists or (not activeTimeRanges and \ not recentUsers and \ not deviceFiles and \ not cpuStatusReports and \ not diskVolumeReports and \ not systemRamFreeReports): display.add_row_titles_to_csv_file(row, csvRows, titles) continue lenATR = len(activeTimeRanges) lenRU = len(recentUsers) lenDF = len(deviceFiles) lenCSR = len(cpuStatusReports) lenDVR = len(diskVolumeReports) lenSRFR = len(systemRamFreeReports) max_len = max(lenATR, lenRU, lenDF, lenCSR, lenDVR, lenSRFR) for i in range(min(max_len, listLimit or max_len)): nrow = row.copy() if i < lenATR: nrow['activeTimeRanges.date'] = \ activeTimeRanges[i]['date'] nrow['activeTimeRanges.activeTime'] = \ str(activeTimeRanges[i]['activeTime']) active_time = activeTimeRanges[i]['activeTime'] nrow['activeTimeRanges.duration'] = \ utils.formatMilliSeconds(active_time) nrow['activeTimeRanges.minutes'] = active_time // 60000 if i < lenRU: nrow['recentUsers.type'] = recentUsers[i]['type'] nrow['recentUsers.email'] = recentUsers[i].get('email') if not nrow['recentUsers.email']: if nrow['recentUsers.type'] == 'USER_TYPE_UNMANAGED': nrow['recentUsers.email'] = 'UnmanagedUser' else: nrow['recentUsers.email'] = 'Unknown' if i < lenDF: nrow['deviceFiles.type'] = deviceFiles[i]['type'] nrow['deviceFiles.createTime'] = \ deviceFiles[i]['createTime'] if i < lenCSR: nrow['cpuStatusReports.reportTime'] = \ cpuStatusReports[i]['reportTime'] tempInfos = cpuStatusReports[i].get( 'cpuTemperatureInfo', []) for tempInfo in tempInfos: label = tempInfo['label'].strip() base = 'cpuStatusReports.cpuTemperatureInfo.' nrow[f'{base}{label}'] = tempInfo['temperature'] cpu_field = 'cpuUtilizationPercentageInfo' cpu_reports = cpuStatusReports[i][cpu_field] cpu_pcts = [str(x) for x in cpu_reports] nrow[f'cpuStatusReports.{cpu_field}'] = ','.join(cpu_pcts) if i < lenDVR: volumeInfo = diskVolumeReports[i]['volumeInfo'] j = 0 vfield = 'diskVolumeReports.volumeInfo.' for volume in volumeInfo: nrow[f'{vfield}{j}.volumeId'] = \ volume['volumeId'] nrow[f'{vfield}{j}.storageFree'] = \ volume['storageFree'] nrow[f'{vfield}{j}.storageTotal'] = \ volume['storageTotal'] j += 1 if i < lenSRFR: nrow['systemRamFreeReports.reportTime'] = \ systemRamFreeReports[i]['reportTime'] ram_reports = systemRamFreeReports[i]['systemRamFreeInfo'] ram_info = [str(x) for x in ram_reports] nrow['systenRamFreeReports.systemRamFreeInfo'] = \ ','.join(ram_info) display.add_row_titles_to_csv_file(nrow, csvRows, titles) if sortHeaders: display.sort_csv_titles([ 'deviceId', ], titles) display.write_csv_file(csvRows, titles, 'CrOS', todrive)
def createExport(): v = buildGAPIObject() query_discovery = v._rootDesc['schemas']['Query'] allowed_formats = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['MailExportOptions']['properties'] ['exportFormat']['enum']) export_format = 'MBOX' showConfidentialModeContent = None # default to not even set matterId = None query = None body = {'exportOptions': {}} i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'matter': matterId = getMatterItem(v, sys.argv[i + 1]) body['matterId'] = matterId i += 2 elif myarg == 'name': body['name'] = sys.argv[i + 1] i += 2 elif myarg in QUERY_ARGS: query, i = _build_query(query, myarg, i, query_discovery) elif myarg in ['format']: export_format = sys.argv[i + 1].upper() if export_format not in allowed_formats: controlflow.expected_argument_exit('export format', ', '.join(allowed_formats), export_format) i += 2 elif myarg in ['showconfidentialmodecontent']: showConfidentialModeContent = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 elif myarg in ['region']: allowed_regions = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['ExportOptions']['properties']['region'] ['enum']) body['exportOptions']['region'] = sys.argv[i + 1].upper() if body['exportOptions']['region'] not in allowed_regions: controlflow.expected_argument_exit( 'region', ', '.join(allowed_regions), body['exportOptions']['region']) i += 2 elif myarg in ['includeaccessinfo']: body['exportOptions'].setdefault( 'driveOptions', {})['includeAccessInfo'] = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam create export') if not matterId: controlflow.system_error_exit( 3, 'you must specify a matter for the new export.') _validate_query(query, query_discovery) body['query'] = query if 'name' not in body: corpus_name = body['query']['corpus'] corpus_date = datetime.datetime.now() body['name'] = f'GAM {corpus_name} export - {corpus_date}' options_field = None if body['query']['corpus'] == 'MAIL': options_field = 'mailOptions' elif body['query']['corpus'] == 'GROUPS': options_field = 'groupsOptions' elif body['query']['corpus'] == 'HANGOUTS_CHAT': options_field = 'hangoutsChatOptions' if options_field: body['exportOptions'].pop('driveOptions', None) body['exportOptions'][options_field] = {'exportFormat': export_format} if showConfidentialModeContent is not None: body['exportOptions'][options_field][ 'showConfidentialModeContent'] = showConfidentialModeContent results = gapi.call(v.matters().exports(), 'create', matterId=matterId, body=body) print(f'Created export {results["id"]}') display.print_json(results)
def createHold(): v = buildGAPIObject() allowed_corpuses = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['Hold']['properties']['corpus']['enum']) body = {'query': {}} i = 3 query = None start_time = None end_time = None matterId = None accounts = [] while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'name': body['name'] = sys.argv[i + 1] i += 2 elif myarg == 'query': query = sys.argv[i + 1] i += 2 elif myarg == 'corpus': body['corpus'] = sys.argv[i + 1].upper() if body['corpus'] not in allowed_corpuses: controlflow.expected_argument_exit('corpus', ', '.join(allowed_corpuses), sys.argv[i + 1]) i += 2 elif myarg in ['accounts', 'users', 'groups']: accounts = sys.argv[i + 1].split(',') i += 2 elif myarg in ['orgunit', 'ou']: body['orgUnit'] = { 'orgUnitId': gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1])[1] } i += 2 elif myarg in ['start', 'starttime']: start_time = utils.get_date_zero_time_or_full_time(sys.argv[i + 1]) i += 2 elif myarg in ['end', 'endtime']: end_time = utils.get_date_zero_time_or_full_time(sys.argv[i + 1]) i += 2 elif myarg == 'matter': matterId = getMatterItem(v, sys.argv[i + 1]) i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam create hold') if not matterId: controlflow.system_error_exit( 3, 'you must specify a matter for the new hold.') if not body.get('name'): controlflow.system_error_exit( 3, 'you must specify a name for the new hold.') if not body.get('corpus'): controlflow.system_error_exit(3, f'you must specify a corpus for ' \ f'the new hold. Choose one of {", ".join(allowed_corpuses)}') if body['corpus'] == 'HANGOUTS_CHAT': query_type = 'hangoutsChatQuery' else: query_type = f'{body["corpus"].lower()}Query' body['query'][query_type] = {} if body['corpus'] == 'DRIVE': if query: try: body['query'][query_type] = json.loads(query) except ValueError as e: controlflow.system_error_exit(3, f'{str(e)}, query: {query}') elif body['corpus'] in ['GROUPS', 'MAIL']: if query: body['query'][query_type] = {'terms': query} if start_time: body['query'][query_type]['startTime'] = start_time if end_time: body['query'][query_type]['endTime'] = end_time if accounts: body['accounts'] = [] cd = gam.buildGAPIObject('directory') account_type = 'group' if body['corpus'] == 'GROUPS' else 'user' for account in accounts: body['accounts'].append({ 'accountId': gam.convertEmailAddressToUID(account, cd, account_type) }) holdId = gapi.call(v.matters().holds(), 'create', matterId=matterId, body=body, fields='holdId') print(f'Created hold {holdId["holdId"]}')
def print_(): cd = gapi_directory.build() todrive = False titles = [] csvRows = [] fields = None projection = orderBy = sortOrder = None queries = [None] delimiter = ' ' listLimit = 1 appsLimit = -1 i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'todrive': todrive = True i += 1 elif myarg in ['query', 'queries']: queries = gam.getQueries(myarg, sys.argv[i + 1]) i += 2 elif myarg == 'delimiter': delimiter = sys.argv[i + 1] i += 2 elif myarg == 'listlimit': listLimit = gam.getInteger(sys.argv[i + 1], myarg, minVal=-1) i += 2 elif myarg == 'appslimit': appsLimit = gam.getInteger(sys.argv[i + 1], myarg, minVal=-1) i += 2 elif myarg == 'fields': fields = f'nextPageToken,mobiledevices({sys.argv[i+1]})' i += 2 elif myarg == 'orderby': orderBy = sys.argv[i + 1].lower() validOrderBy = [ 'deviceid', 'email', 'lastsync', 'model', 'name', 'os', 'status', 'type' ] if orderBy not in validOrderBy: controlflow.expected_argument_exit('orderby', ', '.join(validOrderBy), orderBy) if orderBy == 'lastsync': orderBy = 'lastSync' elif orderBy == 'deviceid': orderBy = 'deviceId' i += 2 elif myarg in SORTORDER_CHOICES_MAP: sortOrder = SORTORDER_CHOICES_MAP[myarg] i += 1 elif myarg in PROJECTION_CHOICES_MAP: projection = PROJECTION_CHOICES_MAP[myarg] i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam print mobile') for query in queries: gam.printGettingAllItems('Mobile Devices', query) page_message = gapi.got_total_items_msg('Mobile Devices', '...\n') all_mobile = gapi.get_all_pages(cd.mobiledevices(), 'list', 'mobiledevices', page_message=page_message, customerId=GC_Values[GC_CUSTOMER_ID], query=query, projection=projection, fields=fields, orderBy=orderBy, sortOrder=sortOrder) for mobile in all_mobile: row = {} for attrib in mobile: if attrib in ['kind', 'etag']: continue if attrib in ['name', 'email', 'otherAccountsInfo']: if attrib not in titles: titles.append(attrib) if listLimit > 0: row[attrib] = delimiter.join( mobile[attrib][0:listLimit]) elif listLimit == 0: row[attrib] = delimiter.join(mobile[attrib]) elif attrib == 'applications': if appsLimit >= 0: if attrib not in titles: titles.append(attrib) applications = [] j = 0 for app in mobile[attrib]: j += 1 if appsLimit and (j > appsLimit): break appDetails = [] for field in [ 'displayName', 'packageName', 'versionName' ]: appDetails.append(app.get(field, '<None>')) appDetails.append( str(app.get('versionCode', '<None>'))) permissions = app.get('permission', []) if permissions: appDetails.append('/'.join(permissions)) else: appDetails.append('<None>') applications.append('-'.join(appDetails)) row[attrib] = delimiter.join(applications) else: if attrib not in titles: titles.append(attrib) if attrib == 'deviceId': row[attrib] = mobile[attrib].encode( 'unicode-escape').decode(UTF8) elif attrib == 'securityPatchLevel' and int( mobile[attrib]): row[attrib] = utils.formatTimestampYMDHMS( mobile[attrib]) else: row[attrib] = mobile[attrib] csvRows.append(row) display.sort_csv_titles( ['resourceId', 'deviceId', 'serialNumber', 'name', 'email', 'status'], titles) display.write_csv_file(csvRows, titles, 'Mobile', todrive)
def showUsageParameters(): rep = build() throw_reasons = [ gapi.errors.ErrorReason.INVALID, gapi.errors.ErrorReason.BAD_REQUEST ] todrive = False if len(sys.argv) == 3: controlflow.missing_argument_exit('user or customer', 'report usageparameters') report = sys.argv[3].lower() titles = ['parameter'] if report == 'customer': endpoint = rep.customerUsageReports() kwargs = {} elif report == 'user': endpoint = rep.userUsageReport() kwargs = {'userKey': gam._get_admin_email()} else: controlflow.expected_argument_exit('usageparameters', ['user', 'customer'], report) customerId = GC_Values[GC_CUSTOMER_ID] if customerId == MY_CUSTOMER: customerId = None tryDate = datetime.date.today().strftime(YYYYMMDD_FORMAT) all_parameters = set() i = 4 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'todrive': todrive = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam report usageparameters') fullDataRequired = ['all'] while True: try: result = gapi.call( endpoint, 'get', throw_reasons=throw_reasons, date=tryDate, customerId=customerId, fields='warnings,usageReports(parameters(name))', **kwargs) warnings = result.get('warnings', []) usage = result.get('usageReports') has_reports = bool(usage) fullData, tryDate = _check_full_data_available( warnings, tryDate, fullDataRequired, has_reports) if fullData < 0: print('No usage parameters available.') sys.exit(1) if has_reports: for parameter in usage[0]['parameters']: name = parameter.get('name') if name: all_parameters.add(name) if fullData == 1: break except gapi.errors.GapiInvalidError as e: tryDate = _adjust_date(str(e)) csvRows = [] for parameter in sorted(all_parameters): csvRows.append({'parameter': parameter}) display.write_csv_file(csvRows, titles, f'{report.capitalize()} Report Usage Parameters', todrive)
def showUsageParameters(): rep = buildGAPIObject() throw_reasons = [ gapi.errors.ErrorReason.INVALID, gapi.errors.ErrorReason.BAD_REQUEST ] todrive = False if len(sys.argv) == 3: controlflow.missing_argument_exit('user or customer', 'report usageparameters') report = sys.argv[3].lower() titles = ['parameter'] if report == 'customer': endpoint = rep.customerUsageReports() kwargs = {} elif report == 'user': endpoint = rep.userUsageReport() kwargs = {'userKey': gam._getValueFromOAuth('email')} else: controlflow.expected_argument_exit('usageparameters', ['user', 'customer'], report) customerId = GC_Values[GC_CUSTOMER_ID] if customerId == MY_CUSTOMER: customerId = None tryDate = datetime.date.today().strftime(YYYYMMDD_FORMAT) partial_apps = [] all_parameters = [] one_day = datetime.timedelta(days=1) i = 4 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'todrive': todrive = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], "gam report usageparameters") while True: try: response = gapi.call(endpoint, 'get', throw_reasons=throw_reasons, date=tryDate, customerId=customerId, **kwargs) partial_on_thisday = [] for warning in response.get('warnings', []): for data in warning.get('data', []): if data.get('key') == 'application': partial_on_thisday.append(data['value']) if partial_apps: partial_apps = [ app for app in partial_apps if app in partial_on_thisday ] else: partial_apps = partial_on_thisday for parameter in response['usageReports'][0]['parameters']: name = parameter.get('name') if name and name not in all_parameters: all_parameters.append(name) if not partial_apps: break tryDate = (utils.get_yyyymmdd(tryDate, returnDateTime=True) - \ one_day).strftime(YYYYMMDD_FORMAT) except gapi.errors.GapiInvalidError as e: tryDate = _adjust_date(str(e)) all_parameters.sort() csvRows = [] for parameter in all_parameters: csvRows.append({'parameter': parameter}) display.write_csv_file(csvRows, titles, f'{report.capitalize()} Report Usage Parameters', todrive)
def sync(): ci = gapi_cloudidentity.build_dwd() device_types = gapi.get_enum_values_minus_unspecified( ci._rootDesc['schemas']['GoogleAppsCloudidentityDevicesV1Device'] ['properties']['deviceType']['enum']) customer = _get_device_customerid() device_filter = None csv_file = None serialnumber_column = 'serialNumber' devicetype_column = 'deviceType' static_devicetype = None assettag_column = None unassigned_missing_action = 'delete' assigned_missing_action = 'donothing' missing_actions = ['delete', 'wipe', 'donothing'] i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg in ['filter', 'query']: device_filter = sys.argv[i + 1] i += 2 elif myarg == 'csvfile': csv_file = sys.argv[i + 1] i += 2 elif myarg == 'serialnumbercolumn': serialnumber_column = sys.argv[i + 1] i += 2 elif myarg == 'devicetypecolumn': devicetype_column = sys.argv[i + 1] i += 2 elif myarg == 'staticdevicetype': static_devicetype = sys.argv[i + 1].upper() if static_devicetype not in device_types: controlflow.expected_argument_exit('device_type', ', '.join(device_types), sys.argv[i + 1]) i += 2 elif myarg in {'assettagcolumn', 'assetidcolumn'}: assettag_column = sys.argv[i + 1] i += 2 elif myarg == 'unassignedmissingaction': unassigned_missing_action = sys.argv[i + 1].lower().replace( '_', '') if unassigned_missing_action not in missing_actions: controlflow.expected_argument_exit('unassigned_missing_action', ', '.join(missing_actions), sys.argv[i + 1]) i += 2 elif myarg == 'assignedmissingaction': assigned_missing_action = sys.argv[i + 1].lower().replace('_', '') if assigned_missing_action not in missing_actions: controlflow.expected_argument_exit('assigned_missing_action', ', '.join(missing_actions), sys.argv[i + 1]) i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam sync devices') if not csv_file: controlflow.system_error_exit( 3, 'csvfile is a required argument for "gam sync devices".') f = fileutils.open_file(csv_file) input_file = csv.DictReader(f, restval='') if serialnumber_column not in input_file.fieldnames: controlflow.csv_field_error_exit(serialnumber_column, input_file.fieldnames) if not static_devicetype and devicetype_column not in input_file.fieldnames: controlflow.csv_field_error_exit(devicetype_column, input_file.fieldnames) if assettag_column and assettag_column not in input_file.fieldnames: controlflow.csv_field_error_exit(assettag_column, input_file.fieldnames) local_devices = {} for row in input_file: # upper() is very important to comparison since Google # always return uppercase serials local_device = { 'serialNumber': row[serialnumber_column].strip().upper() } if static_devicetype: local_device['deviceType'] = static_devicetype else: local_device['deviceType'] = row[devicetype_column].strip() sndt = f"{local_device['serialNumber']}-{local_device['deviceType']}" if assettag_column: local_device['assetTag'] = row[assettag_column].strip() sndt += f"-{local_device['assetTag']}" local_devices[sndt] = local_device fileutils.close_file(f) page_message = gapi.got_total_items_msg('Company Devices', '...\n') device_fields = ['serialNumber', 'deviceType', 'lastSyncTime', 'name'] if assettag_column: device_fields.append('assetTag') fields = f'nextPageToken,devices({",".join(device_fields)})' remote_devices = {} remote_device_map = {} result = gapi.get_all_pages(ci.devices(), 'list', 'devices', customer=customer, page_message=page_message, pageSize=100, filter=device_filter, view='COMPANY_INVENTORY', fields=fields) for remote_device in result: sn = remote_device['serialNumber'] last_sync = remote_device.pop('lastSyncTime', NEVER_TIME_NOMS) name = remote_device.pop('name') sndt = f"{remote_device['serialNumber']}-{remote_device['deviceType']}" if assettag_column: if 'assetTag' not in remote_device: remote_device['assetTag'] = '' sndt += f"-{remote_device['assetTag']}" remote_devices[sndt] = remote_device remote_device_map[sndt] = {'name': name} if last_sync == NEVER_TIME_NOMS: remote_device_map[sndt]['unassigned'] = True devices_to_add = [] for sndt, device in iter(local_devices.items()): if sndt not in remote_devices: devices_to_add.append(device) missing_devices = [] for sndt, device in iter(remote_devices.items()): if sndt not in local_devices: missing_devices.append(device) print( f'Need to add {len(devices_to_add)} and remove {len(missing_devices)} devices...' ) for add_device in devices_to_add: print(f'Creating {add_device["serialNumber"]}') try: result = gapi.call( ci.devices(), 'create', customer=customer, throw_reasons=[gapi_errors.ErrorReason.FOUR_O_NINE], body=add_device) print( f' created {result["response"]["deviceType"]} device {result["response"]["name"]} with serial {result["response"]["serialNumber"]}' ) except googleapiclient.errors.HttpError: print(f' {add_device["serialNumber"]} already exists') for missing_device in missing_devices: sn = missing_device['serialNumber'] sndt = f"{sn}-{missing_device['deviceType']}" if assettag_column: sndt += f"-{missing_device['assetTag']}" name = remote_device_map[sndt]['name'] unassigned = remote_device_map[sndt].get('unassigned') action = unassigned_missing_action if unassigned else assigned_missing_action if action == 'donothing': pass else: if action == 'delete': kwargs = {'customer': customer} else: kwargs = {'body': {'customer': customer}} gapi.call(ci.devices(), action, name=name, **kwargs) print(f'{action}d {sn}')
def getEventAttributes(i, calendarId, cal, body, action): # Default to external only so non-Google # calendars are notified of changes sendUpdates = 'externalOnly' action = 'update' if body else 'add' while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg in ['notifyattendees', 'sendnotifications', 'sendupdates']: sendUpdates, i = getSendUpdates(myarg, i, cal) elif myarg == 'attendee': body.setdefault('attendees', []) body['attendees'].append({'email': sys.argv[i + 1]}) i += 2 elif myarg == 'removeattendee' and action == 'update': remove_email = sys.argv[i + 1].lower() if 'attendees' in body: body['attendees'] = _remove_attendee(body['attendees'], remove_email) i += 2 elif myarg == 'optionalattendee': body.setdefault('attendees', []) body['attendees'].append({ 'email': sys.argv[i + 1], 'optional': True }) i += 2 elif myarg == 'anyonecanaddself': body['anyoneCanAddSelf'] = True i += 1 elif myarg == 'description': body['description'] = sys.argv[i + 1].replace('\\n', '\n') i += 2 elif myarg == 'replacedescription' and action == 'update': search = sys.argv[i + 1] replace = sys.argv[i + 2] if 'description' in body: body['description'] = re.sub(search, replace, body['description']) i += 3 elif myarg == 'start': if sys.argv[i + 1].lower() == 'allday': body['start'] = {'date': utils.get_yyyymmdd(sys.argv[i + 2])} i += 3 else: start_time = utils.get_time_or_delta_from_now(sys.argv[i + 1]) body['start'] = {'dateTime': start_time} i += 2 elif myarg == 'end': if sys.argv[i + 1].lower() == 'allday': body['end'] = {'date': utils.get_yyyymmdd(sys.argv[i + 2])} i += 3 else: end_time = utils.get_time_or_delta_from_now(sys.argv[i + 1]) body['end'] = {'dateTime': end_time} i += 2 elif myarg == 'guestscantinviteothers': body['guestsCanInviteOthers'] = False i += 1 elif myarg == 'guestscaninviteothers': body['guestsCanInviteTohters'] = gam.getBoolean( sys.argv[i + 1], 'guestscaninviteothers') i += 2 elif myarg == 'guestscantseeothers': body['guestsCanSeeOtherGuests'] = False i += 1 elif myarg == 'guestscanseeothers': body['guestsCanSeeOtherGuests'] = gam.getBoolean( sys.argv[i + 1], 'guestscanseeothers') i += 2 elif myarg == 'guestscanmodify': body['guestsCanModify'] = gam.getBoolean(sys.argv[i + 1], 'guestscanmodify') i += 2 elif myarg == 'id': if action == 'update': controlflow.invalid_argument_exit( 'id', 'gam calendar <calendar> updateevent') body['id'] = sys.argv[i + 1] i += 2 elif myarg == 'summary': body['summary'] = sys.argv[i + 1] i += 2 elif myarg == 'location': body['location'] = sys.argv[i + 1] i += 2 elif myarg == 'available': body['transparency'] = 'transparent' i += 1 elif myarg == 'transparency': validTransparency = ['opaque', 'transparent'] if sys.argv[i + 1].lower() in validTransparency: body['transparency'] = sys.argv[i + 1].lower() else: controlflow.expected_argument_exit( 'transparency', ", ".join(validTransparency), sys.argv[i + 1]) i += 2 elif myarg == 'visibility': validVisibility = ['default', 'public', 'private'] if sys.argv[i + 1].lower() in validVisibility: body['visibility'] = sys.argv[i + 1].lower() else: controlflow.expected_argument_exit("visibility", ", ".join(validVisibility), sys.argv[i + 1]) i += 2 elif myarg == 'tentative': body['status'] = 'tentative' i += 1 elif myarg == 'status': validStatus = ['confirmed', 'tentative', 'cancelled'] if sys.argv[i + 1].lower() in validStatus: body['status'] = sys.argv[i + 1].lower() else: controlflow.expected_argument_exit('visibility', ', '.join(validStatus), sys.argv[i + 1]) i += 2 elif myarg == 'source': body['source'] = {'title': sys.argv[i + 1], 'url': sys.argv[i + 2]} i += 3 elif myarg == 'noreminders': body['reminders'] = {'useDefault': False} i += 1 elif myarg == 'reminder': minutes = \ gam.getInteger(sys.argv[i+1], myarg, minVal=0, maxVal=CALENDAR_REMINDER_MAX_MINUTES) reminder = {'minutes': minutes, 'method': sys.argv[i + 2]} body.setdefault('reminders', { 'overrides': [], 'useDefault': False }) body['reminders']['overrides'].append(reminder) i += 3 elif myarg == 'recurrence': body.setdefault('recurrence', []) body['recurrence'].append(sys.argv[i + 1]) i += 2 elif myarg == 'timezone': timeZone = sys.argv[i + 1] i += 2 elif myarg == 'privateproperty': if 'extendedProperties' not in body: body['extendedProperties'] = {'private': {}, 'shared': {}} body['extendedProperties']['private'][sys.argv[i + 1]] = sys.argv[i + 2] i += 3 elif myarg == 'sharedproperty': if 'extendedProperties' not in body: body['extendedProperties'] = {'private': {}, 'shared': {}} body['extendedProperties']['shared'][sys.argv[i + 1]] = sys.argv[i + 2] i += 3 elif myarg == 'colorindex': body['colorId'] = gam.getInteger(sys.argv[i + 1], myarg, CALENDAR_EVENT_MIN_COLOR_INDEX, CALENDAR_EVENT_MAX_COLOR_INDEX) i += 2 elif myarg == 'hangoutsmeet': body['conferenceData'] = { 'createRequest': { 'requestId': f'{str(uuid.uuid4())}' } } i += 1 else: controlflow.invalid_argument_exit( sys.argv[i], f'gam calendar <email> {action}event') if ('recurrence' in body) and (('start' in body) or ('end' in body)): if not timeZone: timeZone = gapi.call(cal.calendars(), 'get', calendarId=calendarId, fields='timeZone')['timeZone'] if 'start' in body: body['start']['timeZone'] = timeZone if 'end' in body: body['end']['timeZone'] = timeZone return (sendUpdates, body)
def getCalendarAttributes(i, body, function): colorRgbFormat = False while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'selected': body['selected'] = gam.getBoolean(sys.argv[i + 1], myarg) i += 2 elif myarg == 'hidden': body['hidden'] = gam.getBoolean(sys.argv[i + 1], myarg) i += 2 elif myarg == 'summary': body['summaryOverride'] = sys.argv[i + 1] i += 2 elif myarg == 'colorindex': body['colorId'] = gam.getInteger(sys.argv[i + 1], myarg, minVal=CALENDAR_MIN_COLOR_INDEX, maxVal=CALENDAR_MAX_COLOR_INDEX) i += 2 elif myarg == 'backgroundcolor': body['backgroundColor'] = gam.getColor(sys.argv[i + 1]) colorRgbFormat = True i += 2 elif myarg == 'foregroundcolor': body['foregroundColor'] = gam.getColor(sys.argv[i + 1]) colorRgbFormat = True i += 2 elif myarg == 'reminder': body.setdefault('defaultReminders', []) method = sys.argv[i + 1].lower() if method not in CLEAR_NONE_ARGUMENT: if method not in CALENDAR_REMINDER_METHODS: controlflow.expected_argument_exit( "Method", ", ".join(CALENDAR_REMINDER_METHODS + CLEAR_NONE_ARGUMENT), method) minutes = gam.getInteger(sys.argv[i + 2], myarg, minVal=0, maxVal=CALENDAR_REMINDER_MAX_MINUTES) body['defaultReminders'].append({ 'method': method, 'minutes': minutes }) i += 3 else: i += 2 elif myarg == 'notification': body.setdefault('notificationSettings', {'notifications': []}) method = sys.argv[i + 1].lower() if method not in CLEAR_NONE_ARGUMENT: if method not in CALENDAR_NOTIFICATION_METHODS: controlflow.expected_argument_exit( "Method", ", ".join(CALENDAR_NOTIFICATION_METHODS + CLEAR_NONE_ARGUMENT), method) eventType = sys.argv[i + 2].lower() if eventType not in CALENDAR_NOTIFICATION_TYPES_MAP: controlflow.expected_argument_exit( "Event", ", ".join(CALENDAR_NOTIFICATION_TYPES_MAP), eventType) notice = { 'method': method, 'type': CALENDAR_NOTIFICATION_TYPES_MAP[eventType] } body['notificationSettings']['notifications'].append(notice) i += 3 else: i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], f"gam {function} calendar") return colorRgbFormat
def print_(): '''gam print userinvitations''' svc = gapi_cloudidentity.build_dwd('cloudidentity_beta') customer = _get_customerid() todrive = False titles = ['name', 'state', 'updateTime'] rows = [] filter_ = None orderByList = [] i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'state': state = sys.argv[i + 1].lower().replace('_', '') if state in USERINVITATION_STATE_CHOICES_MAP: filter_ = f"state=='{USERINVITATION_STATE_CHOICES_MAP[state]}'" else: controlflow.expected_argument_exit( 'state', ', '.join(USERINVITATION_STATE_CHOICES_MAP), state) i += 2 elif myarg == 'orderby': fieldName = sys.argv[i + 1].lower() i += 2 if fieldName in USERINVITATION_ORDERBY_CHOICES_MAP: fieldName = USERINVITATION_ORDERBY_CHOICES_MAP[fieldName] orderBy = '' if i < len(sys.argv): orderBy = sys.argv[i].lower() if orderBy in SORTORDER_CHOICES_MAP: orderBy = SORTORDER_CHOICES_MAP[orderBy] i += 1 if orderBy != 'DESCENDING': orderByList.append(fieldName) else: orderByList.append(f'{fieldName} desc') else: controlflow.expected_argument_exit( 'orderby', ', '.join(sorted(USERINVITATION_ORDERBY_CHOICES_MAP)), fieldName) elif myarg == 'todrive': todrive = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam print userinvitations') if orderByList: orderBy = ' '.join(orderByList) else: orderBy = None gam.printGettingAllItems('User Invitations', filter_) page_message = gapi.got_total_items_msg('User Invitations', '...\n') invitations = gapi.get_all_pages(svc.customers().userinvitations(), 'list', 'userInvitations', page_message=page_message, parent=customer, filter=filter_, orderBy=orderBy) for invitation in invitations: invitation['name'] = _reduce_name(invitation['name']) row = {} for key, val in invitation.items(): if key not in titles: titles.append(key) row[key] = val rows.append(row) display.write_csv_file(rows, titles, 'User Invitations', todrive)
def printHistory(): cv = build() entityType = sys.argv[3].lower().replace('_', '') if entityType not in CHROME_HISTORY_ENTITY_CHOICES: msg = f'{entityType} is not a valid argument to "gam print chromehistory"' controlflow.system_error_exit(3, msg) todrive = False csvRows = [] cplatform = 'all' channel = 'all' version = 'all' kwargs = {} orderByList = [] i = 4 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'todrive': todrive = True i += 1 elif entityType != 'platforms' and myarg == 'platform': cplatform = sys.argv[i + 1].lower().replace('_', '') platform_map = get_platform_map(cv) if cplatform not in platform_map: controlflow.expected_argument_exit('platform', ', '.join(platform_map), cplatform) cplatform = platform_map[cplatform] i += 2 elif entityType in {'versions', 'releases'} and myarg == 'channel': channel = sys.argv[i + 1].lower().replace('_', '') channel_map = get_channel_map(cv) if channel not in channel_map: controlflow.expected_argument_exit('channel', ', '.join(channel_map), channel) channel = channel_map[channel] i += 2 elif entityType == 'releases' and myarg == 'version': version = sys.argv[i + 1] i += 2 elif entityType in {'versions', 'releases'} and myarg == 'orderby': fieldName = sys.argv[i + 1].lower().replace('_', '') i += 2 if fieldName in CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[ entityType]: fieldName = CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[ entityType][fieldName] orderBy = '' if i < len(sys.argv): orderBy = sys.argv[i].lower() if orderBy in SORTORDER_CHOICES_MAP: orderBy = SORTORDER_CHOICES_MAP[orderBy] i += 1 if orderBy != 'DESCENDING': orderByList.append(fieldName) else: orderByList.append(f'{fieldName} desc') else: controlflow.expected_argument_exit( 'orderby', ', '.join( CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType]), fieldName) elif entityType in {'versions', 'releases'} and myarg == 'filter': kwargs['filter'] = sys.argv[i + 1] i += 2 else: msg = f'{myarg} is not a valid argument to "gam print chromehistory {entityType}"' controlflow.system_error_exit(3, msg) if orderByList: kwargs['orderBy'] = ','.join(orderByList) if entityType == 'platforms': svc = cv.platforms() parent = 'chrome' elif entityType == 'channels': svc = cv.platforms().channels() parent = f'chrome/platforms/{cplatform}' elif entityType == 'versions': svc = cv.platforms().channels().versions() parent = f'chrome/platforms/{cplatform}/channels/{channel}' else: #elif entityType == 'releases' svc = cv.platforms().channels().versions().releases() parent = f'chrome/platforms/{cplatform}/channels/{channel}/versions/{version}' reportTitle = f'Chrome Version History {entityType.capitalize()}' page_message = gapi.got_total_items_msg(reportTitle, '...\n') gam.printGettingAllItems(reportTitle, None) citems = gapi.get_all_pages(svc, 'list', entityType, page_message=page_message, parent=parent, fields=f'nextPageToken,{entityType}', **kwargs) for citem in citems: for key in list(citem): if key.endswith('Type'): newkey = key[:-4] citem[newkey] = citem.pop(key) if 'channel' in citem: citem['channel'] = citem['channel'].lower() else: channel_match = re.search(r'\/channels\/([^/]*)', citem['name']) if channel_match: try: citem['channel'] = channel_match.group(1) except IndexError: pass if 'platform' in citem: citem['platform'] = citem['platform'].lower() else: platform_match = re.search(r'\/platforms\/([^/]*)', citem['name']) if platform_match: try: citem['platform'] = platform_match.group(1) except IndexError: pass if citem.get('version', '').count('.') == 3: citem['major_version'], \ citem['minor_version'], \ citem['build'], \ citem['patch'] = citem['version'].split('.') citem.pop('name') csvRows.append(utils.flatten_json(citem)) display.write_csv_file(csvRows, CHROME_VERSIONHISTORY_TITLES[entityType], reportTitle, todrive)
def createExport(): v = buildGAPIObject() allowed_corpuses = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['Query']['properties']['corpus']['enum']) allowed_scopes = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['Query']['properties']['dataScope']['enum']) allowed_formats = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['MailExportOptions']['properties'] ['exportFormat']['enum']) export_format = 'MBOX' showConfidentialModeContent = None # default to not even set matterId = None body = {'query': {'dataScope': 'ALL_DATA'}, 'exportOptions': {}} i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'matter': matterId = getMatterItem(v, sys.argv[i + 1]) body['matterId'] = matterId i += 2 elif myarg == 'name': body['name'] = sys.argv[i + 1] i += 2 elif myarg == 'corpus': body['query']['corpus'] = sys.argv[i + 1].upper() if body['query']['corpus'] not in allowed_corpuses: controlflow.expected_argument_exit('corpus', ', '.join(allowed_corpuses), sys.argv[i + 1]) i += 2 elif myarg in VAULT_SEARCH_METHODS_MAP: if body['query'].get('searchMethod'): message = f'Multiple search methods ' \ f'({", ".join(VAULT_SEARCH_METHODS_LIST)})' \ f'specified, only one is allowed' controlflow.system_error_exit(3, message) searchMethod = VAULT_SEARCH_METHODS_MAP[myarg] body['query']['searchMethod'] = searchMethod if searchMethod == 'ACCOUNT': body['query']['accountInfo'] = { 'emails': sys.argv[i + 1].split(',') } i += 2 elif searchMethod == 'ORG_UNIT': body['query']['orgUnitInfo'] = { 'orgUnitId': gam.getOrgUnitId(sys.argv[i + 1])[1] } i += 2 elif searchMethod == 'SHARED_DRIVE': body['query']['sharedDriveInfo'] = { 'sharedDriveIds': sys.argv[i + 1].split(',') } i += 2 elif searchMethod == 'ROOM': body['query']['hangoutsChatInfo'] = { 'roomId': sys.argv[i + 1].split(',') } i += 2 else: i += 1 elif myarg == 'scope': body['query']['dataScope'] = sys.argv[i + 1].upper() if body['query']['dataScope'] not in allowed_scopes: controlflow.expected_argument_exit('scope', ', '.join(allowed_scopes), sys.argv[i + 1]) i += 2 elif myarg in ['terms']: body['query']['terms'] = sys.argv[i + 1] i += 2 elif myarg in ['start', 'starttime']: body['query']['startTime'] = utils.get_date_zero_time_or_full_time( sys.argv[i + 1]) i += 2 elif myarg in ['end', 'endtime']: body['query']['endTime'] = utils.get_date_zero_time_or_full_time( sys.argv[i + 1]) i += 2 elif myarg in ['timezone']: body['query']['timeZone'] = sys.argv[i + 1] i += 2 elif myarg in ['excludedrafts']: body['query']['mailOptions'] = { 'excludeDrafts': gam.getBoolean(sys.argv[i + 1], myarg) } i += 2 elif myarg in ['driveversiondate']: body['query'].setdefault('driveOptions', {})['versionDate'] = \ utils.get_date_zero_time_or_full_time(sys.argv[i+1]) i += 2 elif myarg in ['includeshareddrives', 'includeteamdrives']: body['query'].setdefault( 'driveOptions', {})['includeSharedDrives'] = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 elif myarg in ['includerooms']: body['query']['hangoutsChatOptions'] = { 'includeRooms': gam.getBoolean(sys.argv[i + 1], myarg) } i += 2 elif myarg in ['format']: export_format = sys.argv[i + 1].upper() if export_format not in allowed_formats: controlflow.expected_argument_exit('export format', ', '.join(allowed_formats), export_format) i += 2 elif myarg in ['showconfidentialmodecontent']: showConfidentialModeContent = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 elif myarg in ['region']: allowed_regions = gapi.get_enum_values_minus_unspecified( v._rootDesc['schemas']['ExportOptions']['properties']['region'] ['enum']) body['exportOptions']['region'] = sys.argv[i + 1].upper() if body['exportOptions']['region'] not in allowed_regions: controlflow.expected_argument_exit( 'region', ', '.join(allowed_regions), body['exportOptions']['region']) i += 2 elif myarg in ['includeaccessinfo']: body['exportOptions'].setdefault( 'driveOptions', {})['includeAccessInfo'] = gam.getBoolean( sys.argv[i + 1], myarg) i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam create export') if not matterId: controlflow.system_error_exit( 3, 'you must specify a matter for the new export.') if 'corpus' not in body['query']: controlflow.system_error_exit(3, f'you must specify a corpus for the ' \ f'new export. Choose one of {", ".join(allowed_corpuses)}') if 'searchMethod' not in body['query']: controlflow.system_error_exit(3, f'you must specify a search method ' \ 'for the new export. Choose one of ' \ f'{", ".join(VAULT_SEARCH_METHODS_LIST)}') if 'name' not in body: corpus_name = body['query']['corpus'] corpus_date = datetime.datetime.now() body['name'] = f'GAM {corpus_name} export - {corpus_date}' options_field = None if body['query']['corpus'] == 'MAIL': options_field = 'mailOptions' elif body['query']['corpus'] == 'GROUPS': options_field = 'groupsOptions' elif body['query']['corpus'] == 'HANGOUTS_CHAT': options_field = 'hangoutsChatOptions' if options_field: body['exportOptions'].pop('driveOptions', None) body['exportOptions'][options_field] = {'exportFormat': export_format} if showConfidentialModeContent is not None: body['exportOptions'][options_field][ 'showConfidentialModeContent'] = showConfidentialModeContent results = gapi.call(v.matters().exports(), 'create', matterId=matterId, body=body) print(f'Created export {results["id"]}') display.print_json(results)
def update_state(): ci = gapi_cloudidentity.build_dwd() gapi_directory_customer.setTrueCustomerId() customer = _get_device_customerid() customer_id = customer[10:] client_id = f'{customer_id}-gam' body = {} i, deviceuser = _get_deviceuser_name() while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'clientid': client_id = f'{customer_id}-{sys.argv[i+1]}' i += 2 elif myarg in ['assettag', 'assettags']: body['assetTags'] = gam.shlexSplitList(sys.argv[i + 1]) if body['assetTags'] == ['clear']: # TODO: this doesn't work to clear # existing values. Figure out why. body['assetTags'] = [None] i += 2 elif myarg in ['compliantstate', 'compliancestate']: comp_states = gapi.get_enum_values_minus_unspecified( ci._rootDesc['schemas'] ['GoogleAppsCloudidentityDevicesV1ClientState']['properties'] ['complianceState']['enum']) body['complianceState'] = sys.argv[i + 1].upper() if body['complianceState'] not in comp_states: controlflow.expected_argument_exit('compliant_state', ', '.join(comp_states), sys.argv[i + 1]) i += 2 elif myarg == 'customid': body['customId'] = sys.argv[i + 1] i += 2 elif myarg == 'healthscore': health_scores = gapi.get_enum_values_minus_unspecified( ci._rootDesc['schemas'] ['GoogleAppsCloudidentityDevicesV1ClientState']['properties'] ['healthScore']['enum']) body['healthScore'] = sys.argv[i + 1].upper() if body['healthScore'] == 'CLEAR': body['healthScore'] = None if body['healthScore'] and body['healthScore'] not in health_scores: controlflow.expected_argument_exit('health_score', ', '.join(health_scores), sys.argv[i + 1]) i += 2 elif myarg == 'customvalue': allowed_types = ['bool', 'number', 'string'] value_type = sys.argv[i + 1].lower() if value_type not in allowed_types: controlflow.expected_argument_exit('custom_value', ', '.join(allowed_types), sys.argv[i + 1]) key = sys.argv[i + 2] value = sys.argv[i + 3] if value_type == 'bool': value = gam.getBoolean(value, key) elif value_type == 'number': value = int(value) body.setdefault('keyValuePairs', {}) body['keyValuePairs'][key] = {f'{value_type}Value': value} i += 4 elif myarg in ['managedstate']: managed_states = gapi.get_enum_values_minus_unspecified( ci._rootDesc['schemas'] ['GoogleAppsCloudidentityDevicesV1ClientState']['properties'] ['managed']['enum']) body['managed'] = sys.argv[i + 1].upper() if body['managed'] == 'CLEAR': body['managed'] = None if body['managed'] and body['managed'] not in managed_states: controlflow.expected_argument_exit('managed_state', ', '.join(managed_states), sys.argv[i + 1]) i += 2 elif myarg in ['scorereason']: body['scoreReason'] = sys.argv[i + 1] if body['scoreReason'] == 'clear': body['scoreReason'] = None i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam update deviceuserstate') name = f'{deviceuser}/clientStates/{client_id}' updateMask = ','.join(body.keys()) result = gapi.call(ci.devices().deviceUsers().clientStates(), 'patch', name=name, customer=customer, updateMask=updateMask, body=body) display.print_json(result)
def showUsage(): rep = build() throw_reasons = [ gapi.errors.ErrorReason.INVALID, gapi.errors.ErrorReason.BAD_REQUEST ] todrive = False if len(sys.argv) == 3: controlflow.missing_argument_exit('user or customer', 'report usage') report = sys.argv[3].lower() titles = ['date'] if report == 'customer': endpoint = rep.customerUsageReports() kwargs = [{}] elif report == 'user': endpoint = rep.userUsageReport() kwargs = [{'userKey': 'all'}] titles.append('user') else: controlflow.expected_argument_exit('usage', ['user', 'customer'], report) customerId = GC_Values[GC_CUSTOMER_ID] if customerId == MY_CUSTOMER: customerId = None parameters = [] start_date = end_date = orgUnitId = None skip_day_numbers = [] skip_dates = set() one_day = datetime.timedelta(days=1) i = 4 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'startdate': start_date = utils.get_yyyymmdd(sys.argv[i + 1], returnDateTime=True) i += 2 elif myarg == 'enddate': end_date = utils.get_yyyymmdd(sys.argv[i + 1], returnDateTime=True) i += 2 elif myarg == 'todrive': todrive = True i += 1 elif myarg in ['fields', 'parameters']: parameters = sys.argv[i + 1].split(',') i += 2 elif myarg == 'skipdates': for skip in sys.argv[i + 1].split(','): if skip.find(':') == -1: skip_dates.add( utils.get_yyyymmdd(skip, returnDateTime=True)) else: skip_start, skip_end = skip.split(':', 1) skip_start = utils.get_yyyymmdd(skip_start, returnDateTime=True) skip_end = utils.get_yyyymmdd(skip_end, returnDateTime=True) while skip_start <= skip_end: skip_dates.add(skip_start) skip_start += one_day i += 2 elif myarg == 'skipdaysofweek': skipdaynames = sys.argv[i + 1].split(',') dow = [d.lower() for d in calendar.day_abbr] skip_day_numbers = [dow.index(d) for d in skipdaynames if d in dow] i += 2 elif report == 'user' and myarg in ['orgunit', 'org', 'ou']: _, orgUnitId = gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1]) i += 2 elif report == 'user' and myarg in usergroup_types: users = gam.getUsersToModify(myarg, sys.argv[i + 1]) kwargs = [{'userKey': user} for user in users] i += 2 else: controlflow.invalid_argument_exit(sys.argv[i], f'gam report usage {report}') if parameters: titles.extend(parameters) parameters = ','.join(parameters) else: parameters = None if not end_date: end_date = datetime.datetime.now() if not start_date: start_date = end_date + relativedelta(months=-1) if orgUnitId: for kw in kwargs: kw['orgUnitID'] = orgUnitId usage_on_date = start_date start_date = usage_on_date.strftime(YYYYMMDD_FORMAT) usage_end_date = end_date end_date = end_date.strftime(YYYYMMDD_FORMAT) start_use_date = end_use_date = None csvRows = [] while usage_on_date <= usage_end_date: if usage_on_date.weekday() in skip_day_numbers or \ usage_on_date in skip_dates: usage_on_date += one_day continue use_date = usage_on_date.strftime(YYYYMMDD_FORMAT) usage_on_date += one_day try: for kwarg in kwargs: try: usage = gapi.get_all_pages(endpoint, 'get', 'usageReports', throw_reasons=throw_reasons, customerId=customerId, date=use_date, parameters=parameters, **kwarg) except gapi.errors.GapiBadRequestError: continue for entity in usage: row = {'date': use_date} if 'userEmail' in entity['entity']: row['user'] = entity['entity']['userEmail'] for item in entity.get('parameters', []): if 'name' not in item: continue name = item['name'] if name == 'cros:device_version_distribution': for cros_ver in item['msgValue']: v = cros_ver['version_number'] column_name = f'cros:num_devices_chrome_{v}' if column_name not in titles: titles.append(column_name) row[column_name] = cros_ver['num_devices'] else: if not name in titles: titles.append(name) for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES: if ptype in item: row[name] = item[ptype] break else: row[name] = '' if not start_use_date: start_use_date = use_date end_use_date = use_date csvRows.append(row) except gapi.errors.GapiInvalidError as e: display.print_warning(str(e)) break if start_use_date: report_name = f'{report.capitalize()} Usage Report - {start_use_date}:{end_use_date}' else: report_name = f'{report.capitalize()} Usage Report - {start_date}:{end_date} - No Data' display.write_csv_file(csvRows, titles, report_name, todrive)
def print_(): ci = gapi_cloudidentity.build_dwd() customer = _get_device_customerid() parent = 'devices/-' device_filter = None get_device_users = True view = None orderByList = [] titles = [] csvRows = [] todrive = False sortHeaders = False i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg in ['filter', 'query']: device_filter = sys.argv[i + 1] i += 2 elif myarg == 'company': view = 'COMPANY_INVENTORY' i += 1 elif myarg == 'personal': view = 'USER_ASSIGNED_DEVICES' i += 1 elif myarg == 'nocompanydevices': view = 'USER_ASSIGNED_DEVICES' i += 1 elif myarg == 'nopersonaldevices': view = 'COMPANY_INVENTORY' i += 1 elif myarg == 'nodeviceusers': get_device_users = False i += 1 elif myarg == 'todrive': todrive = True i += 1 elif myarg == 'orderby': fieldName = sys.argv[i + 1].lower() i += 2 if fieldName in DEVICE_ORDERBY_CHOICES_MAP: fieldName = DEVICE_ORDERBY_CHOICES_MAP[fieldName] orderBy = '' if i < len(sys.argv): orderBy = sys.argv[i].lower() if orderBy in SORTORDER_CHOICES_MAP: orderBy = SORTORDER_CHOICES_MAP[orderBy] i += 1 if orderBy != 'DESCENDING': orderByList.append(fieldName) else: orderByList.append(f'{fieldName} desc') else: controlflow.expected_argument_exit( 'orderby', ', '.join(sorted(DEVICE_ORDERBY_CHOICES_MAP)), fieldName) elif myarg == 'sortheaders': sortHeaders = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam print devices') view_name_map = { None: 'Devices', 'COMPANY_INVENTORY': 'Company Devices', 'USER_ASSIGNED_DEVICES': 'Personal Devices', } if orderByList: orderBy = ','.join(orderByList) else: orderBy = None devices = [] page_message = gapi.got_total_items_msg(view_name_map[view], '...\n') devices += gapi.get_all_pages(ci.devices(), 'list', 'devices', customer=customer, page_message=page_message, pageSize=100, filter=device_filter, view=view, orderBy=orderBy) if get_device_users: page_message = gapi.got_total_items_msg('Device Users', '...\n') device_users = gapi.get_all_pages(ci.devices().deviceUsers(), 'list', 'deviceUsers', customer=customer, parent=parent, page_message=page_message, pageSize=20, filter=device_filter) for device_user in device_users: for device in devices: if device_user.get('name').startswith(device.get('name')): if 'users' not in device: device['users'] = [] device['users'].append(device_user) break for device in devices: device = utils.flatten_json(device) for a_key in device: if a_key not in titles: titles.append(a_key) csvRows.append(device) if sortHeaders: display.sort_csv_titles([ 'name', ], titles) display.write_csv_file(csvRows, titles, 'Devices', todrive)
def showReport(): rep = build() throw_reasons = [gapi.errors.ErrorReason.INVALID] report = sys.argv[2].lower() report = REPORT_CHOICE_MAP.get(report.replace('_', ''), report) if report == 'usage': showUsage() return if report == 'usageparameters': showUsageParameters() return valid_apps = gapi.get_enum_values_minus_unspecified( rep._rootDesc['resources']['activities']['methods']['list'] ['parameters']['applicationName']['enum']) + ['customer', 'user'] if report not in valid_apps: controlflow.expected_argument_exit('report', ', '.join(sorted(valid_apps)), report) customerId = GC_Values[GC_CUSTOMER_ID] if customerId == MY_CUSTOMER: customerId = None filters = parameters = actorIpAddress = groupIdFilter = startTime = endTime = eventName = orgUnitId = None tryDate = datetime.date.today().strftime(YYYYMMDD_FORMAT) to_drive = False userKey = 'all' fullDataRequired = None i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower() if myarg == 'date': tryDate = utils.get_yyyymmdd(sys.argv[i + 1]) i += 2 elif myarg in ['orgunit', 'org', 'ou']: _, orgUnitId = gapi_directory_orgunits.getOrgUnitId(sys.argv[i + 1]) i += 2 elif myarg == 'fulldatarequired': fullDataRequired = [] fdr = sys.argv[i + 1].lower() if fdr and fdr == 'all': fullDataRequired = 'all' else: fullDataRequired = fdr.replace(',', ' ').split() i += 2 elif myarg == 'start': startTime = utils.get_time_or_delta_from_now(sys.argv[i + 1]) i += 2 elif myarg == 'end': endTime = utils.get_time_or_delta_from_now(sys.argv[i + 1]) i += 2 elif myarg == 'event': eventName = sys.argv[i + 1] i += 2 elif myarg == 'user': userKey = sys.argv[i + 1].lower() if userKey != 'all': userKey = gam.normalizeEmailAddressOrUID(sys.argv[i + 1]) i += 2 elif myarg in ['filter', 'filters']: filters = sys.argv[i + 1] i += 2 elif myarg in ['fields', 'parameters']: parameters = sys.argv[i + 1] i += 2 elif myarg == 'ip': actorIpAddress = sys.argv[i + 1] i += 2 elif myarg == 'groupidfilter': groupIdFilter = sys.argv[i + 1] i += 2 elif myarg == 'todrive': to_drive = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam report') if report == 'user': while True: try: one_page = gapi.call(rep.userUsageReport(), 'get', throw_reasons=throw_reasons, date=tryDate, userKey=userKey, customerId=customerId, orgUnitID=orgUnitId, fields='warnings,usageReports', maxResults=1) warnings = one_page.get('warnings', []) has_reports = bool(one_page.get('usageReports')) fullData, tryDate = _check_full_data_available( warnings, tryDate, fullDataRequired, has_reports) if fullData < 0: print('No user report available.') sys.exit(1) if fullData == 0: continue page_message = gapi.got_total_items_msg('Users', '...\n') usage = gapi.get_all_pages(rep.userUsageReport(), 'get', 'usageReports', page_message=page_message, throw_reasons=throw_reasons, date=tryDate, userKey=userKey, customerId=customerId, orgUnitID=orgUnitId, filters=filters, parameters=parameters) break except gapi.errors.GapiInvalidError as e: tryDate = _adjust_date(str(e)) if not usage: print('No user report available.') sys.exit(1) titles = ['email', 'date'] csvRows = [] for user_report in usage: if 'entity' not in user_report: continue row = { 'email': user_report['entity']['userEmail'], 'date': tryDate } for item in user_report.get('parameters', []): if 'name' not in item: continue name = item['name'] if not name in titles: titles.append(name) for ptype in REPORTS_PARAMETERS_SIMPLE_TYPES: if ptype in item: row[name] = item[ptype] break else: row[name] = '' csvRows.append(row) display.write_csv_file(csvRows, titles, f'User Reports - {tryDate}', to_drive) elif report == 'customer': while True: try: first_page = gapi.call(rep.customerUsageReports(), 'get', throw_reasons=throw_reasons, customerId=customerId, date=tryDate, fields='warnings,usageReports') warnings = first_page.get('warnings', []) has_reports = bool(first_page.get('usageReports')) fullData, tryDate = _check_full_data_available( warnings, tryDate, fullDataRequired, has_reports) if fullData < 0: print('No customer report available.') sys.exit(1) if fullData == 0: continue usage = gapi.get_all_pages(rep.customerUsageReports(), 'get', 'usageReports', throw_reasons=throw_reasons, customerId=customerId, date=tryDate, parameters=parameters) break except gapi.errors.GapiInvalidError as e: tryDate = _adjust_date(str(e)) if not usage: print('No customer report available.') sys.exit(1) titles = ['name', 'value', 'client_id'] csvRows = [] auth_apps = list() for item in usage[0]['parameters']: if 'name' not in item: continue name = item['name'] if 'intValue' in item: value = item['intValue'] elif 'msgValue' in item: if name == 'accounts:authorized_apps': for subitem in item['msgValue']: app = {} for an_item in subitem: if an_item == 'client_name': app['name'] = 'App: ' + \ subitem[an_item].replace('\n', '\\n') elif an_item == 'num_users': app['value'] = f'{subitem[an_item]} users' elif an_item == 'client_id': app['client_id'] = subitem[an_item] auth_apps.append(app) continue values = [] for subitem in item['msgValue']: if 'count' in subitem: mycount = myvalue = None for key, value in list(subitem.items()): if key == 'count': mycount = value else: myvalue = value if mycount and myvalue: values.append(f'{myvalue}:{mycount}') value = ' '.join(values) elif 'version_number' in subitem \ and 'num_devices' in subitem: values.append(f'{subitem["version_number"]}:' f'{subitem["num_devices"]}') else: continue value = ' '.join(sorted(values, reverse=True)) csvRows.append({'name': name, 'value': value}) for app in auth_apps: # put apps at bottom csvRows.append(app) display.write_csv_file(csvRows, titles, f'Customer Report - {tryDate}', todrive=to_drive) else: page_message = gapi.got_total_items_msg('Activities', '...\n') activities = gapi.get_all_pages(rep.activities(), 'list', 'items', page_message=page_message, applicationName=report, userKey=userKey, customerId=customerId, actorIpAddress=actorIpAddress, startTime=startTime, endTime=endTime, eventName=eventName, filters=filters, orgUnitID=orgUnitId, groupIdFilter=groupIdFilter) if activities: titles = ['name'] csvRows = [] for activity in activities: events = activity['events'] del activity['events'] activity_row = utils.flatten_json(activity) purge_parameters = True for event in events: for item in event.get('parameters', []): if set(item) == {'value', 'name'}: event[item['name']] = item['value'] elif set(item) == {'intValue', 'name'}: if item['name'] in ['start_time', 'end_time']: val = item.get('intValue') if val is not None: val = int(val) if val >= 62135683200: event[item['name']] = \ datetime.datetime.fromtimestamp( val-62135683200).isoformat() else: event[item['name']] = item['intValue'] elif set(item) == {'boolValue', 'name'}: event[item['name']] = item['boolValue'] elif set(item) == {'multiValue', 'name'}: event[item['name']] = ' '.join(item['multiValue']) elif item['name'] == 'scope_data': parts = {} for message in item['multiMessageValue']: for mess in message['parameter']: value = mess.get( 'value', ' '.join(mess.get('multiValue', []))) parts[mess['name']] = parts.get( mess['name'], []) + [value] for part, v in parts.items(): if part == 'scope_name': part = 'scope' event[part] = ' '.join(v) else: purge_parameters = False if purge_parameters: event.pop('parameters', None) row = utils.flatten_json(event) row.update(activity_row) for item in row: if item not in titles: titles.append(item) csvRows.append(row) display.sort_csv_titles([ 'name', ], titles) display.write_csv_file(csvRows, titles, f'{report.capitalize()} Activity Report', to_drive)
def update(): cd = gapi_directory.build resourceIds = sys.argv[3] match_users = None doit = False if resourceIds[:6] == 'query:': query = resourceIds[6:] fields = 'nextPageToken,mobiledevices(resourceId,email)' page_message = gapi.got_total_items_msg('Mobile Devices', '...\n') devices = gapi.get_all_pages(cd.mobiledevices(), 'list', page_message=page_message, customerId=GC_Values[GC_CUSTOMER_ID], items='mobiledevices', query=query, fields=fields) else: devices = [{'resourceId': resourceIds, 'email': ['not set']}] doit = True i = 4 body = {} while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'action': body['action'] = sys.argv[i + 1].lower() validActions = [ 'wipe', 'wipeaccount', 'accountwipe', 'wipe_account', 'account_wipe', 'approve', 'block', 'cancel_remote_wipe_then_activate', 'cancel_remote_wipe_then_block' ] if body['action'] not in validActions: controlflow.expected_argument_exit('action', ', '.join(validActions), body['action']) if body['action'] == 'wipe': body['action'] = 'admin_remote_wipe' elif body['action'].replace('_', '') in ['accountwipe', 'wipeaccount']: body['action'] = 'admin_account_wipe' i += 2 elif myarg in ['ifusers', 'matchusers']: match_users = gam.getUsersToModify(entity_type=sys.argv[i + 1].lower(), entity=sys.argv[i + 2]) i += 3 elif myarg == 'doit': doit = True i += 1 else: controlflow.invalid_argument_exit(sys.argv[i], 'gam update mobile') if body: if doit: print(f'Updating {len(devices)} devices') describe_as = 'Performing' else: print( f'Showing {len(devices)} changes that would be made, not actually making changes because doit argument not specified' ) describe_as = 'Would perform' for device in devices: device_user = device.get('email', [''])[0] if match_users and device_user not in match_users: print( f'Skipping device for user {device_user} that did not match match_users argument' ) else: print( f'{describe_as} {body["action"]} on user {device_user} device {device["resourceId"]}' ) if doit: gapi.call(cd.mobiledevices(), 'action', resourceId=device['resourceId'], body=body, customerId=GC_Values[GC_CUSTOMER_ID])
def printAppDevices(): cm = build() customer = _get_customerid() todrive = False titles = CHROME_APP_DEVICES_TITLES csvRows = [] orgunit = None appId = None appType = None startDate = None endDate = None pfilter = None orderBy = None i = 3 while i < len(sys.argv): myarg = sys.argv[i].lower().replace('_', '') if myarg == 'todrive': todrive = True i += 1 elif myarg in ['ou', 'org', 'orgunit']: orgunit = _get_orgunit(sys.argv[i + 1]) i += 2 elif myarg == 'appid': appId = sys.argv[i + 1] i += 2 elif myarg == 'apptype': appType = sys.argv[i + 1].lower().replace('_', '') if appType not in CHROME_APP_DEVICES_APPTYPE_CHOICE_MAP: controlflow.expected_argument_exit( 'orderby', ', '.join(CHROME_APP_DEVICES_APPTYPE_CHOICE_MAP), appType) appType = CHROME_APP_DEVICES_APPTYPE_CHOICE_MAP[appType] i += 2 elif myarg in CROS_START_ARGUMENTS: startDate = _getFilterDate(sys.argv[i + 1]).strftime(YYYYMMDD_FORMAT) i += 2 elif myarg in CROS_END_ARGUMENTS: endDate = _getFilterDate(sys.argv[i + 1]).strftime(YYYYMMDD_FORMAT) i += 2 elif myarg == 'orderby': orderBy = sys.argv[i + 1].lower().replace('_', '') if orderBy not in CHROME_APP_DEVICES_ORDERBY_CHOICE_MAP: controlflow.expected_argument_exit( 'orderby', ', '.join(CHROME_APP_DEVICES_ORDERBY_CHOICE_MAP), orderBy) orderBy = CHROME_APP_DEVICES_ORDERBY_CHOICE_MAP[orderBy] i += 2 else: msg = f'{myarg} is not a valid argument to "gam print chromeappdevices"' controlflow.system_error_exit(3, msg) if not appId: controlflow.system_error_exit(3, 'You must specify an appid') if not appType: controlflow.system_error_exit(3, 'You must specify an apptype') if endDate: pfilter = f'last_active_date<={endDate}' if startDate: if pfilter: pfilter += ' AND ' else: pfilter = '' pfilter += f'last_active_date>={startDate}' if orgunit: orgUnitPath = gapi_directory_orgunits.orgunit_from_orgunitid( orgunit, None) titles.append('orgUnitPath') else: orgUnitPath = '/' gam.printGettingAllItems('Chrome Installed Application Devices', pfilter) page_message = gapi.got_total_items_msg( 'Chrome Installed Application Devices', '...\n') devices = gapi.get_all_pages(cm.customers().reports(), 'findInstalledAppDevices', 'devices', page_message=page_message, appId=appId, appType=appType, customer=customer, orgUnitId=orgunit, filter=pfilter, orderBy=orderBy) for device in devices: if orgunit: device['orgUnitPath'] = orgUnitPath device['appId'] = appId device['appType'] = appType csvRows.append(device) display.write_csv_file(csvRows, titles, 'Chrome Installed Application Devices', todrive)