Example #1
0
def print_():
    cbcm = build()
    customer_id = _get_customerid()
    projection = 'BASIC'
    orgUnitPath = query = None
    fields = None
    titles = []
    csv_rows = []
    todrive = False
    sort_headers = False
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'query':
            query = sys.argv[i + 1]
            i += 2
        elif myarg in ['ou', 'org', 'orgunit']:
            orgUnitPath = gapi_directory_orgunits.getOrgUnitItem(
                sys.argv[i + 1], pathOnly=True, absolutePath=True)
            i += 2
        elif myarg == 'projection':
            projection = sys.argv[i + 1].upper()
            i += 2
        elif myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'sortheaders':
            sort_headers = True
            i += 1
        elif myarg == 'fields':
            fields = sys.argv[i + 1].replace(',', ' ').split()
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print browsers')
    if fields:
        fields.append('deviceId')
        fields = f'browsers({",".join(set(fields))}),nextPageToken'
    page_message = gapi.got_total_items_msg('Browsers', '...\n')
    browsers = gapi.get_all_pages(cbcm.chromebrowsers(),
                                  'list',
                                  'browsers',
                                  page_message=page_message,
                                  customer=customer_id,
                                  orgUnitPath=orgUnitPath,
                                  query=query,
                                  projection=projection,
                                  fields=fields)
    for browser in browsers:
        browser = utils.flatten_json(browser)
        for a_key in browser:
            if a_key not in titles:
                titles.append(a_key)
        csv_rows.append(browser)
    if sort_headers:
        display.sort_csv_titles([
            'deviceId',
        ], titles)
    display.write_csv_file(csv_rows, titles, 'Browsers', todrive)
Example #2
0
def printEvents():
    calendarId, cal = buildCalendarDataGAPIObject(sys.argv[2])
    if not cal:
        return
    q = showDeleted = showHiddenInvitations = timeMin = \
        timeMax = timeZone = updatedMin = None
    toDrive = False
    titles = []
    csvRows = []
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'query':
            q = sys.argv[i + 1]
            i += 2
        elif myarg == 'includedeleted':
            showDeleted = True
            i += 1
        elif myarg == 'includehidden':
            showHiddenInvitations = True
            i += 1
        elif myarg == 'after':
            timeMin = utils.get_time_or_delta_from_now(sys.argv[i + 1])
            i += 2
        elif myarg == 'before':
            timeMax = utils.get_time_or_delta_from_now(sys.argv[i + 1])
            i += 2
        elif myarg == 'timezone':
            timeZone = sys.argv[i + 1]
            i += 2
        elif myarg == 'updated':
            updatedMin = utils.get_time_or_delta_from_now(sys.argv[i + 1])
            i += 2
        elif myarg == 'todrive':
            toDrive = True
            i += 1
        else:
            controlflow.invalid_argument_exit(
                sys.argv[i], 'gam calendar <email> printevents')
    page_message = gapi.got_total_items_msg(f'Events for {calendarId}', '')
    results = gapi.get_all_pages(cal.events(),
                                 'list',
                                 'items',
                                 page_message=page_message,
                                 calendarId=calendarId,
                                 q=q,
                                 showDeleted=showDeleted,
                                 showHiddenInvitations=showHiddenInvitations,
                                 timeMin=timeMin,
                                 timeMax=timeMax,
                                 timeZone=timeZone,
                                 updatedMin=updatedMin)
    for result in results:
        row = {'calendarId': calendarId}
        display.add_row_titles_to_csv_file(
            utils.flatten_json(result, flattened=row), csvRows, titles)
    display.sort_csv_titles(['calendarId', 'id', 'summary', 'status'], titles)
    display.write_csv_file(csvRows, titles, 'Calendar Events', toDrive)
Example #3
0
def printBuildings():
    to_drive = False
    cd = gapi_directory.build()
    titles = []
    csvRows = []
    fieldsList = ['buildingId']
    # buildings.list() currently doesn't support paging
    # but should soon, attempt to use it now so we
    # won't break when it's turned on.
    fields = 'nextPageToken,buildings(%s)'
    possible_fields = {}
    for pfield in cd._rootDesc['schemas']['Building']['properties']:
        possible_fields[pfield.lower()] = pfield
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower()
        if myarg == 'todrive':
            to_drive = True
            i += 1
        elif myarg == 'allfields':
            fields = None
            i += 1
        elif myarg in possible_fields:
            fieldsList.append(possible_fields[myarg])
            i += 1
        # Allows shorter arguments like "name" instead of "buildingname"
        elif 'building' + myarg in possible_fields:
            fieldsList.append(possible_fields['building' + myarg])
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print buildings')
    if fields:
        fields = fields % ','.join(fieldsList)
    buildings = gapi.get_all_pages(cd.resources().buildings(),
                                   'list',
                                   'buildings',
                                   customer=GC_Values[GC_CUSTOMER_ID],
                                   fields=fields)
    for building in buildings:
        building.pop('etags', None)
        building.pop('etag', None)
        building.pop('kind', None)
        if 'buildingId' in building:
            building['buildingId'] = f'id:{building["buildingId"]}'
        if 'floorNames' in building:
            building['floorNames'] = ','.join(building['floorNames'])
        building = utils.flatten_json(building)
        for item in building:
            if item not in titles:
                titles.append(item)
        csvRows.append(building)
    display.sort_csv_titles('buildingId', titles)
    display.write_csv_file(csvRows, titles, 'Buildings', to_drive)
