Exemple #1
0
def _run():
    """
    The script's body. Prints out backup usage data to stdout, which will be
    captured by Splunk.
    """
    server, _ = common.setup()
    params = {'active': 'true',
              'incBackupUsage': True,
              'incHistory': True}
    results = c42api.fetch_computers(server, params, insert_schema_version=True)
    timestamp = datetime.datetime.now().isoformat()
    for result in results:
        guid = result['guid']
        schema_version = result['schema_version']
        backup_usage_array = result['backupUsage']
        for backup_usage in backup_usage_array:
            backup_usage['guid'] = guid
            backup_usage['timestamp'] = timestamp
            backup_usage['schema_version'] = schema_version
        c42api.write_json_splunk(sys.stdout, backup_usage_array)
def _run():
    """
    The script's body. Prints out backup usage data to stdout, which will be
    captured by Splunk.
    """
    server, _ = common.setup()
    params = {'active': 'true', 'incBackupUsage': True, 'incHistory': True}
    results = c42api.fetch_computers(server,
                                     params,
                                     insert_schema_version=True)
    timestamp = datetime.datetime.now().isoformat()
    for result in results:
        guid = result['guid']
        schema_version = result['schema_version']
        backup_usage_array = result['backupUsage']
        for backup_usage in backup_usage_array:
            backup_usage['guid'] = guid
            backup_usage['timestamp'] = timestamp
            backup_usage['schema_version'] = schema_version
        c42api.write_json_splunk(sys.stdout, backup_usage_array)
def _run():
    """
    Run through Splunk
    """
    server, config_dict = common.setup()
    events_dir = os.path.join(common.app_home(), 'events')
    cursor_path = os.path.join(events_dir, 'security-lastRun')
    if not os.path.exists(events_dir):
        os.makedirs(events_dir)

    devices = config_dict['devices']

    device_guids = c42api.devices(server, devices)

    cursors_dict = _try_read_cursor(cursor_path)
    event_filters = []
    for device_guid in device_guids:
        try:
            cursor = cursors_dict[device_guid]
            event_filter = c42api.create_filter_by_cursor(cursor)
            event_filters.append(event_filter)
        except (KeyError, TypeError):
            event_filter = c42api.create_filter_by_utc_datetime(datetime.utcfromtimestamp(0), datetime.utcnow())
            event_filters.append(event_filter)

    guids_and_filters = zip(device_guids, event_filters)

    cursors_dict = cursors_dict if cursors_dict else {}
    for guid, cursor, detection_events in c42api.fetch_detection_events(server, guids_and_filters):
        if not cursor or not detection_events:
            continue
        cursors_dict[guid] = cursor

        c42api.write_json_splunk(sys.stdout, detection_events)

    _write_cursor(cursor_path, cursors_dict)
def _fetch_detection_events_for_device(authority, device_guid,
                                       detection_event_filter, cursor_dict):
    """
    Returns unbatched detection events and the corresponding min_timestamp string (ISO format)
    for the target device. 
    The detection events are gathered by sequentially requesting a page of events from the server.
    An empty 'next_cursor' means that there are no more pages to get.

    :param authority:               A Server object to make the API call to
    :param device_guid:             Device to retrieve events for
    :param detection_event_filter:  Filter to use when pulling detection events
    :param cursor_dict:             A dictionary of deviceGuid -> cursor. This dictionary is used
                                    to store the latest cursor returned before failing to retrieve the
                                    next page of events. This allows us to restart from the proper place
                                    next time the script runs (in the event a server goes down part way through).
    :return:                        returns a tuple of the nextMinTimestamp and the list of
                                     detection events -> (next_min_timestamp, detection_events)
    """
    event_count_for_device = 0
    try:
        security_plan = _fetch_security_plan(authority, device_guid)
    except RequestException:
        LOG.exception(
            "Unable to retrieve securityPlan for deviceGuid %s, from authority %s. Please ensure the authority is online",
            str(device_guid), str(authority))
        security_plan = None
    if not security_plan:
        LOG.info("No security plan found for device: %s", str(device_guid))
        return None, 0, cursor_dict
    LOG.debug("Found security plan")
    for storage_server, plan_uid in fetch_storage.storage_servers(
            authority, [security_plan['planUid']], device_guid):
        page_count = 0

        if not storage_server:
            LOG.info("No storage servers found were found for plan %s",
                     str(plan_uid))
            return None, event_count_for_device, cursor_dict

        # Finding a cursor in the dictionary implies that the last time the script ran, this device was only able to get
        # some of its pages of events, due to issues talking to the Code42 server(s). Start with the cursor form the last
        # successful request. Also, remove the cursor from dictionary. If this request fails, it will be re-added later on.
        cursor_from_interrupt_file = cursor_dict.pop(device_guid, None)
        if cursor_from_interrupt_file:
            detection_event_filter['cursor'] = cursor_from_interrupt_file
            LOG.info(
                "Using cursor from security-interrupted-lastCursor to get page that previously failed to be retrieved. Cursor: %s deviceGuid: %s",
                str(cursor_from_interrupt_file), str(device_guid))

        # Retrieve pages of events until an empty cursor is returned, signifying we have gotten the last page of events,
        # or a request for a page fails.
        while True:
            next_cursor, unbatched_event_page, request_successful = _get_page_of_events_from_server(
                storage_server, plan_uid, detection_event_filter)
            event_count_for_device += len(unbatched_event_page)
            page_count = page_count + 1

            # If the previous request was NOT successful, we need to store the cursor used in that request to the cursor_file.
            # Otherwise, we will not be able to re-try getting the page of events next time the script runs. If no cursor was used
            # we must have failed while requesting the first page. Do not store a cursor, as next time we will attempt to get the
            # first page again.
            if not request_successful and detection_event_filter.get('cursor'):
                cursor = detection_event_filter.get('cursor')
                cursor_dict[device_guid] = cursor

                LOG.debug(
                    "Page %d was not retrieved successfully. Storing cursor: %s in security-interrupted-lastCursor for deviceGuid: %s",
                    page_count, str(cursor), str(device_guid))

            # Stdout here so that we don't need to save all of the detection events for a single device.
            # After this point this page of events is 'in the splunk app'
            # NOTE: this must be done single-threaded
            c42api.write_json_splunk(sys.stdout, unbatched_event_page)

            if not next_cursor and request_successful:
                LOG.info(
                    "All pages of events retrieved for plan: %s, from server %s, total pages retrieved: %d",
                    plan_uid, storage_server, page_count)
                # This value will be used as the event_filter['minTs'] value the next time Splunk retrieves events for this device.
                # the value will be stored in a local cache until then.
                next_min_ISO_timestamp = detection_event_filter['maxTs']

                return next_min_ISO_timestamp, event_count_for_device, cursor_dict
            elif not next_cursor:
                LOG.info(
                    "Unable to get all pages of events for plan: %s, from server %s. The next time script runs, we will try to retrieve page %d again.",
                    plan_uid, str(storage_server), page_count)
                return None, event_count_for_device, cursor_dict

            # Replacing the previous cursor with the next_cursor allows us to get the next page of events with our next request.
            detection_event_filter['cursor'] = next_cursor

    return detection_event_filter['minTs'], event_count_for_device, cursor_dict