Ejemplo n.º 1
0
def issue_command():
    cd = gapi_directory.build()
    i, devices = getCrOSDeviceEntity(3, cd)
    body = {}
    valid_commands = gapi.get_enum_values_minus_unspecified(
        cd._rootDesc['schemas']['DirectoryChromeosdevicesIssueCommandRequest']
        ['properties']['commandType']['enum'])
    command_map = {}
    for valid_command in valid_commands:
        v = valid_command.lower().replace('_', '')
        command_map[v] = valid_command
    times_to_check_status = 1
    doit = False
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'command':
            command = sys.argv[i + 1].lower().replace('_', '')
            if command not in command_map:
                controlflow.system_error_exit(2, f'expected command of ' \
                    f'{", ".join(valid_commands)} got {command}')
            body['commandType'] = command_map[command]
            i += 2
            if command == 'setvolume':
                body['payload'] = json.dumps({'volume': sys.argv[i]})
                i += 1
        elif myarg == 'timestocheckstatus':
            times_to_check_status = int(sys.argv[i + 1])
            i += 2
        elif myarg == 'doit':
            doit = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i],
                                              'gam issuecommand cros')
    if 'commandType' not in body:
        controlflow.missing_argument_exit('command <CrOSCommand>',
                                          'gam issuecommand cros')
    if body['commandType'] == 'WIPE_USERS' and not doit:
        controlflow.system_error_exit(2, 'wipe_users command requires admin ' \
            'acknowledge user data will be destroyed with the ' \
            'doit argument')
    if body['commandType'] == 'REMOTE_POWERWASH' and not doit:
        controlflow.system_error_exit(2, 'remote_powerwash command requires ' \
            'admin acknowledge user data will be destroyed, device will need' \
            ' to be reconnected to WiFi and re-enrolled with the doit argument')
    for device_id in devices:
        try:
            result = gapi.call(
                cd.customer().devices().chromeos(),
                'issueCommand',
                customerId=GC_Values[GC_CUSTOMER_ID],
                deviceId=device_id,
                throw_reasons=[gapi_errors.ErrorReason.FOUR_O_O],
                body=body)
        except googleapiclient.errors.HttpError:
            controlflow.system_error_exit(4, '400 response from Google. This ' \
              'usually indicates the devices was not in a state where it will' \
              ' accept the command. For example, reboot, set_volume and take_a_screenshot' \
              ' require the device to be in auto-start kiosk app mode.')
        command_id = result.get('commandId')
        _display_cros_command_result(cd, device_id, command_id,
                                     times_to_check_status)
Ejemplo n.º 2
0
def call(service,
         function,
         silent_errors=False,
         soft_errors=False,
         throw_reasons=None,
         retry_reasons=None,
         **kwargs):
    """Executes a single request on a Google service function.

  Args:
    service: A Google service object for the desired API.
    function: String, The name of a service request method to execute.
    silent_errors: Bool, If True, error messages are suppressed when
      encountered.
    soft_errors: Bool, If True, writes non-fatal errors to stderr.
    throw_reasons: A list of Google HTTP error reason strings indicating the
      errors generated by this request should be re-thrown. All other HTTP
      errors are consumed.
    retry_reasons: A list of Google HTTP error reason strings indicating which
      error should be retried, using exponential backoff techniques, when the
      error reason is encountered.
    **kwargs: Additional params to pass to the request method.

  Returns:
    A response object for the corresponding Google API call.
  """
    if throw_reasons is None:
        throw_reasons = []
    if retry_reasons is None:
        retry_reasons = []

    method = getattr(service, function)
    retries = 10
    parameters = dict(
        list(kwargs.items()) + list(GM_Globals[GM_EXTRA_ARGS_DICT].items()))
    for n in range(1, retries + 1):
        try:
            return method(**parameters).execute()
        except googleapiclient.errors.HttpError as e:
            http_status, reason, message = errors.get_gapi_error_detail(
                e,
                soft_errors=soft_errors,
                silent_errors=silent_errors,
                retry_on_http_error=n < 3)
            if http_status == -1:
                # The error detail indicated that we should retry this request
                # We'll refresh credentials and make another pass
                service._http.credentials.refresh(transport.create_http())
                continue
            if http_status == 0:
                return None

            is_known_error_reason = reason in [
                r.value for r in errors.ErrorReason
            ]
            if is_known_error_reason and errors.ErrorReason(
                    reason) in throw_reasons:
                if errors.ErrorReason(
                        reason) in errors.ERROR_REASON_TO_EXCEPTION:
                    raise errors.ERROR_REASON_TO_EXCEPTION[errors.ErrorReason(
                        reason)](message)
                raise e
            if (n != retries) and (is_known_error_reason and errors.ErrorReason(
                    reason) in errors.DEFAULT_RETRY_REASONS + retry_reasons):
                controlflow.wait_on_failure(n, retries, reason)
                continue
            if soft_errors:
                display.print_error(
                    f'{http_status}: {message} - {reason}{["", ": Giving up."][n > 1]}'
                )
                return None
            controlflow.system_error_exit(
                int(http_status), f'{http_status}: {message} - {reason}')
        except google.auth.exceptions.RefreshError as e:
            handle_oauth_token_error(
                e, soft_errors or
                errors.ErrorReason.SERVICE_NOT_AVAILABLE in throw_reasons)
            if errors.ErrorReason.SERVICE_NOT_AVAILABLE in throw_reasons:
                raise errors.GapiServiceNotAvailableError(str(e))
            display.print_error(
                f'User {GM_Globals[GM_CURRENT_API_USER]}: {str(e)}')
            return None
        except ValueError as e:
            if hasattr(service._http,
                       'cache') and service._http.cache is not None:
                service._http.cache = None
                continue
            controlflow.system_error_exit(4, str(e))
        except (httplib2.ServerNotFoundError, RuntimeError) as e:
            if n != retries:
                service._http.connections = {}
                controlflow.wait_on_failure(n, retries, str(e))
                continue
            controlflow.system_error_exit(4, str(e))
        except TypeError as e:
            controlflow.system_error_exit(4, str(e))