Example #4
0
def print_():
    cbcm = build()
    projection = 'BASIC'
    query = None
    fields = None
    titles = []
    csv_rows = []
    todrive = False
    sort_headers = False
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'query':
            query = sys.argv[i+1]
            i += 2
        elif myarg == 'projection':
            projection = sys.argv[i + 1].upper()
            i += 2
        elif myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'sortheaders':
            sort_headers = True
            i += 1
        elif myarg == 'fields':
            fields = sys.argv[i + 1]
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print browsers')
    if fields:
        fields = f'browsers({fields}),nextPageToken'
    page_message = gapi.got_total_items_msg('Browsers', '...\n')
    browsers = gapi.get_all_pages(cbcm.chromebrowsers(), 'list',
                         'browsers', page_message=page_message,
                         customer=GC_Values[GC_CUSTOMER_ID],
                         query=query, projection=projection,
                         fields=fields)
    for browser in browsers:
        browser = utils.flatten_json(browser)
        for a_key in browser:
            if a_key not in titles:
                titles.append(a_key)
        csv_rows.append(browser)
    if sort_headers:
        display.sort_csv_titles(['name',], titles)
    display.write_csv_file(csv_rows, titles, 'Browsers', todrive)
Example #5
0
def printFeatures():
    to_drive = False
    cd = gapi_directory.build()
    titles = []
    csvRows = []
    fieldsList = ['name']
    fields = 'nextPageToken,features(%s)'
    possible_fields = {}
    for pfield in cd._rootDesc['schemas']['Feature']['properties']:
        possible_fields[pfield.lower()] = pfield
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower()
        if myarg == 'todrive':
            to_drive = True
            i += 1
        elif myarg == 'allfields':
            fields = None
            i += 1
        elif myarg in possible_fields:
            fieldsList.append(possible_fields[myarg])
            i += 1
        elif 'feature' + myarg in possible_fields:
            fieldsList.append(possible_fields['feature' + myarg])
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print features')
    if fields:
        fields = fields % ','.join(fieldsList)
    features = gapi.get_all_pages(cd.resources().features(),
                                  'list',
                                  'features',
                                  customer=GC_Values[GC_CUSTOMER_ID],
                                  fields=fields)
    for feature in features:
        feature.pop('etags', None)
        feature.pop('etag', None)
        feature.pop('kind', None)
        feature = utils.flatten_json(feature)
        for item in feature:
            if item not in titles:
                titles.append(item)
        csvRows.append(feature)
    display.sort_csv_titles('name', titles)
    display.write_csv_file(csvRows, titles, 'Features', to_drive)
Example #6
0
def printShowCalendars(users, csvFormat):
    if csvFormat:
        todrive = False
        titles = []
        csvRows = []
    i = 5
    while i < len(sys.argv):
        myarg = sys.argv[i].lower()
        if csvFormat and myarg == 'todrive':
            todrive = True
            i += 1
        else:
            controlflow.invalid_argument_exit(
                myarg, f"gam <users> {['show', 'print'][csvFormat]} calendars")
    i = 0
    count = len(users)
    for user in users:
        i += 1
        user, cal = buildCalendarGAPIObject(user)
        if not cal:
            continue
        result = gapi.get_all_pages(cal.calendarList(),
                                    'list',
                                    'items',
                                    soft_errors=True)
        jcount = len(result)
        if not csvFormat:
            print(f'User: {user}, Calendars:{display.current_count(i, count)}')
            if jcount == 0:
                continue
            j = 0
            for userCalendar in result:
                j += 1
                _showCalendar(userCalendar, j, jcount)
        else:
            if jcount == 0:
                continue
            for userCalendar in result:
                row = {'primaryEmail': user}
                display.add_row_titles_to_csv_file(
                    utils.flatten_json(userCalendar, flattened=row), csvRows,
                    titles)
    if csvFormat:
        display.sort_csv_titles(['primaryEmail', 'id'], titles)
        display.write_csv_file(csvRows, titles, 'Calendars', todrive)
Example #7
0
def printExports():
    v = buildGAPIObject()
    todrive = False
    csvRows = []
    initialTitles = ['matterId', 'id', 'name', 'createTime', 'status']
    titles = initialTitles[:]
    matters = []
    matterIds = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in ['matter', 'matters']:
            matters = sys.argv[i + 1].split(',')
            i += 2
        else:
            controlflow.invalid_argument_exit(myarg, 'gam print exports')
    if not matters:
        fields = 'matters(matterId),nextPageToken'
        matters_results = gapi.get_all_pages(v.matters(),
                                             'list',
                                             'matters',
                                             view='BASIC',
                                             state='OPEN',
                                             fields=fields)
        for matter in matters_results:
            matterIds.append(matter['matterId'])
    else:
        for matter in matters:
            matterIds.append(getMatterItem(v, matter))
    for matterId in matterIds:
        sys.stderr.write(f'Retrieving exports for matter {matterId}\n')
        exports = gapi.get_all_pages(v.matters().exports(),
                                     'list',
                                     'exports',
                                     matterId=matterId)
        for export in exports:
            display.add_row_titles_to_csv_file(
                utils.flatten_json(export, flattened={'matterId': matterId}),
                csvRows, titles)
    display.sort_csv_titles(initialTitles, titles)
    display.write_csv_file(csvRows, titles, 'Vault Exports', todrive)
