예제 #1
0
    def import_timeline(self, filename):
        """Import a Plaso, CSV or JSONL file.

        Args:
            filename (str): Filename of the file to be imported.

        Raises:
            TimeoutError if import takes too long.
        """
        file_path = os.path.join(TEST_DATA_DIR, filename)
        print('Importing: {0:s}'.format(file_path))

        with importer.ImportStreamer() as streamer:
            streamer.set_sketch(self.sketch)
            streamer.set_timeline_name(file_path)
            streamer.add_file(file_path)
            timeline = streamer.timeline

        # Poll the timeline status and wait for the timeline to be ready
        max_time_seconds = 600  # Timeout after 10min
        sleep_time_seconds = 5  # Sleep between API calls
        max_retries = max_time_seconds / sleep_time_seconds
        retry_count = 0
        while True:
            if retry_count >= max_retries:
                raise TimeoutError
            _ = timeline.lazyload_data(refresh_cache=True)
            status = timeline.status
            # TODO: Do something with other statuses? (e.g. failed)
            if status == 'ready':
                break
            retry_count += 1
            time.sleep(sleep_time_seconds)
예제 #2
0
  def Process(self):
    """Executes a Timesketch export."""
    if not self.timesketch_api:
      message = 'Could not connect to Timesketch server'
      self.ModuleError(message, critical=True)

    sketch = self.state.GetFromCache('timesketch_sketch')
    if not sketch:
      sketch = self.timesketch_api.get_sketch(self.sketch_id)

    recipe_name = self.state.recipe.get('name', 'no_recipe')
    input_names = []
    for file_container in self.state.GetContainers(containers.File):
      description = file_container.name
      if not description:
        continue
      name = description.rpartition('.')[0]
      name = name.replace(' ', '_').replace('-', '_')
      input_names.append(name)

    if input_names:
      timeline_name = '{0:s}_{1:s}'.format(
          recipe_name, '_'.join(input_names))
    else:
      timeline_name = recipe_name

    with importer.ImportStreamer() as streamer:
      streamer.set_sketch(sketch)
      streamer.set_timeline_name(timeline_name)

      for file_container in self.state.GetContainers(containers.File):
        path = file_container.path
        streamer.add_file(path)

    api_root = sketch.api.api_root
    host_url = api_root.partition('api/v1')[0]
    sketch_url = '{0:s}sketches/{1:d}/'.format(host_url, sketch.id)
    message = 'Your Timesketch URL is: {0:s}'.format(sketch_url)
    container = containers.Report(
        module_name='TimesketchExporter',
        text=message,
        text_format='markdown')
    self.state.StoreContainer(container)

    for analyzer in self._analyzers:
      results = sketch.run_analyzer(
          analyzer_name=analyzer, timeline_name=timeline_name)
      if not results:
        self.logger.info('Analyzer [{0:s}] not able to run on {1:s}'.format(
            analyzer, timeline_name))
        continue
      session_id = results.id
      if not session_id:
        self.logger.info(
            'Analyzer [{0:s}] didn\'t provide any session data'.format(
                analyzer))
        continue
      self.logger.info('Analyzer: {0:s} is running, session ID: {1:d}'.format(
          analyzer, session_id))
      self.logger.info(results.status_string)
예제 #3
0
def upload_file(
        my_sketch: sketch.Sketch, config_dict: Dict[str, any],
        file_path: str) -> str:
    """Uploads a file to Timesketch.

    Args:
        my_sketch (sketch.Sketch): a sketch object to point to the sketch the
            data will be imported to.
        config_dict (dict): dict with settings for the importer.
        file_path (str): the path to the file to upload.

    Returns:
        A string with results (whether successful or not).
    """
    if not my_sketch or not hasattr(my_sketch, 'id'):
        return 'Sketch needs to be set'

    _, _, file_extension = file_path.rpartition('.')
    if file_extension.lower() not in ('plaso', 'mans', 'csv', 'jsonl'):
        return (
            'File needs to have one of the following extensions: '
            '.plaso, .mans, .csv, '
            '.jsonl (not {0:s})').format(file_extension.lower())

    with importer.ImportStreamer() as streamer:
        streamer.set_sketch(my_sketch)

        format_string = config_dict.get('message_format_string')
        if format_string:
            streamer.set_message_format_string(format_string)
        timeline_name = config_dict.get('timeline_name')
        if timeline_name:
            streamer.set_timeline_name(timeline_name)
        index_name = config_dict.get('index_name')
        if index_name:
            streamer.set_index_name(index_name)
        time_desc = config_dict.get('timestamp_description')
        if time_desc:
            streamer.set_timestamp_description(time_desc)

        log_config_file = config_dict.get('log_config_file', '')
        streamer.set_config_file(log_config_file)

        entry_threshold = config_dict.get('entry_threshold')
        if entry_threshold:
            streamer.set_entry_threshold(entry_threshold)
        size_threshold = config_dict.get('size_threshold')
        if size_threshold:
            streamer.set_filesize_threshold(size_threshold)

        streamer.add_file(file_path)

    return 'File got successfully uploaded to sketch: {0:d}'.format(
        my_sketch.id)