Ejemplo n.º 3
0
def doUpdateCros():
    cd = gapi_directory.build()
    i, devices = getCrOSDeviceEntity(3, cd)
    update_body = {}
    action_body = {}
    orgUnitPath = None
    ack_wipe = False
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'user':
            update_body['annotatedUser'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'location':
            update_body['annotatedLocation'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'notes':
            update_body['notes'] = sys.argv[i + 1].replace('\\n', '\n')
            i += 2
        elif myarg in ['tag', 'asset', 'assetid']:
            update_body['annotatedAssetId'] = sys.argv[i + 1]
            i += 2
        elif myarg in ['ou', 'org']:
            orgUnitPath = gapi_directory_orgunits.getOrgUnitItem(sys.argv[i +
                                                                          1])
            i += 2
        elif myarg == 'action':
            action = sys.argv[i + 1].lower().replace('_', '').replace('-', '')
            deprovisionReason = None
            if action in [
                    'deprovisionsamemodelreplace',
                    'deprovisionsamemodelreplacement'
            ]:
                action = 'deprovision'
                deprovisionReason = 'same_model_replacement'
            elif action in [
                    'deprovisiondifferentmodelreplace',
                    'deprovisiondifferentmodelreplacement'
            ]:
                action = 'deprovision'
                deprovisionReason = 'different_model_replacement'
            elif action in ['deprovisionretiringdevice']:
                action = 'deprovision'
                deprovisionReason = 'retiring_device'
            elif action == 'deprovisionupgradetransfer':
                action = 'deprovision'
                deprovisionReason = 'upgrade_transfer'
            elif action not in ['disable', 'reenable']:
                controlflow.system_error_exit(2, f'expected action of ' \
                    f'deprovision_same_model_replace, ' \
                    f'deprovision_different_model_replace, ' \
                    f'deprovision_retiring_device, ' \
                    f'deprovision_upgrade_transfer, disable or reenable,'
                    f' got {action}')
            action_body = {'action': action}
            if deprovisionReason:
                action_body['deprovisionReason'] = deprovisionReason
            i += 2
        elif myarg == 'acknowledgedevicetouchrequirement':
            ack_wipe = True
            i += 1
        else:
            controlflow.invalid_argument_exit(sys.argv[i], 'gam update cros')
    i = 0
    count = len(devices)
    if action_body:
        if action_body['action'] == 'deprovision' and not ack_wipe:
            print(f'WARNING: Refusing to deprovision {count} devices because '
                  'acknowledge_device_touch_requirement not specified. ' \
                  'Deprovisioning a device means the device will have to ' \
                  'be physically wiped and re-enrolled to be managed by ' \
                  'your domain again. This requires physical access to ' \
                  'the device and is very time consuming to perform for ' \
                  'each device. Please add ' \
                  '"acknowledge_device_touch_requirement" to the GAM ' \
                  'command if you understand this and wish to proceed ' \
                  'with the deprovision. Please also be aware that ' \
                  'deprovisioning can have an effect on your device ' \
                  'license count. See ' \
                  'https://support.google.com/chrome/a/answer/3523633 '\
                  'for full details.')
            sys.exit(3)
        for deviceId in devices:
            i += 1
            cur_count = gam.currentCount(i, count)
            print(f' performing action {action} for {deviceId}{cur_count}')
            gapi.call(cd.chromeosdevices(),
                      function='action',
                      customerId=GC_Values[GC_CUSTOMER_ID],
                      resourceId=deviceId,
                      body=action_body)
    else:
        if update_body:
            for deviceId in devices:
                i += 1
                current_count = gam.currentCount(i, count)
                print(f' updating {deviceId}{current_count}')
                gapi.call(cd.chromeosdevices(),
                          'update',
                          customerId=GC_Values[GC_CUSTOMER_ID],
                          deviceId=deviceId,
                          body=update_body)
        if orgUnitPath:
            # split moves into max 50 devices per batch
            for l in range(0, len(devices), 50):
                move_body = {'deviceIds': devices[l:l + 50]}
                print(f' moving {len(move_body["deviceIds"])} devices to ' \
                      f'{orgUnitPath}')
                gapi.call(cd.chromeosdevices(),
                          'moveDevicesToOu',
                          customerId=GC_Values[GC_CUSTOMER_ID],
                          orgUnitPath=orgUnitPath,
                          body=move_body)
Ejemplo n.º 4
0
Archivo: errors.py Proyecto: xbl3/GAM
def get_gapi_error_detail(e,
                          soft_errors=False,
                          silent_errors=False,
                          retry_on_http_error=False):
    """Extracts error detail from a non-200 GAPI Response.

  Args:
    e: googleapiclient.HttpError, The HTTP Error received.
    soft_errors: Boolean, If true, causes error messages to be surpressed,
      rather than sending them to stderr.
    silent_errors: Boolean, If true, suppresses and ignores any errors from
      being displayed
    retry_on_http_error: Boolean, If true, will return -1 as the HTTP Response
      code, indicating that the request can be retried. TODO: Remove this param,
        as it seems to be outside the scope of this method.

  Returns:
    A tuple containing the HTTP Response code, GAPI error reason, and error
        message.
  """
    try:
        error = json.loads(e.content.decode(UTF8))
    except ValueError:
        error_content = e.content.decode(UTF8) if isinstance(
            e.content, bytes) else e.content
        if (e.resp['status'] == '503') and (
                error_content == 'Quota exceeded for the current request'):
            return (e.resp['status'], ErrorReason.QUOTA_EXCEEDED.value,
                    error_content)
        if (e.resp['status'] == '403') and (error_content.startswith(
                'Request rate higher than configured')):
            return (e.resp['status'], ErrorReason.QUOTA_EXCEEDED.value,
                    error_content)
        if (e.resp['status'] == '502') and ('Bad Gateway' in error_content):
            return (e.resp['status'], ErrorReason.BAD_GATEWAY.value,
                    error_content)
        if (e.resp['status'] == '504') and ('Gateway Timeout' in error_content):
            return (e.resp['status'], ErrorReason.GATEWAY_TIMEOUT.value,
                    error_content)
        if (e.resp['status'] == '403') and ('Invalid domain.' in error_content):
            error = _create_http_error_dict(403, ErrorReason.NOT_FOUND.value,
                                            'Domain not found')
        elif (e.resp['status'] == '400') and (
                'InvalidSsoSigningKey' in error_content):
            error = _create_http_error_dict(400, ErrorReason.INVALID.value,
                                            'InvalidSsoSigningKey')
        elif (e.resp['status'] == '400') and ('UnknownError' in error_content):
            error = _create_http_error_dict(400, ErrorReason.INVALID.value,
                                            'UnknownError')
        elif retry_on_http_error:
            return (-1, None, None)
        elif soft_errors:
            if not silent_errors:
                display.print_error(error_content)
            return (0, None, None)
        else:
            controlflow.system_error_exit(5, error_content)
        # END: ValueError catch

    if 'error' in error:
        http_status = error['error']['code']
        try:
            message = error['error']['errors'][0]['message']
        except KeyError:
            message = error['error']['message']
        if http_status == 404:
            if 'Requested entity was not found' in message or 'does not exist' in message:
                error = _create_http_error_dict(404, ErrorReason.NOT_FOUND.value,
                                                message)
    else:
        if 'error_description' in error:
            if error['error_description'] == 'Invalid Value':
                message = error['error_description']
                http_status = 400
                error = _create_http_error_dict(400, ErrorReason.INVALID.value,
                                                message)
            else:
                controlflow.system_error_exit(4, str(error))
        else:
            controlflow.system_error_exit(4, str(error))

    # Extract the error reason
    try:
        reason = error['error']['errors'][0]['reason']
        if reason == 'notFound':
            if 'userKey' in message:
                reason = ErrorReason.USER_NOT_FOUND.value
            elif 'groupKey' in message:
                reason = ErrorReason.GROUP_NOT_FOUND.value
            elif 'memberKey' in message:
                reason = ErrorReason.MEMBER_NOT_FOUND.value
            elif 'Domain not found' in message:
                reason = ErrorReason.DOMAIN_NOT_FOUND.value
            elif 'Resource Not Found' in message:
                reason = ErrorReason.RESOURCE_NOT_FOUND.value
        elif reason == 'invalid':
            if 'userId' in message:
                reason = ErrorReason.USER_NOT_FOUND.value
            elif 'memberKey' in message:
                reason = ErrorReason.INVALID_MEMBER.value
        elif reason == 'failedPrecondition':
            if 'Bad Request' in message:
                reason = ErrorReason.BAD_REQUEST.value
            elif 'Mail service not enabled' in message:
                reason = ErrorReason.SERVICE_NOT_AVAILABLE.value
        elif reason == 'required':
            if 'memberKey' in message:
                reason = ErrorReason.MEMBER_NOT_FOUND.value
        elif reason == 'conditionNotMet':
            if 'Cyclic memberships not allowed' in message:
                reason = ErrorReason.CYCLIC_MEMBERSHIPS_NOT_ALLOWED.value
    except KeyError:
        reason = f'{http_status}'
    return (http_status, reason, message)
Ejemplo n.º 5
0
def update_policy():
    svc = build()
    customer = _get_customerid()
    schemas = build_schemas(svc)
    orgunit = None
    printer_id = None
    app_id = None
    i = 3
    body = {'requests': []}
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg in ['ou', 'org', 'orgunit']:
            orgunit = _get_orgunit(sys.argv[i + 1])
            i += 2
        elif myarg == 'printerid':
            printer_id = sys.argv[i + 1]
            i += 2
        elif myarg == 'appid':
            app_id = sys.argv[i + 1]
            i += 2
        elif myarg in schemas:
            body['requests'].append({
                'policyValue': {
                    'policySchema': schemas[myarg]['name'],
                    'value': {}
                },
                'updateMask': ''
            })
            i += 1
            while i < len(sys.argv):
                field = sys.argv[i].lower()
                if field in ['ou', 'org', 'orgunit', 'printerid', 'appid'
                             ] or '.' in field:
                    break  # field is actually a new policy, orgunit or app/printer id
                expected_fields = ', '.join(schemas[myarg]['settings'])
                if field not in expected_fields:
                    msg = f'Expected {myarg} field of {expected_fields}. Got {field}.'
                    controlflow.system_error_exit(4, msg)
                cased_field = schemas[myarg]['settings'][field]['name']
                value = sys.argv[i + 1]
                vtype = schemas[myarg]['settings'][field]['type']
                if vtype in ['TYPE_INT64', 'TYPE_INT32', 'TYPE_UINT64']:
                    if not value.isnumeric():
                        msg = f'Value for {myarg} {field} must be a number, got {value}'
                        controlflow.system_error_exit(7, msg)
                    value = int(value)
                elif vtype in ['TYPE_BOOL']:
                    value = gam.getBoolean(value, field)
                elif vtype in ['TYPE_ENUM']:
                    value = value.upper()
                    enum_values = schemas[myarg]['settings'][field]['enums']
                    if value not in enum_values:
                        expected_enums = ', '.join(enum_values)
                        msg = f'Expected {myarg} {field} value to be one of ' \
                              f'{expected_enums}, got {value}'
                        controlflow.system_error_exit(8, msg)
                    prefix = schemas[myarg]['settings'][field]['enum_prefix']
                    value = f'{prefix}{value}'
                elif vtype in ['TYPE_LIST']:
                    value = value.split(',')
                body['requests'][-1]['policyValue']['value'][
                    cased_field] = value
                body['requests'][-1]['updateMask'] += f'{cased_field},'
                i += 2
        else:
            msg = f'{myarg} is not a valid argument to "gam update chromepolicy"'
            controlflow.system_error_exit(4, msg)
    if not orgunit:
        controlflow.system_error_exit(3, 'You must specify an orgunit')
    for request in body['requests']:
        request['policyTargetKey'] = {'targetResource': orgunit}
        if printer_id:
            request['policyTargetKey']['additionalTargetKeys'] = {
                'printer_id': printer_id
            }
        elif app_id:
            request['policyTargetKey']['additionalTargetKeys'] = {
                'app_id': app_id
            }
    gapi.call(svc.customers().policies().orgunits(),
              'batchModify',
              customer=customer,
              body=body)
Ejemplo n.º 6
0
def updateHold():
    v = buildGAPIObject()
    hold = sys.argv[3]
    matterId = None
    body = {}
    query = None
    add_accounts = []
    del_accounts = []
    start_time = None
    end_time = None
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'matter':
            matterId = getMatterItem(v, sys.argv[i + 1])
            holdId = convertHoldNameToID(v, hold, matterId)
            i += 2
        elif myarg == 'query':
            query = sys.argv[i + 1]
            i += 2
        elif myarg in ['orgunit', 'ou']:
            body['orgUnit'] = {
                'orgUnitId': gam.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 in ['addusers', 'addaccounts', 'addgroups']:
            add_accounts = sys.argv[i + 1].split(',')
            i += 2
        elif myarg in ['removeusers', 'removeaccounts', 'removegroups']:
            del_accounts = sys.argv[i + 1].split(',')
            i += 2
        else:
            controlflow.invalid_argument_exit(myarg, 'gam update hold')
    if not matterId:
        controlflow.system_error_exit(
            3, 'you must specify a matter for the hold.')
    if query or start_time or end_time or body.get('orgUnit'):
        fields = 'corpus,query,orgUnit'
        old_body = gapi.call(v.matters().holds(),
                             'get',
                             matterId=matterId,
                             holdId=holdId,
                             fields=fields)
        body['query'] = old_body['query']
        body['corpus'] = old_body['corpus']
        if 'orgUnit' in old_body and 'orgUnit' not in body:
            # bah, API requires this to be sent
            # on update even when it's not changing
            body['orgUnit'] = old_body['orgUnit']
        query_type = f'{body["corpus"].lower()}Query'
        if body['corpus'] == 'DRIVE':
            if query:
                try:
                    body['query'][query_type] = json.loads(query)
                except ValueError as e:
                    message = f'{str(e)}, query: {query}'
                    controlflow.system_error_exit(3, message)
        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 body:
        print(f'Updating hold {hold} / {holdId}')
        gapi.call(v.matters().holds(),
                  'update',
                  matterId=matterId,
                  holdId=holdId,
                  body=body)
    if add_accounts or del_accounts:
        cd = gam.buildGAPIObject('directory')
        for account in add_accounts:
            print(f'adding {account} to hold.')
            add_body = {'accountId': gam.convertEmailAddressToUID(account, cd)}
            gapi.call(v.matters().holds().accounts(),
                      'create',
                      matterId=matterId,
                      holdId=holdId,
                      body=add_body)
        for account in del_accounts:
            print(f'removing {account} from hold.')
            accountId = gam.convertEmailAddressToUID(account, cd)
            gapi.call(v.matters().holds().accounts(),
                      'delete',
                      matterId=matterId,
                      holdId=holdId,
                      accountId=accountId)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
def update():
    verif = build()
    a_domain = sys.argv[3]
    verificationMethod = sys.argv[4].upper()
    if verificationMethod == 'CNAME':
        verificationMethod = 'DNS_CNAME'
    elif verificationMethod in ['TXT', 'TEXT']:
        verificationMethod = 'DNS_TXT'
    if verificationMethod in ['DNS_TXT', 'DNS_CNAME']:
        verify_type = 'INET_DOMAIN'
        identifier = a_domain
    else:
        verify_type = 'SITE'
        identifier = f'http://{a_domain}/'
    body = {
        'site': {
            'type': verify_type,
            'identifier': identifier
        },
        'verificationMethod': verificationMethod
    }
    try:
        verify_result = gapi.call(
            verif.webResource(),
            'insert',
            throw_reasons=[gapi_errors.ErrorReason.BAD_REQUEST],
            verificationMethod=verificationMethod,
            body=body)
    except gapi_errors.GapiBadRequestError as e:
        print(f'ERROR: {str(e)}')
        verify_data = gapi.call(verif.webResource(), 'getToken', body=body)
        print(f'Method:  {verify_data["method"]}')
        print(f'Expected Token:      {verify_data["token"]}')
        if verify_data['method'] in ['DNS_CNAME', 'DNS_TXT']:
            simplehttp = transport.create_http()
            base_url = 'https://dns.google/resolve?'
            query_params = {}
            if verify_data['method'] == 'DNS_CNAME':
                cname_token = verify_data['token']
                cname_list = cname_token.split(' ')
                cname_subdomain = cname_list[0]
                query_params['name'] = f'{cname_subdomain}.{a_domain}'
                query_params['type'] = 'cname'
            else:
                query_params['name'] = a_domain
                query_params['type'] = 'txt'
            full_url = base_url + urlencode(query_params)
            (_, c) = simplehttp.request(full_url, 'GET')
            result = json.loads(c)
            status = result['Status']
            if status == 0 and 'Answer' in result:
                answers = result['Answer']
                if verify_data['method'] == 'DNS_CNAME':
                    answer = answers[0]['data']
                else:
                    answer = 'no matching record found'
                    for possible_answer in answers:
                        possible_answer['data'] = possible_answer[
                            'data'].strip('"')
                        if possible_answer['data'].startswith(
                                'google-site-verification'):
                            answer = possible_answer['data']
                            break
                        print(
                            f'Unrelated TXT record: {possible_answer["data"]}')
                print(f'Found DNS Record: {answer}')
            elif status == 0:
                controlflow.system_error_exit(1, 'DNS record not found')
            else:
                controlflow.system_error_exit(
                    status,
                    DNS_ERROR_CODES_MAP.get(status, f'Unknown error {status}'))
        return
    print('SUCCESS!')
    print(f'Verified:  {verify_result["site"]["identifier"]}')
    print(f'ID:  {verify_result["id"]}')
    print(f'Type: {verify_result["site"]["type"]}')
    print('All Owners:')
    try:
        for owner in verify_result['owners']:
            print(f' {owner}')
    except KeyError:
        pass
    print()
    print(
        f'You can now add {a_domain} or it\'s subdomains as secondary or domain aliases of the {GC_Values[GC_DOMAIN]} G Suite Account.'
    )
Ejemplo n.º 9
0
def update_policy():
    svc = build()
    customer = _get_customerid()
    schemas = build_schemas(svc)
    orgunit = None
    printer_id = None
    app_id = None
    i = 3
    body = {'requests': []}
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg in ['ou', 'org', 'orgunit']:
            orgunit = _get_orgunit(sys.argv[i+1])
            i += 2
        elif myarg == 'printerid':
            printer_id = sys.argv[i+1]
            i += 2
        elif myarg == 'appid':
            app_id = sys.argv[i+1]
            i += 2
        elif myarg in schemas:
            schemaName = schemas[myarg]['name']
            body['requests'].append({'policyValue': {'policySchema': schemaName,
                                                     'value': {}},
                                     'updateMask': ''})
            i += 1
            while i < len(sys.argv):
                field = sys.argv[i].lower()
                if field in ['ou', 'org', 'orgunit', 'printerid', 'appid'] or '.' in field:
                    break # field is actually a new policy, orgunit or app/printer id
                # Handle TYPE_MESSAGE fields with durations, values, counts and timeOfDay as special cases
                schema = CHROME_SCHEMA_TYPE_MESSAGE.get(schemaName, {}).get(field)
                if schema:
                    i += 1
                    casedField = schema['casedField']
                    vtype = schema['type']
                    if vtype != 'timeOfDay':
                        if 'default' not in  schema:
                            value = gam.getInteger(sys.argv[i], casedField,
                                                   minVal=schema['minVal'], maxVal=schema['maxVal'])*schema['scale']
                            i += 1
                        elif i < len(sys.argv) and sys.argv[i].isdigit():
                            value = gam.getInteger(sys.argv[i], casedField,
                                                   minVal=schema['minVal'], maxVal=schema['maxVal'])*schema['scale']
                            i += 1
                        else: # Handle empty value for fields with default
                            value = schema['default']*schema['scale']
                            if i < len(sys.argv) and not sys.argv[i]:
                                i += 1
                    else:
                        value = utils.get_hhmm(sys.argv[i])
                        i += 1
                    if vtype == 'duration':
                        body['requests'][-1]['policyValue']['value'][casedField] = {vtype: f'{value}s'}
                    elif vtype == 'value':
                        body['requests'][-1]['policyValue']['value'][casedField] = {vtype: value}
                    elif vtype == 'count':
                        body['requests'][-1]['policyValue']['value'][casedField] = value
                    else: ##timeOfDay
                        hours, minutes = value.split(':')
                        body['requests'][-1]['policyValue']['value'][casedField] = {vtype: {'hours': hours, 'minutes': minutes}}
                    body['requests'][-1]['updateMask'] += f'{casedField},'
                    continue
                expected_fields = ', '.join(schemas[myarg]['settings'])
                if field not in expected_fields:
                    msg = f'Expected {myarg} field of {expected_fields}. Got {field}.'
                    controlflow.system_error_exit(4, msg)
                cased_field = schemas[myarg]['settings'][field]['name']
                value = sys.argv[i+1]
                vtype = schemas[myarg]['settings'][field]['type']
                if vtype in ['TYPE_INT64', 'TYPE_INT32', 'TYPE_UINT64']:
                    if not value.isnumeric():
                        msg = f'Value for {myarg} {field} must be a number, got {value}'
                        controlflow.system_error_exit(7, msg)
                    value = int(value)
                elif vtype in ['TYPE_BOOL']:
                    value = gam.getBoolean(value, field)
                elif vtype in ['TYPE_ENUM']:
                    value = value.upper()
                    prefix = schemas[myarg]['settings'][field]['enum_prefix']
                    enum_values = schemas[myarg]['settings'][field]['enums']
                    if value in enum_values:
                        value = f'{prefix}{value}'
                    elif value.replace(prefix, '') in enum_values:
                        pass
                    else:
                        expected_enums = ', '.join(enum_values)
                        msg = f'Expected {myarg} {field} value to be one of ' \
                              f'{expected_enums}, got {value}'
                        controlflow.system_error_exit(8, msg)
                elif vtype in ['TYPE_LIST']:
                    value = value.split(',')
                if myarg == 'chrome.users.chromebrowserupdates' and \
                      cased_field == 'targetVersionPrefixSetting':
                    mg = re.compile(r'^([a-z]+)-(\d+)$').match(value)
                    if mg:
                        channel = mg.group(1).lower().replace('_', '')
                        minus = mg.group(2)
                        channel_map = gapi_chromehistory.get_channel_map(None)
                        if channel not in channel_map:
                            expected_channels = ', '.join(channel_map)
                            msg = f'Expected {myarg} {cased_field} channel to be one of ' \
                                f'{expected_channels}, got {channel}'
                            controlflow.system_error_exit(8, msg)
                        milestone = gapi_chromehistory.get_relative_milestone(
                            channel_map[channel], int(minus))
                        if not milestone:
                            msg = f'{myarg} {cased_field} channel {channel} offset {minus} does not exist'
                            controlflow.system_error_exit(8, msg)
                        value = f'{milestone}.'
                body['requests'][-1]['policyValue']['value'][cased_field] = value
                body['requests'][-1]['updateMask'] += f'{cased_field},'
                i += 2
        else:
            msg = f'{myarg} is not a valid argument to "gam update chromepolicy"'
            controlflow.system_error_exit(4, msg)
    if not orgunit:
        controlflow.system_error_exit(3, 'You must specify an orgunit')
    for request in body['requests']:
        request['policyTargetKey'] = {'targetResource': orgunit}
        if printer_id:
            request['policyTargetKey']['additionalTargetKeys'] = {'printer_id': printer_id}
        elif app_id:
            request['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
    gapi.call(svc.customers().policies().orgunits(),
              'batchModify',
              customer=customer,
              body=body)
Ejemplo n.º 10
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)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
def printVersions():
    cm = build()
    customer = _get_customerid()
    todrive = False
    titles = CHROME_VERSIONS_TITLES
    csvRows = []
    orgunit = None
    startDate = None
    endDate = None
    pfilter = None
    reverse = False
    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 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 == 'recentfirst':
            reverse = True
            i += 1
        else:
            msg = f'{myarg} is not a valid argument to "gam print chromeversions"'
            controlflow.system_error_exit(3, msg)
    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 Versions', pfilter)
    page_message = gapi.got_total_items_msg('Chrome Versions', '...\n')
    versions = gapi.get_all_pages(cm.customers().reports(),
                                  'countChromeVersions',
                                  'browserVersions',
                                  page_message=page_message,
                                  customer=customer,
                                  orgUnitId=orgunit,
                                  filter=pfilter)
    for version in sorted(versions,
                          key=lambda k: k.get('version', 'Unknown'),
                          reverse=reverse):
        if orgunit:
            version['orgUnitPath'] = orgUnitPath
        if 'version' not in version:
            version['version'] = 'Unknown'
        csvRows.append(version)
    display.write_csv_file(csvRows, titles, 'Chrome Versions', todrive)
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
def printshow_policies():
    svc = build()
    customer = _get_customerid()
    orgunit = None
    printer_id = None
    app_id = None
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg in ['ou', 'org', 'orgunit']:
            orgunit = _get_orgunit(sys.argv[i + 1])
            i += 2
        elif myarg == 'printerid':
            printer_id = sys.argv[i + 1]
            i += 2
        elif myarg == 'appid':
            app_id = sys.argv[i + 1]
            i += 2
        else:
            msg = f'{myarg} is not a valid argument to "gam print chromepolicy"'
            controlflow.system_error_exit(3, msg)
    if not orgunit:
        controlflow.system_error_exit(3, 'You must specify an orgunit')
    body = {
        'policyTargetKey': {
            'targetResource': orgunit,
        }
    }
    if printer_id:
        body['policyTargetKey']['additionalTargetKeys'] = {
            'printer_id': printer_id
        }
        namespaces = ['chrome.printers']
    elif app_id:
        body['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
        namespaces = [
            'chrome.users.apps', 'chrome.devices.managedGuest.apps',
            'chrome.devices.kiosk.apps'
        ]
    else:
        namespaces = [
            'chrome.users',
            #           Not yet implemented:
            #           'chrome.devices',
            #           'chrome.devices.managedGuest',
            #           'chrome.devices.kiosk',
        ]
    throw_reasons = [
        gapi_errors.ErrorReason.FOUR_O_O,
    ]
    orgunitPath = gapi_directory_orgunits.orgunit_from_orgunitid(
        orgunit[9:], None)
    header = f'Organizational Unit: {orgunitPath}'
    if printer_id:
        header += f', printerid: {printer_id}'
    elif app_id:
        header += f', appid: {app_id}'
    print(header)
    for namespace in namespaces:
        body['policySchemaFilter'] = f'{namespace}.*'
        try:
            policies = gapi.get_all_pages(svc.customers().policies(),
                                          'resolve',
                                          items='resolvedPolicies',
                                          throw_reasons=throw_reasons,
                                          customer=customer,
                                          body=body)
        except googleapiclient.errors.HttpError:
            policies = []
        for policy in sorted(
                policies,
                key=lambda k: k.get('value', {}).get('policySchema', '')):
            print()
            name = policy.get('value', {}).get('policySchema', '')
            print(name)
            values = policy.get('value', {}).get('value', {})
            for setting, value in values.items():
                if isinstance(value, str) and value.find('_ENUM_') != -1:
                    value = value.split('_ENUM_')[-1]
                print(f'  {setting}: {value}')
Ejemplo n.º 15
0
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': gam.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"]}')
Ejemplo n.º 16
0
def printshow_policies():
    svc = build()
    customer = _get_customerid()
    orgunit = None
    printer_id = None
    app_id = None
    body = {}
    namespaces = []
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg in ['ou', 'org', 'orgunit']:
            orgunit = _get_orgunit(sys.argv[i+1])
            i += 2
        elif myarg == 'printerid':
            printer_id = sys.argv[i+1]
            i += 2
        elif myarg == 'appid':
            app_id = sys.argv[i+1]
            i += 2
        elif myarg == 'namespace':
            namespaces.extend(sys.argv[i+1].replace(',', ' ').split())
            i += 2
        else:
            msg = f'{myarg} is not a valid argument to "gam print chromepolicy"'
            controlflow.system_error_exit(3, msg)
    if not orgunit:
        controlflow.system_error_exit(3, 'You must specify an orgunit')
    body['policyTargetKey'] = {'targetResource': orgunit}
    if printer_id:
        body['policyTargetKey']['additionalTargetKeys'] = {'printer_id': printer_id}
        if not namespaces:
            namespaces = ['chrome.printers']
    elif app_id:
        body['policyTargetKey']['additionalTargetKeys'] = {'app_id': app_id}
        if not namespaces:
            namespaces = ['chrome.users.apps',
                          'chrome.devices.managedGuest.apps',
                          'chrome.devices.kiosk.apps']
    elif not namespaces:
        namespaces = [
            'chrome.users',
            'chrome.users.apps',
            'chrome.devices',
            'chrome.devices.kiosk',
            'chrome.devices.managedGuest',
            ]
    throw_reasons = [gapi_errors.ErrorReason.FOUR_O_O,]
    orgunitPath = gapi_directory_orgunits.orgunit_from_orgunitid(orgunit[9:], None)
    print(f'Organizational Unit: {orgunitPath}')
    for namespace in namespaces:
        spacing = '  '
        body['policySchemaFilter'] = f'{namespace}.*'
        body['pageToken'] = None
        try:
            policies = gapi.get_all_pages(svc.customers().policies(), 'resolve',
                                          items='resolvedPolicies',
                                          throw_reasons=throw_reasons,
                                          customer=customer,
                                          body=body,
                                          page_args_in_body=True)
        except googleapiclient.errors.HttpError:
            policies = []
        # sort policies first by app/printer id then by schema name
        policies = sorted(policies,
                key=lambda k: (
                    list(k.get('targetKey', {}).get('additionalTargetKeys', {}).values()),
                    k.get('value', {}).get('policySchema', '')))
        printed_ids = []
        for policy in policies:
            print()
            name = policy.get('value', {}).get('policySchema', '')
            for key, val in policy['targetKey'].get('additionalTargetKeys', {}).items():
                additional_id = f'{key} - {val}'
                if additional_id not in printed_ids:
                    print(f'  {additional_id}')
                    printed_ids.append(additional_id)
                    spacing = '    '
            print(f'{spacing}{name}')
            values = policy.get('value', {}).get('value', {})
            for setting, value in values.items():
                # Handle TYPE_MESSAGE fields with durations, values, counts and timeOfDay as special cases
                schema = CHROME_SCHEMA_TYPE_MESSAGE.get(name, {}).get(setting.lower())
                if schema and setting == schema['casedField']:
                    vtype = schema['type']
                    if vtype in {'duration', 'value'}:
                        value = value.get(vtype, '')
                        if value:
                            if value.endswith('s'):
                                value = value[:-1]
                            value = int(value) // schema['scale']
                    elif vtype == 'count':
                        pass
                    else: ##timeOfDay
                        hours = value.get(vtype, {}).get('hours', 0)
                        minutes = value.get(vtype, {}).get('minutes', 0)
                        value = f'{hours:02}:{minutes:02}'
                elif isinstance(value, str) and value.find('_ENUM_') != -1:
                    value = value.split('_ENUM_')[-1]
                print(f'{spacing}{setting}: {value}')
Ejemplo n.º 17
0
def getMatterItem(v, nameOrID):
    matterId = convertMatterNameToID(v, nameOrID)
    if not matterId:
        controlflow.system_error_exit(4, f'could not find matter {nameOrID}')
    return matterId
Ejemplo n.º 18
0
def print_count():
    v = buildGAPIObject()
    query_discovery = v._rootDesc['schemas']['Query']
    matterId = None
    operation_wait = 15
    query = None
    body = {'view': 'ALL'}
    name = None
    todrive = False
    i = 3
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'matter':
            matterId = getMatterItem(v, sys.argv[i + 1])
            i += 2
        elif myarg == 'operation':
            name = sys.argv[i + 1]
            i += 2
        elif myarg == 'todrive':
            todrive = True
            i += 1
        elif myarg in QUERY_ARGS:
            query, i = _build_query(query, myarg, i, query_discovery)
        elif myarg == 'wait':
            operation_wait = int(sys.argv[i + 1])
            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 count.')
    if name:
        operation = {'name': name}
    else:
        _validate_query(query, query_discovery)
        body['query'] = query
        operation = gapi.call(v.matters(),
                              'count',
                              matterId=matterId,
                              body=body)
    print(f'Watching operation {operation["name"]}...')
    while not operation.get('done'):
        print(
            f' operation {operation["name"]} is not done yet. Checking again in {operation_wait} seconds'
        )
        sleep(operation_wait)
        operation = gapi.call(v.operations(), 'get', name=operation['name'])
    response = operation.get('response', {})
    query = operation['metadata']['query']
    search_method = query.get('searchMethod')
    # ARGH count results don't include accounts with zero items.
    # so we keep track of which accounts we searched and can report
    # zero data for them.
    if search_method == 'ACCOUNT':
        query_accounts = query.get('accountInfo', [])
    elif search_method == 'ENTIRE_ORG':
        query_accounts = gam.getUsersToModify('all', 'users')
    elif search_method == 'ORG_UNIT':
        org_unit = query['orgUnitInfo']['orgUnitId']
        query_accounts = gam.getUsersToModify('ou', org_unit)
    mailcounts = response.get('mailCountResult', {})
    groupcounts = response.get('groupsCountResult', {})
    csv_rows = []
    for a_count in [mailcounts, groupcounts]:
        for errored_account in a_count.get('accountCountErrors', []):
            account = errored_account.get('account')
            csv_rows.append({
                'account': account,
                'error': errored_account.get('errorType')
            })
            if account in query_accounts: query_accounts.remove(account)
        for account in a_count.get('nonQueryableAccounts', []):
            csv_rows.append({
                'account': account,
                'error': 'Not queried because not on hold'
            })
            if account in query_accounts: query_accounts.remove(account)
        for account in a_count.get('accountCounts', []):
            email = account.get('account', {}).get('email', '')
            csv_rows.append({'account': email, 'count': account.get('count')})
            if email in query_accounts: query_accounts.remove(email)
    for account in query_accounts:
        csv_rows.append({'account': account, 'count': 0})
    titles = ['account', 'count', 'error']
    display.write_csv_file(csv_rows, titles, 'Vault Counts', todrive)
Ejemplo n.º 19
0
def updateMatter(action=None):
    v = buildGAPIObject()
    matterId = getMatterItem(v, sys.argv[3])
    body = {}
    action_kwargs = {'body': {}}
    add_collaborators = []
    remove_collaborators = []
    cd = None
    i = 4
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'action':
            action = sys.argv[i + 1].lower()
            if action not in VAULT_MATTER_ACTIONS:
                controlflow.system_error_exit(3, f'allowed actions are ' \
                    f'{", ".join(VAULT_MATTER_ACTIONS)}, got {action}')
            i += 2
        elif myarg == 'name':
            body['name'] = sys.argv[i + 1]
            i += 2
        elif myarg == 'description':
            body['description'] = sys.argv[i + 1]
            i += 2
        elif myarg in ['addcollaborator', 'addcollaborators']:
            if not cd:
                cd = gam.buildGAPIObject('directory')
            add_collaborators.extend(validateCollaborators(
                sys.argv[i + 1], cd))
            i += 2
        elif myarg in ['removecollaborator', 'removecollaborators']:
            if not cd:
                cd = gam.buildGAPIObject('directory')
            remove_collaborators.extend(
                validateCollaborators(sys.argv[i + 1], cd))
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], 'gam update matter')
    if action == 'delete':
        action_kwargs = {}
    if body:
        print(f'Updating matter {sys.argv[3]}...')
        if 'name' not in body or 'description' not in body:
            # bah, API requires name/description to be sent
            # on update even when it's not changing
            result = gapi.call(v.matters(),
                               'get',
                               matterId=matterId,
                               view='BASIC')
            body.setdefault('name', result['name'])
            body.setdefault('description', result.get('description'))
        gapi.call(v.matters(), 'update', body=body, matterId=matterId)
    if action:
        print(f'Performing {action} on matter {sys.argv[3]}')
        gapi.call(v.matters(), action, matterId=matterId, **action_kwargs)
    for collaborator in add_collaborators:
        print(f' adding collaborator {collaborator["email"]}')
        body = {
            'matterPermission': {
                'role': 'COLLABORATOR',
                'accountId': collaborator['id']
            }
        }
        gapi.call(v.matters(), 'addPermissions', matterId=matterId, body=body)
    for collaborator in remove_collaborators:
        print(f' removing collaborator {collaborator["email"]}')
        gapi.call(v.matters(),
                  'removePermissions',
                  matterId=matterId,
                  body={'accountId': collaborator['id']})
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
def get_delta_time(argstr):
    deltaTime = get_delta(argstr, DELTA_TIME_PATTERN)
    if deltaTime is None:
        controlflow.system_error_exit(
            2, f'expected a <{DELTA_TIME_FORMAT_REQUIRED}>; got {argstr}')
    return deltaTime
Ejemplo n.º 22
0
def move():
    cbcm = build()
    body = {'resource_ids': []}
    i = 3
    resource_ids = []
    batch_size = 600
    while i < len(sys.argv):
        myarg = sys.argv[i].lower().replace('_', '')
        if myarg == 'ids':
            resource_ids.extend(sys.argv[i + 1].split(','))
            i += 2
        elif myarg == 'query':
            query = sys.argv[i + 1]
            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='BASIC',
                fields='browsers(deviceId),nextPageToken')
            ids = [browser['deviceId'] for browser in browsers]
            resource_ids.extend(ids)
            i += 2
        elif myarg == 'file':
            with fileutils.open_file(sys.argv[i + 1],
                                     strip_utf_bom=True) as filed:
                for row in filed:
                    rid = row.strip()
                    if rid:
                        resource_ids.append(rid)
            i += 2
        elif myarg == 'csvfile':
            drive, fname_column = os.path.splitdrive(sys.argv[i + 1])
            if fname_column.find(':') == -1:
                controlflow.system_error_exit(
                    2, 'Expected csvfile FileName:FieldName')
            (filename, column) = fname_column.split(':')
            with fileutils.open_file(drive + filename) as filed:
                input_file = csv.DictReader(filed, restval='')
                if column not in input_file.fieldnames:
                    controlflow.csv_field_error_exit(column,
                                                     input_file.fieldnames)
                for row in input_file:
                    rid = row[column].strip()
                    if rid:
                        resource_ids.append(rid)
            i += 2
        elif myarg in ['ou', 'orgunit', 'org']:
            org_unit = gapi_directory_orgunits.getOrgUnitItem(sys.argv[i + 1])
            body['org_unit_path'] = org_unit
            i += 2
        elif myarg == 'batchsize':
            batch_size = int(sys.argv[i + 1])
            i += 2
        else:
            controlflow.invalid_argument_exit(sys.argv[i], 'gam move browsers')
    if 'org_unit_path' not in body:
        controlflow.missing_argument_exit('ou', 'gam move browsers')
    elif not resource_ids:
        controlflow.missing_argument_exit('query or ids', 'gam move browsers')
    # split moves into max 600 devices per batch
    for chunk in range(0, len(resource_ids), batch_size):
        body['resource_ids'] = resource_ids[chunk:chunk + batch_size]
        print(f' moving {len(body["resource_ids"])} browsers to ' \
                       f'{body["org_unit_path"]}')
        gapi.call(cbcm.chromebrowsers(),
                  'moveChromeBrowsersToOu',
                  customer=GC_Values[GC_CUSTOMER_ID],
                  body=body)
Ejemplo n.º 23
0
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
    useNewExport = 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], state='OPEN')
            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 == 'usenewexport':
            useNewExport = 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.')
    _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
        if useNewExport is not None:
            body['exportOptions'][options_field]['useNewExport'] = useNewExport
    results = gapi.call(v.matters().exports(),
                        'create',
                        matterId=matterId,
                        body=body)
    print(f'Created export {results["id"]}')
    display.print_json(results)
Ejemplo n.º 24
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)