Example #8
0
def printMatters():
    v = buildGAPIObject()
    todrive = False
    csvRows = []
    initialTitles = ['matterId', 'name', 'description', 'state']
    titles = initialTitles[:]
    view = 'FULL'
    state = None
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in PROJECTION_CHOICES_MAP:
            view = PROJECTION_CHOICES_MAP[myarg]
            i += 1
        elif myarg == 'matterstate':
            valid_states = gapi.get_enum_values_minus_unspecified(
                v._rootDesc['schemas']['Matter']['properties']['state']
                ['enum'])
            state = sys.argv[i + 1].upper()
            if state not in valid_states:
                controlflow.expected_argument_exit('state',
                                                   ', '.join(valid_states),
                                                   state)
            i += 2
        else:
            controlflow.invalid_argument_exit(myarg, 'gam print matters')
    gam.printGettingAllItems('Vault Matters', None)
    page_message = gapi.got_total_items_msg('Vault Matters', '...\n')
    matters = gapi.get_all_pages(v.matters(),
                                 'list',
                                 'matters',
                                 page_message=page_message,
                                 view=view,
                                 state=state)
    for matter in matters:
        display.add_row_titles_to_csv_file(utils.flatten_json(matter), csvRows,
                                           titles)
    display.sort_csv_titles(initialTitles, titles)
    display.write_csv_file(csvRows, titles, 'Vault Matters', todrive)
Example #9
0
def printShowACLs(csvFormat):
    calendarId, cal = buildCalendarDataGAPIObject(sys.argv[2])
    if not cal:
        return
    toDrive = False
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if csvFormat and myarg == 'todrive':
            toDrive = True
            i += 1
        else:
            action = ['showacl', 'printacl'][csvFormat]
            message = f'gam calendar <email> {action}'
            controlflow.invalid_argument_exit(sys.argv[i], message)
    acls = gapi.get_all_pages(cal.acl(),
                              'list',
                              'items',
                              calendarId=calendarId)
    i = 0
    if csvFormat:
        titles = []
        rows = []
    else:
        count = len(acls)
    for rule in acls:
        i += 1
        if csvFormat:
            row = utils.flatten_json(rule, None)
            for key in row:
                if key not in titles:
                    titles.append(key)
            rows.append(row)
        else:
            formatted_acl = formatACLRule(rule)
            current_count = display.current_count(i, count)
            print(
                f'Calendar: {calendarId}, ACL: {formatted_acl}{current_count}')
    if csvFormat:
        display.write_csv_file(rows, titles, f'{calendarId} Calendar ACLs',
                               toDrive)
Example #10
0
def printHolds():
    v = buildGAPIObject()
    todrive = False
    csvRows = []
    initialTitles = ['matterId', 'holdId', 'name', 'corpus', 'updateTime']
    titles = initialTitles[:]
    matters = []
    matterIds = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in ['matter', 'matters']:
            matters = sys.argv[i + 1].split(',')
            i += 2
        else:
            controlflow.invalid_argument_exit(myarg, 'gam print holds')
    if not matters:
        matterIds = _getAllMatterIds(v)
    else:
        for matter in matters:
            matterIds.append(getMatterItem(v, matter))
    i = 0
    matter_count = len(matterIds)
    for matterId in matterIds:
        i += 1
        sys.stderr.write(
            f'Retrieving holds for matter {matterId} ({i}/{matter_count})\n')
        holds = gapi.get_all_pages(v.matters().holds(),
                                   'list',
                                   'holds',
                                   matterId=matterId)
        for hold in holds:
            display.add_row_titles_to_csv_file(
                utils.flatten_json(hold, flattened={'matterId': matterId}),
                csvRows, titles)
    display.sort_csv_titles(initialTitles, titles)
    display.write_csv_file(csvRows, titles, 'Vault Holds', todrive)