예제 #4
0
def importer(ctx, name, timeout, file_path):
    """Import timeline.

    Args:
        ctx: Click CLI context object.
        name: Name of the timeline to create.
        timeout: Seconds to wait for indexing.
        file_path: File path to the file to import.
    """
    sketch = ctx.obj.sketch
    if not name:
        name = click.format_filename(file_path, shorten=True)

    timeline = None
    with import_client.ImportStreamer() as streamer:
        click.echo("Uploading to server .. ", nl=False)
        streamer.set_sketch(sketch)
        streamer.set_timeline_name(name)
        streamer.set_provider("Timesketch CLI client")
        # TODO: Consider using the whole command as upload context instead
        # of the file path.
        streamer.set_upload_context(file_path)
        streamer.add_file(file_path)
        timeline = streamer.timeline
        if not timeline:
            click.echo("Error creating timeline, please try again.")
            sys.exit(1)

        click.echo("Done")

    # Poll the timeline status and wait for the timeline to be ready
    click.echo("Indexing .. ", nl=False)
    max_time_seconds = timeout
    sleep_time_seconds = 5  # Sleep between API calls
    max_retries = max_time_seconds / sleep_time_seconds
    retry_count = 0
    while True:
        if retry_count >= max_retries:
            click.echo(
                (
                    "WARNING: The command timed out before indexing finished. "
                    "The timeline will continue to be indexed in the background"
                )
            )
            break
        status = timeline.status
        # TODO: Do something with other statuses? (e.g. failed)
        if status == "ready":
            click.echo("Done")
            break
        retry_count += 1
        time.sleep(sleep_time_seconds)

    click.echo(f"Timeline imported: {timeline.name}")
예제 #5
0
def timesketch_upload_file(data: Text, name: Optional[Text] = ''):
    """Upload a file to Timesketch.

  Args:
    data (str): Path to the file that's about to be uploaded.
    name (str): Name of the timeline.
  """
    if not os.path.isfile(data):
        print('File [{0:s}] does not exist.'.format(data))
        return

    connect()
    state_obj = state.state()
    sketch = state_obj.get_from_cache('timesketch_sketch')
    result = None

    if not name:
        name = data.split(os.sep)[-1]
        first, _, last = name.rpartition('.')
        name = first or last
        name = name.replace(' ', '_').replace('-', '_')

    timeline = None
    with importer.ImportStreamer() as streamer:
        streamer.set_sketch(sketch)
        streamer.set_timeline_name(name)

        # Set the file size to 20Mb before the file is split.
        streamer.set_filesize_threshold(20971520)
        streamer.add_file(data)

        # Force a flush.
        streamer.flush()

        result = streamer.response
        timeline = streamer.timeline

    if not result:
        print('Unable to upload data.')
        return

    if not timeline.name:
        print('Unable to get a timeline.')
        return

    print(f'Timeline: {timeline.name}{timeline.description}\n'
          f'Status: {timeline.status}')
예제 #6
0
def timesketch_upload_file(data: Text, name: Optional[Text] = ''):
    """Upload a file to Timesketch.

  Args:
    data (str): Path to the file that's about to be uploaded.
    name (str): Name of the timeline.
  """
    if not os.path.isfile(data):
        print('File [{0:s}] does not exist.'.format(data))
        return

    connect()
    state_obj = state.state()
    sketch = state_obj.get_from_cache('timesketch_sketch')
    result = None

    if not name:
        name = data.split(os.sep)[-1]
        first, _, last = name.rpartition('.')
        name = first or last
        name = name.replace(' ', '_').replace('-', '_')

    with importer.ImportStreamer() as streamer:
        streamer.set_sketch(sketch)
        streamer.set_timeline_name(name)

        # Set the file size to 20Mb before the file is split.
        streamer.set_filesize_threshold(20971520)
        streamer.add_file(data)
        result = streamer.response

    if not result:
        print('Unable to upload data.')
        return

    for timesketch_object in result.get('objects', []):
        if not timesketch_object:
            continue
        print('Timeline: {0:s}\nStatus: {1:s}'.format(
            timesketch_object.get('description'), ','.join(
                [x.get('status') for x in timesketch_object.get('status')])))
예제 #7
0
    def to_timesketch(self):
        """
            to_timesketch: push dataframe to timesketch
        """
        import_helper = helper.ImportHelper()

        with importer.ImportStreamer() as streamer:
            streamer.set_sketch(self.sketch)
            streamer.set_provider("MansToEs")
            streamer.set_config_helper(import_helper)
            streamer.set_timeline_name(self.timeline_name)
            for file in glob(self.folder_path + "/tmp__*.json"):
                df = pd.read_json(file,
                                  orient="records",
                                  lines=True,
                                  dtype=False)
                filetype = file.split("tmp___")[-1].split(".")[0].split("_")[0]
                streamer.set_upload_context(filetype)
                streamer.add_data_frame(df, part_of_iter=True)
            if self.exd_alerts:
                for alert in self.exd_alerts:
                    streamer.set_upload_context("EXD alerts")
                    streamer.add_dict(alert)
        logging.debug("[MAIN] Bulk timesketch push [✔]")