Example #11
0
def printShowCrosTelemetry(mode):
    cm = build()
    cd = None
    parent = _get_customerid()
    todrive = False
    filter_ = None
    readMask = []
    orgUnitIdPathMap = {}
    diskpercentonly = False
    showOrgUnitPath = False
    supported_readmask_values = list(
        cm._rootDesc['schemas']['GoogleChromeManagementV1TelemetryDevice']
        ['properties'].keys())
    supported_readmask_values.sort()
    supported_readmask_map = {
        item.lower(): item
        for item in supported_readmask_values
    }
    i = 3
    if mode == 'info':
        if i >= len(sys.argv):
            controlflow.system_error_exit(
                3, f'<SerialNumber> required for "gam info crostelemetry"')
        filter_ = f'serialNumber={sys.argv[i]}'
        i += 1
        mode = 'show'
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'fields':
            field_list = sys.argv[i + 1].lower().split(',')
            for field_item in field_list:
                if field_item not in supported_readmask_map:
                    controlflow.expected_argument_exit(
                        'fields', ', '.join(supported_readmask_values),
                        field_item)
                else:
                    readMask.append(supported_readmask_map[field_item])
            i += 2
        elif myarg in supported_readmask_map:
            readMask.append(supported_readmask_map[myarg])
            i += 1
        elif myarg == 'filter':
            filter_ = sys.argv[i + 1]
            i += 2
        elif myarg in ['ou', 'org', 'orgunit']:
            _, orgUnitId = gapi_directory_orgunits.getOrgUnitId(
                sys.argv[i + 1], None)
            filter_ = f'orgUnitId={orgUnitId[3:]}'
            i += 2
        elif myarg == 'crossn':
            filter_ = f'serialNumber={sys.argv[i + 1]}'
            i += 2
        elif myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'showorgunitpath':
            showOrgUnitPath = True
            cd = gapi_directory.build()
            i += 1
        elif myarg == 'storagepercentonly':
            diskpercentonly = True
            i += 1
        else:
            msg = f'{myarg} is not a valid argument to "gam print crostelemetry"'
            controlflow.system_error_exit(3, msg)
    if not readMask:
        readMask = ','.join(supported_readmask_values)
    else:
        if 'deviceId' not in readMask:
            readMask.append('deviceId')
        readMask = ','.join(readMask)
    gam.printGettingAllItems('Chrome Device Telemetry...', filter_)
    page_message = gapi.got_total_items_msg('Chrome Device Telemetry', '...\n')
    devices = gapi.get_all_pages(cm.customers().telemetry().devices(),
                                 'list',
                                 'devices',
                                 page_message=page_message,
                                 parent=parent,
                                 filter=filter_,
                                 readMask=readMask)
    for device in devices:
        if 'totalDiskBytes' in device.get(
                'storageInfo', {}) and 'availableDiskBytes' in device.get(
                    'storageInfo', {}):
            disk_avail = int(device['storageInfo']['availableDiskBytes'])
            disk_size = int(device['storageInfo']['totalDiskBytes'])
            if diskpercentonly:
                device['storageInfo'] = {}
            device['storageInfo']['percentDiskFree'] = int(
                (disk_avail / disk_size) * 100)
            device['storageInfo']['percentDiskUsed'] = 100 - device[
                'storageInfo']['percentDiskFree']
        for cpuStatusReport in device.get('cpuStatusReport', []):
            for tempInfo in cpuStatusReport.pop('cpuTemperatureInfo', []):
                cpuStatusReport[
                    f"cpuTemperatureInfo.{tempInfo['label'].strip()}"] = tempInfo[
                        'temperatureCelsius']
        if showOrgUnitPath:
            orgUnitId = device.get('orgUnitId')
            if orgUnitId not in orgUnitIdPathMap:
                orgUnitIdPathMap[
                    orgUnitId] = gapi_directory_orgunits.orgunit_from_orgunitid(
                        orgUnitId, cd)
            device['orgUnitPath'] = orgUnitIdPathMap[orgUnitId]
    if mode == 'show':
        for device in devices:
            display.print_json(device)
            print()
            print()
    else:
        csvRows = []
        titles = []
        for device in devices:
            display.add_row_titles_to_csv_file(utils.flatten_json(device),
                                               csvRows, titles)
        display.write_csv_file(csvRows, titles, 'Telemetry Devices', todrive)
Example #12
0
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 {
                        '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'
                    if cpu_field in cpuStatusReports[i]:
                        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)
Example #13
0
def print_():
    ci = gapi_cloudidentity.build()
    i = 3
    members = membersCountOnly = managers = managersCountOnly = owners = ownersCountOnly = False
    gapi_directory_customer.setTrueCustomerId()
    parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    aliasDelimiter = ' '
    memberDelimiter = '\n'
    todrive = False
    titles = []
    csvRows = []
    roles = []
    sortHeaders = False
    while i < len(sys.argv):
        myarg = sys.argv[i].lower()
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'delimiter':
            aliasDelimiter = memberDelimiter = sys.argv[i + 1]
            i += 2
        elif myarg == 'sortheaders':
            sortHeaders = True
            i += 1
        elif myarg in ['members', 'memberscount']:
            roles.append(ROLE_MEMBER)
            members = True
            if myarg == 'memberscount':
                membersCountOnly = True
            i += 1
        elif myarg in ['owners', 'ownerscount']:
            roles.append(ROLE_OWNER)
            owners = True
            if myarg == 'ownerscount':
                ownersCountOnly = True
            i += 1
        elif myarg in ['managers', 'managerscount']:
            roles.append(ROLE_MANAGER)
            managers = True
            if myarg == 'managerscount':
                managersCountOnly = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print cigroups')
    if roles:
        if members:
            display.add_titles_to_csv_file([
                'MembersCount',
            ], titles)
            if not membersCountOnly:
                display.add_titles_to_csv_file([
                    'Members',
                ], titles)
        if managers:
            display.add_titles_to_csv_file([
                'ManagersCount',
            ], titles)
            if not managersCountOnly:
                display.add_titles_to_csv_file([
                    'Managers',
                ], titles)
        if owners:
            display.add_titles_to_csv_file([
                'OwnersCount',
            ], titles)
            if not ownersCountOnly:
                display.add_titles_to_csv_file([
                    'Owners',
                ], titles)
    gam.printGettingAllItems('Groups', None)
    page_message = gapi.got_total_items_first_last_msg('Groups')
    entityList = gapi.get_all_pages(ci.groups(),
                                    'list',
                                    'groups',
                                    page_message=page_message,
                                    message_attribute=['groupKey', 'id'],
                                    parent=parent,
                                    srcview='FULL',
                                    pageSize=500)
    i = 0
    count = len(entityList)
    for groupEntity in entityList:
        i += 1
        groupEmail = groupEntity['groupKey']['id']
        group = utils.flatten_json(groupEntity)
        for a_key in group:
            if a_key not in titles:
                titles.append(a_key)
        groupKey_id = groupEntity['name']
        if roles:
            sys.stderr.write(
                f' Getting {roles} for {groupEmail}{gam.currentCountNL(i, count)}'
            )
            page_message = gapi.got_total_items_first_last_msg('Members')
            validRoles, listRoles, listFields = gam._getRoleVerification(
                roles, 'nextPageToken,members(email,id,role)')
            groupMembers = gapi.get_all_pages(ci.groups().memberships(),
                                              'list',
                                              'memberships',
                                              page_message=page_message,
                                              message_attribute='email',
                                              soft_errors=True,
                                              groupKey_id=groupKey_id,
                                              view='BASIC')
            if members:
                membersList = []
                membersCount = 0
            if managers:
                managersList = []
                managersCount = 0
            if owners:
                ownersList = []
                ownersCount = 0
            for member in groupMembers:
                member_email = member['memberKey']['id']
                role = get_single_role(member.get('roles'))
                if not validRoles or role in validRoles:
                    if role == ROLE_MEMBER:
                        if members:
                            membersCount += 1
                            if not membersCountOnly:
                                membersList.append(member_email)
                    elif role == ROLE_MANAGER:
                        if managers:
                            managersCount += 1
                            if not managersCountOnly:
                                managersList.append(member_email)
                    elif role == ROLE_OWNER:
                        if owners:
                            ownersCount += 1
                            if not ownersCountOnly:
                                ownersList.append(member_email)
                    elif members:
                        membersCount += 1
                        if not membersCountOnly:
                            membersList.append(member_email)
            if members:
                group['MembersCount'] = membersCount
                if not membersCountOnly:
                    group['Members'] = memberDelimiter.join(membersList)
            if managers:
                group['ManagersCount'] = managersCount
                if not managersCountOnly:
                    group['Managers'] = memberDelimiter.join(managersList)
            if owners:
                group['OwnersCount'] = ownersCount
                if not ownersCountOnly:
                    group['Owners'] = memberDelimiter.join(ownersList)
        csvRows.append(group)
    if sortHeaders:
        display.sort_csv_titles([
            'Email',
        ], titles)
    display.write_csv_file(csvRows, titles, 'Groups', todrive)