예제 #8
0
def timesketch_upload_data(data: pd.DataFrame,
                           name: Optional[Text] = '',
                           format_message_string: Optional[Text] = ''):
    """Upload a data frame to TimeSketch.

  Args:
    data (pandas.core.frame.DataFrame): the DataFrame to upload.
    name (str): the name used for the timeline in Timesketch.
    format_message_string (str): formatting string for the message column of
        the data frame, eg: "{src_ip:s} to {dst_ip:s}, {bytes:d} bytes
        transferred"'

  Raises:
    ValueError: if the dataframe cannot be uploaded to Timesketch or the
        data is invalid.
  """
    if not isinstance(data, pd.DataFrame):
        raise ValueError(
            ('The data attribute is not a pandas DataFrame, please use curly '
             'braces to expand variables.'))

    if not name:
        name = 'unknown_timeline'

    connect()
    state_obj = state.state()

    sketch = state_obj.get_from_cache('timesketch_sketch')
    if not sketch:
        raise ValueError('Unable to upload data frame, need to set sketch.')

    result = None

    import_helper = helper.ImportHelper()
    timeline = None
    with importer.ImportStreamer() as streamer:
        streamer.set_sketch(sketch)

        if 'data_type' not in data:
            data_type = utils.ask_question('What is the value of [data_type]?',
                                           input_type=str)
            if data_type:
                streamer.set_data_type(data_type)
        else:
            data_types = data.data_type.unique()
            data_type = data_types[0]

        columns = list(data.columns)
        streamer.set_config_helper(import_helper)
        import_helper.configure_streamer(streamer,
                                         data_type=data_type,
                                         columns=columns)

        if format_message_string:
            streamer.set_message_format_string(format_message_string)

        streamer.set_timeline_name(name)

        streamer.add_data_frame(data)
        streamer.flush()
        result = streamer.response
        timeline = streamer.timeline

    if not result:
        print('Unable to upload data.')
        return

    if not timeline.name:
        print('Unable to import the timeline.')
        return

    print(
        f'Timeline: [{timeline.id}]{timeline.name} - {timeline.description}\n'
        f'Status: {timeline.status}')
예제 #9
0
def upload_file(my_sketch: sketch.Sketch, config_dict: Dict[str, any],
                file_path: str) -> str:
    """Uploads a file to Timesketch.

    Args:
        my_sketch (sketch.Sketch): a sketch object to point to the sketch the
            data will be imported to.
        config_dict (dict): dict with settings for the importer.
        file_path (str): the path to the file to upload.

    Returns:
        A tuple with the timeline object (timeline.Timeline) or None if not
        able to upload the timeline as well as the celery task identification
        for the indexing.
    """
    if not my_sketch or not hasattr(my_sketch, 'id'):
        return 'Sketch needs to be set'

    _, _, file_extension = file_path.rpartition('.')
    if file_extension.lower() not in ('plaso', 'csv', 'jsonl'):
        return ('File needs to have one of the following extensions: '
                '.plaso, .csv, '
                '.jsonl (not {0:s})').format(file_extension.lower())

    import_helper = helper.ImportHelper()
    import_helper.add_config_dict(config_dict)

    log_config_file = config_dict.get('log_config_file', '')
    if log_config_file:
        import_helper.add_config(log_config_file)

    timeline = None
    task_id = ''
    logger.info('About to upload file.')
    with importer.ImportStreamer() as streamer:
        streamer.set_sketch(my_sketch)
        streamer.set_config_helper(import_helper)
        streamer.set_provider('CLI importer tool')

        format_string = config_dict.get('message_format_string')
        if format_string:
            streamer.set_message_format_string(format_string)

        timeline_name = config_dict.get('timeline_name')
        if timeline_name:
            streamer.set_timeline_name(timeline_name)

        index_name = config_dict.get('index_name')
        if index_name:
            streamer.set_index_name(index_name)

        time_desc = config_dict.get('timestamp_description')
        if time_desc:
            streamer.set_timestamp_description(time_desc)

        entry_threshold = config_dict.get('entry_threshold')
        if entry_threshold:
            streamer.set_entry_threshold(entry_threshold)

        size_threshold = config_dict.get('size_threshold')
        if size_threshold:
            streamer.set_filesize_threshold(size_threshold)

        data_label = config_dict.get('data_label')
        if data_label:
            streamer.set_data_label(data_label)

        context = config_dict.get('context')
        if context:
            streamer.set_upload_context(context)
        else:
            streamer.set_upload_context(' '.join(sys.argv))

        streamer.add_file(file_path)

        # Force a flush.
        streamer.flush()

        timeline = streamer.timeline
        task_id = streamer.celery_task_id

    logger.info('File upload completed.')
    return timeline, task_id