Example #14
0
def showReport():
    rep = buildGAPIObject()
    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 = 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 = gam.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 == '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)
        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) == set(['value', 'name']):
                            event[item['name']] = item['value']
                        elif set(item) == set(['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) == set(['boolValue', 'name']):
                            event[item['name']] = item['boolValue']
                        elif set(item) == set(['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)
Example #15
0
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)
Example #16
0
def printshowtokens(csvFormat):
    cbcm = build()
    query = None
    fields = []
    if csvFormat:
        titles = ['token']
        csv_rows = []
        todrive = False
        sort_headers = False
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'query':
            query = sys.argv[i + 1]
            i += 2
        elif csvFormat and myarg == 'todrive':
            todrive = True
            i += 1
        elif csvFormat and myarg == 'sortheaders':
            sort_headers = True
            i += 1
        elif myarg == 'fields':
            fields = sys.argv[i + 1].replace(',', ' ').split()
            i += 2
        else:
            controlflow.invalid_argument_exit(
                sys.argv[i],
                f"gam {['show', 'print'][csvFormat]} browsertokens")
    if fields:
        fields.append('token')
        fields = f'chromeEnrollmentTokens({",".join(set(fields))}),nextPageToken'
    page_message = gapi.got_total_items_msg('Chrome Browser Enrollment Tokens',
                                            '...\n')
    browsers = gapi.get_all_pages(cbcm.enrollmentTokens(),
                                  'list',
                                  'chromeEnrollmentTokens',
                                  page_message=page_message,
                                  customer=GC_Values[GC_CUSTOMER_ID],
                                  query=query,
                                  fields=fields)
    if not csvFormat:
        count = len(browsers)
        print(f'Show {count} Chrome Browser Enrollment Tokens')
        i = 0
        for browser in browsers:
            i += 1
            print(
                f'  Chrome Browser Enrollment Token: {browser["token"]}{gam.currentCount(i, count)}'
            )
            browser.pop('kind', None)
            for field in browser:
                print(f'    {field}: {browser[field]}')
    else:
        for browser in browsers:
            browser = utils.flatten_json(browser)
            for a_key in browser:
                if a_key not in titles:
                    titles.append(a_key)
            csv_rows.append(browser)
        if sort_headers:
            display.sort_csv_titles([
                'token',
            ], titles)
        display.write_csv_file(csv_rows, titles,
                               'Chrome Browser Enrollment Tokens', todrive)
Example #17
0
def print_():
    ci = gapi_cloudidentity.build('cloudidentity_beta')
    i = 3
    members = membersCountOnly = managers = managersCountOnly = owners = ownersCountOnly = False
    gapi_directory_customer.setTrueCustomerId()
    parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    usemember = None
    memberDelimiter = '\n'
    todrive = False
    titles = []
    csvRows = []
    roles = []
    sortHeaders = False
    while i < len(sys.argv):
        myarg = sys.argv[i].lower()
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'enterprisemember':
            member = gam.convertUIDtoEmailAddress(
                sys.argv[i + 1], email_types=['user', 'group'])
            usemember = f"member_key_id == '{member}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels"
            i += 2
        elif myarg == 'delimiter':
            memberDelimiter = sys.argv[i + 1]
            i += 2
        elif myarg == 'sortheaders':
            sortHeaders = True
            i += 1
        elif myarg in ['members', 'memberscount']:
            roles.append(ROLE_MEMBER)
            members = True
            if myarg == 'memberscount':
                membersCountOnly = True
            i += 1
        elif myarg in ['owners', 'ownerscount']:
            roles.append(ROLE_OWNER)
            owners = True
            if myarg == 'ownerscount':
                ownersCountOnly = True
            i += 1
        elif myarg in ['managers', 'managerscount']:
            roles.append(ROLE_MANAGER)
            managers = True
            if myarg == 'managerscount':
                managersCountOnly = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print cigroups')
    if roles:
        if members:
            display.add_titles_to_csv_file([
                'MembersCount',
            ], titles)
            if not membersCountOnly:
                display.add_titles_to_csv_file([
                    'Members',
                ], titles)
        if managers:
            display.add_titles_to_csv_file([
                'ManagersCount',
            ], titles)
            if not managersCountOnly:
                display.add_titles_to_csv_file([
                    'Managers',
                ], titles)
        if owners:
            display.add_titles_to_csv_file([
                'OwnersCount',
            ], titles)
            if not ownersCountOnly:
                display.add_titles_to_csv_file([
                    'Owners',
                ], titles)
    gam.printGettingAllItems('Groups', usemember)
    page_message = gapi.got_total_items_first_last_msg('Groups')
    if usemember:
        try:
            result = gapi.get_all_pages(
                ci.groups().memberships(),
                'searchTransitiveGroups',
                'memberships',
                throw_reasons=[gapi_errors.ErrorReason.FOUR_O_O],
                page_message=page_message,
                message_attribute=['groupKey', 'id'],
                parent='groups/-',
                query=usemember,
                fields=
                'nextPageToken,memberships(group,groupKey(id),relationType)',
                pageSize=1000)
        except googleapiclient.errors.HttpError:
            controlflow.system_error_exit(
                2, f'enterprisemember requires Enterprise license')
        entityList = []
        for entity in result:
            if entity['relationType'] == 'DIRECT':
                entityList.append(
                    gapi.call(ci.groups(), 'get', name=entity['group']))
    else:
        entityList = gapi.get_all_pages(ci.groups(),
                                        'list',
                                        'groups',
                                        page_message=page_message,
                                        message_attribute=['groupKey', 'id'],
                                        parent=parent,
                                        view='FULL',
                                        pageSize=500)
    i = 0
    count = len(entityList)
    for groupEntity in entityList:
        i += 1
        groupEmail = groupEntity['groupKey']['id']
        for k, v in iter(groupEntity.pop('labels', {}).items()):
            if v == '':
                groupEntity[f'labels.{k}'] = True
            else:
                groupEntity[f'labels.{k}'] = v
        group = utils.flatten_json(groupEntity)
        for a_key in group:
            if a_key not in titles:
                titles.append(a_key)
        groupKey_id = groupEntity['name']
        if roles:
            sys.stderr.write(
                f' Getting {roles} for {groupEmail}{gam.currentCountNL(i, count)}'
            )
            page_message = gapi.got_total_items_first_last_msg('Members')
            validRoles, _, _ = gam._getRoleVerification(
                '.'.join(roles), 'nextPageToken,members(email,id,role)')
            groupMembers = gapi.get_all_pages(
                ci.groups().memberships(),
                'list',
                'memberships',
                page_message=page_message,
                message_attribute=['memberKey', 'id'],
                soft_errors=True,
                parent=groupKey_id,
                view='BASIC')
            if members:
                membersList = []
                membersCount = 0
            if managers:
                managersList = []
                managersCount = 0
            if owners:
                ownersList = []
                ownersCount = 0
            for member in groupMembers:
                member_email = member['memberKey']['id']
                role = get_single_role(member.get('roles'))
                if not validRoles or role in validRoles:
                    if role == ROLE_MEMBER:
                        if members:
                            membersCount += 1
                            if not membersCountOnly:
                                membersList.append(member_email)
                    elif role == ROLE_MANAGER:
                        if managers:
                            managersCount += 1
                            if not managersCountOnly:
                                managersList.append(member_email)
                    elif role == ROLE_OWNER:
                        if owners:
                            ownersCount += 1
                            if not ownersCountOnly:
                                ownersList.append(member_email)
                    elif members:
                        membersCount += 1
                        if not membersCountOnly:
                            membersList.append(member_email)
            if members:
                group['MembersCount'] = membersCount
                if not membersCountOnly:
                    group['Members'] = memberDelimiter.join(membersList)
            if managers:
                group['ManagersCount'] = managersCount
                if not managersCountOnly:
                    group['Managers'] = memberDelimiter.join(managersList)
            if owners:
                group['OwnersCount'] = ownersCount
                if not ownersCountOnly:
                    group['Owners'] = memberDelimiter.join(ownersList)
        csvRows.append(group)
    if sortHeaders:
        display.sort_csv_titles(['name', 'groupKey.id'], titles)
    display.write_csv_file(csvRows, titles, 'Groups', todrive)
Example #18
0
def print_():
    ci = gapi_cloudidentity.build_dwd()
    customer = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    parent = 'devices/-'
    device_filter = None
    get_device_users = True
    get_device_views = ['COMPANY_INVENTORY', 'USER_ASSIGNED_DEVICES']
    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 == 'nocompanydevices':
            get_device_views.remove('COMPANY_INVENTORY')
            i += 1
        elif myarg == 'nopersonaldevices':
            get_device_views.remove('USER_ASSIGNED_DEVICES')
            i += 1
        elif myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg == 'sortheaders':
            sortHeaders = True
            i += 1
        else:
           controlflow.invalid_argument_exit(sys.argv[i], 'gam print devices')
    view_name_map = {
      'COMPANY_INVENTORY': 'Company Devices',
      'USER_ASSIGNED_DEVICES': 'Personal Devices',
      }
    devices = []
    for view in get_device_views:
        view_name = view_name_map.get(view, 'Devices')
        page_message = gapi.got_total_items_msg(view_name, '...\n')
        devices += gapi.get_all_pages(ci.devices(), 'list', 'devices',
            customer=customer, page_message=page_message,
            pageSize=100, filter=device_filter, view=view)
    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)
Example #19
0
def print_members():
    ci = gapi_cloudidentity.build('cloudidentity_beta')
    todrive = False
    gapi_directory_customer.setTrueCustomerId()
    parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    usemember = None
    roles = []
    titles = ['group']
    csvRows = []
    groups_to_get = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in ['role', 'roles']:
            for role in sys.argv[i + 1].lower().replace(',', ' ').split():
                if role in GROUP_ROLES_MAP:
                    roles.append(GROUP_ROLES_MAP[role])
                else:
                    controlflow.system_error_exit(
                        2,
                        f'{role} is not a valid role for "gam print group-members {myarg}"'
                    )
            i += 2
        elif myarg == 'enterprisemember':
            member = gam.convertUIDtoEmailAddress(
                sys.argv[i + 1], email_types=['user', 'group'])
            usemember = f"member_key_id == '{member}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels"
            i += 2
        elif myarg in ['cigroup', 'cigroups']:
            group_email = gam.normalizeEmailAddressOrUID(sys.argv[i + 1])
            groups_to_get = [group_email]
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print cigroup-members')
    if not groups_to_get:
        gam.printGettingAllItems('Groups', usemember)
        page_message = gapi.got_total_items_first_last_msg('Groups')
        if usemember:
            try:
                groups_to_get = gapi.get_all_pages(
                    ci.groups().memberships(),
                    'searchTransitiveGroups',
                    'memberships',
                    throw_reasons=[gapi_errors.ErrorReason.FOUR_O_O],
                    message_attribute=['groupKey', 'id'],
                    page_message=page_message,
                    parent='groups/-',
                    query=usemember,
                    pageSize=1000,
                    fields=
                    'nextPageToken,memberships(groupKey(id),relationType)')
            except googleapiclient.errors.HttpError:
                controlflow.system_error_exit(
                    2, f'enterprisemember requires Enterprise license')
            groups_to_get = [
                group['groupKey']['id'] for group in groups_to_get
                if group['relationType'] == 'DIRECT'
            ]
        else:
            groups_to_get = gapi.get_all_pages(
                ci.groups(),
                'list',
                'groups',
                message_attribute=['groupKey', 'id'],
                page_message=page_message,
                parent=parent,
                view='BASIC',
                pageSize=1000,
                fields='nextPageToken,groups(groupKey(id))')
            groups_to_get = [
                group['groupKey']['id'] for group in groups_to_get
            ]
    i = 0
    count = len(groups_to_get)
    for group_email in groups_to_get:
        i += 1

        sys.stderr.write(
            f'Getting members for {group_email}{gam.currentCountNL(i, count)}')
        group_id = group_email_to_id(ci, group_email)
        print(f'Getting members of cigroup {group_email}...')
        page_message = f' {gapi.got_total_items_first_last_msg("Members")}'
        group_members = gapi.get_all_pages(
            ci.groups().memberships(),
            'list',
            'memberships',
            soft_errors=True,
            parent=group_id,
            view='FULL',
            pageSize=500,
            page_message=page_message,
            message_attribute=['memberKey', 'id'])
        #fields='nextPageToken,memberships(memberKey,roles,createTime,updateTime)')
        if roles:
            group_members = filter_members_to_roles(group_members, roles)
        for member in group_members:
            # reduce role to a single value
            member['role'] = get_single_role(member.pop('roles'))
            member = utils.flatten_json(member)
            for title in member:
                if title not in titles:
                    titles.append(title)
            member['group'] = group_email
            csvRows.append(member)
    display.write_csv_file(csvRows, titles, 'Group Members', todrive)
Example #20
0
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)
Example #21
0
def print_members():
    ci = gapi_cloudidentity.build()
    todrive = False
    gapi_directory_customer.setTrueCustomerId()
    parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    roles = []
    titles = ['group']
    csvRows = []
    groups_to_get = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in ['role', 'roles']:
            for role in sys.argv[i + 1].lower().replace(',', ' ').split():
                if role in GROUP_ROLES_MAP:
                    roles.append(GROUP_ROLES_MAP[role])
                else:
                    controlflow.system_error_exit(
                        2,
                        f'{role} is not a valid role for "gam print group-members {myarg}"'
                    )
            i += 2
        elif myarg in ['cigroup', 'cigroups']:
            group_email = gam.normalizeEmailAddressOrUID(sys.argv[i + 1])
            groups_to_get = [group_email]
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print cigroup-members')
    if not groups_to_get:
        gam.printGettingAllItems('Groups', None)
        page_message = gapi.got_total_items_first_last_msg('Groups')
        groups_to_get = gapi.get_all_pages(
            ci.groups(),
            'list',
            'groups',
            message_attribute=['groupKey', 'id'],
            page_message=page_message,
            parent=parent,
            view='BASIC',
            pageSize=1000,
            fields='nextPageToken,groups(groupKey(id))')
        groups_to_get = [group['groupKey']['id'] for group in groups_to_get]
    i = 0
    count = len(groups_to_get)
    for group_email in groups_to_get:
        i += 1

        sys.stderr.write(
            f'Getting members for {group_email}{gam.currentCountNL(i, count)}')
        group_id = group_email_to_id(ci, group_email)
        print(f'Getting members of cigroup {group_email}...')
        page_message = f' {gapi.got_total_items_first_last_msg("Members")}'
        group_members = gapi.get_all_pages(
            ci.groups().memberships(),
            'list',
            'memberships',
            soft_errors=True,
            parent=group_id,
            view='FULL',
            pageSize=500,
            page_message=page_message,
            message_attribute=['memberKey', 'id'])
        #fields='nextPageToken,memberships(memberKey,roles,createTime,updateTime)')
        if roles:
            group_members = filter_members_to_roles(group_members, roles)
        for member in group_members:
            # reduce role to a single value
            member['role'] = get_single_role(member.pop('roles'))
            member = utils.flatten_json(member)
            for title in member:
                if title not in titles:
                    titles.append(title)
            member['group'] = group_email
            csvRows.append(member)
    display.write_csv_file(csvRows, titles, 'Group Members', todrive)
Example #22
0
def print_members():
    ci = gapi_cloudidentity.build(CIGROUP_API_BETA)
    todrive = False
    gapi_directory_customer.setTrueCustomerId()
    parent = f'customers/{GC_Values[GC_CUSTOMER_ID]}'
    usemember = None
    roles = []
    titles = ['group']
    csvRows = []
    groups_to_get = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in ['role', 'roles']:
            for role in sys.argv[i + 1].lower().replace(',', ' ').split():
                if role in GROUP_ROLES_MAP:
                    roles.append(GROUP_ROLES_MAP[role])
                else:
                    controlflow.system_error_exit(
                        2,
                        f'{role} is not a valid role for "gam print group-members {myarg}"'
                    )
            i += 2
        elif myarg == 'enterprisemember':
            member = gam.convertUIDtoEmailAddress(
                sys.argv[i + 1], email_types=['user', 'group'])
            usemember = f"member_key_id == '{member}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels"
            i += 2
        elif myarg in ['cigroup', 'cigroups']:
            group_email = gam.normalizeEmailAddressOrUID(sys.argv[i + 1])
            groups_to_get = [group_email]
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam print cigroup-members')
    if not groups_to_get:
        groups_to_get = _get_groups_list(ci, usemember, parent)
    i = 0
    count = len(groups_to_get)
    for group_email in groups_to_get:
        i += 1

        sys.stderr.write(
            f'Getting members for {group_email}{gam.currentCountNL(i, count)}')
        group_id = group_email_to_id(ci, group_email)
        print(f'Getting members of cigroup {group_email}...')
        page_message = f' {gapi.got_total_items_first_last_msg("Members")}'
        group_members = gapi.get_all_pages(
            ci.groups().memberships(),
            'list',
            'memberships',
            soft_errors=True,
            parent=group_id,
            view='FULL',
            pageSize=500,
            page_message=page_message,
            message_attribute=[CIGROUP_MEMBERKEY, 'id'])
        #fields=f'nextPageToken,memberships({CIGROUP_MEMBERKEY},roles,createTime,updateTime)')
        if roles:
            group_members = filter_members_to_roles(group_members, roles)
        for member in group_members:
            # reduce role to a single value
            member['role'] = get_single_role(member.pop('roles'))
            member = utils.flatten_json(member)
            for title in member:
                if title not in titles:
                    titles.append(title)
            member['group'] = group_email
            csvRows.append(member)
    display.write_csv_file(csvRows, titles, 'Group Members', todrive)