예제 #1
0
    def StartHunt(cls, args=None, runner_args=None, **kwargs):
        """This class method creates new hunts."""
        # Build the runner args from the keywords.
        if runner_args is None:
            runner_args = HuntRunnerArgs()

        cls.FilterArgsFromSemanticProtobuf(runner_args, kwargs)

        # Is the required flow a known flow?
        if (runner_args.hunt_name not in cls.classes or not aff4.issubclass(
                cls.classes[runner_args.hunt_name], GRRHunt)):
            raise RuntimeError("Unable to locate hunt %s" %
                               runner_args.hunt_name)

        # Make a new hunt object and initialize its runner.
        hunt_obj = aff4.FACTORY.Create(None,
                                       runner_args.hunt_name,
                                       mode="w",
                                       token=runner_args.token)

        # Hunt is called using keyword args. We construct an args proto from the
        # kwargs..
        if hunt_obj.args_type and args is None:
            args = hunt_obj.args_type()
            cls.FilterArgsFromSemanticProtobuf(args, kwargs)

        if hunt_obj.args_type and not isinstance(args, hunt_obj.args_type):
            raise RuntimeError("Hunt args must be instance of %s" %
                               hunt_obj.args_type)

        if kwargs:
            raise type_info.UnknownArg("Unknown parameters to StartHunt: %s" %
                                       kwargs)

        # Store the hunt args in the state.
        hunt_obj.state.Register("args", args)

        # Hunts are always created in the paused state. The runner method Start
        # should be called to start them.
        hunt_obj.Set(hunt_obj.Schema.STATE("PAUSED"))

        runner = hunt_obj.CreateRunner(runner_args=runner_args)
        # Allow the hunt to do its own initialization.
        runner.RunStateMethod("Start")

        hunt_obj.Flush()

        try:
            flow_name = args.flow_runner_args.flow_name
        except AttributeError:
            flow_name = ""

        event = flow.AuditEvent(user=runner_args.token.username,
                                action="HUNT_CREATED",
                                urn=hunt_obj.urn,
                                flow_name=flow_name,
                                description=runner_args.description)
        flow.Events.PublishEvent("Audit", event, token=runner_args.token)

        return hunt_obj
예제 #2
0
    def StartHunt(cls, args=None, runner_args=None, **kwargs):
        """This class method creates new hunts."""
        # Build the runner args from the keywords.
        if runner_args is None:
            runner_args = HuntRunnerArgs()

        cls._FilterArgsFromSemanticProtobuf(runner_args, kwargs)

        # Is the required flow a known flow?
        if (runner_args.hunt_name not in cls.classes and not aff4.issubclass(
                GRRHunt, cls.classes[runner_args.hunt_name])):
            raise RuntimeError("Unable to locate hunt %s" %
                               runner_args.hunt_name)

        # Make a new hunt object and initialize its runner.
        hunt_obj = aff4.FACTORY.Create(None,
                                       runner_args.hunt_name,
                                       mode="w",
                                       token=runner_args.token)

        # Hunt is called using keyword args. We construct an args proto from the
        # kwargs..
        if hunt_obj.args_type and args is None:
            args = hunt_obj.args_type()
            cls._FilterArgsFromSemanticProtobuf(args, kwargs)

        if hunt_obj.args_type and not isinstance(args, hunt_obj.args_type):
            raise RuntimeError("Hunt args must be instance of %s" %
                               hunt_obj.args_type)

        if kwargs:
            raise type_info.UnknownArg("Unknown parameters to StartHunt: %s" %
                                       kwargs)

        # Store the hunt args in the state.
        hunt_obj.state.Register("args", args)

        # Hunts are always created in the paused state. The runner method Start
        # should be called to start them.
        hunt_obj.Set(hunt_obj.Schema.STATE("PAUSED"))

        with hunt_obj.CreateRunner(runner_args=runner_args) as runner:
            # Allow the hunt to do its own initialization.
            runner.RunStateMethod("Start")

        hunt_obj.Flush()

        return hunt_obj
예제 #3
0
    def StartFlow(cls,
                  args=None,
                  runner_args=None,
                  parent_flow=None,
                  sync=True,
                  token=None,
                  **kwargs):
        """The main factory function for Creating and executing a new flow.

    Args:

      args: An arg protocol buffer which is an instance of the required flow's
        args_type class attribute.

      runner_args: an instance of FlowRunnerArgs() protocol buffer which is used
        to initialize the runner for this flow.

      parent_flow: A parent flow or None if this is a top level flow.

      sync: If True, the Start method of this flow will be called
         inline. Otherwise we schedule the starting of this flow on another
         worker.

      token: Security credentials token identifying the user.

      **kwargs: If args or runner_args are not specified, we construct these
        protobufs from these keywords.

    Returns:
      the session id of the flow.

    Raises:
      RuntimeError: Unknown or invalid parameters were provided.
    """
        # Build the runner args from the keywords.
        if runner_args is None:
            runner_args = rdf_flows.FlowRunnerArgs()

        cls.FilterArgsFromSemanticProtobuf(runner_args, kwargs)

        # When asked to run a flow in the future this implied it will run
        # asynchronously.
        if runner_args.start_time:
            sync = False

        # Is the required flow a known flow?
        if runner_args.flow_name not in GRRFlow.classes:
            stats.STATS.IncrementCounter("grr_flow_invalid_flow_count")
            raise RuntimeError("Unable to locate flow %s" %
                               runner_args.flow_name)

        # If no token is specified, raise.
        if not token:
            raise access_control.UnauthorizedAccess(
                "A token must be specified.")

        # For the flow itself we use a supervisor token.
        token = token.SetUID()

        # Extend the expiry time of this token indefinitely. Python on Windows only
        # supports dates up to the year 3000.
        token.expiry = rdfvalue.RDFDatetime.FromHumanReadable("2997-01-01")

        flow_cls = aff4.AFF4Object.classes.get(runner_args.flow_name)
        if flow_cls.category and not runner_args.client_id:
            raise RuntimeError(
                "Flow with category (user-visible flow) has to be "
                "started on a client, but runner_args.client_id "
                "is missing.")

        # We create an anonymous AFF4 object first, The runner will then generate
        # the appropriate URN.
        flow_obj = aff4.FACTORY.Create(None, flow_cls, token=token)

        # Now parse the flow args into the new object from the keywords.
        if args is None:
            args = flow_obj.args_type()

        cls.FilterArgsFromSemanticProtobuf(args, kwargs)

        # Check that the flow args are valid.
        args.Validate()

        # Store the flow args.
        flow_obj.args = args
        flow_obj.runner_args = runner_args

        # At this point we should exhaust all the keyword args. If any are left
        # over, we do not know what to do with them so raise.
        if kwargs:
            raise type_info.UnknownArg("Unknown parameters to StartFlow: %s" %
                                       kwargs)

        # Create a flow runner to run this flow with.
        if parent_flow:
            parent_runner = parent_flow.runner
        else:
            parent_runner = None

        runner = flow_obj.CreateRunner(parent_runner=parent_runner,
                                       runner_args=runner_args)

        logging.info(u"Scheduling %s(%s) on %s", flow_obj.urn,
                     runner_args.flow_name, runner_args.client_id)

        if sync:
            # Just run the first state inline. NOTE: Running synchronously means
            # that this runs on the thread that starts the flow. The advantage is
            # that that Start method can raise any errors immediately.
            flow_obj.Start()
        else:
            # Running Asynchronously: Schedule the start method on another worker.
            runner.CallState(next_state="Start",
                             start_time=runner_args.start_time)

        # The flow does not need to actually remain running.
        if not runner.OutstandingRequests():
            flow_obj.Terminate()

        flow_obj.Close()

        # Publish an audit event, only for top level flows.
        if parent_flow is None:
            events.Events.PublishEvent("Audit",
                                       events.AuditEvent(
                                           user=token.username,
                                           action="RUN_FLOW",
                                           flow_name=runner_args.flow_name,
                                           urn=flow_obj.urn,
                                           client=runner_args.client_id),
                                       token=token)

        return flow_obj.urn
예제 #4
0
  def StartFlow(cls, args=None, runner_args=None,  # pylint: disable=g-bad-name
                parent_flow=None, sync=True, **kwargs):
    """The main factory function for Creating and executing a new flow.

    Args:

      args: An arg protocol buffer which is an instance of the required flow's
        args_type class attribute.

      runner_args: an instance of FlowRunnerArgs() protocol buffer which is used
        to initialize the runner for this flow.

      parent_flow: A parent flow or None if this is a top level flow.

      sync: If True, the Start method of this flow will be called
         inline. Otherwise we schedule the starting of this flow on another
         worker.

      **kwargs: If args or runner_args are not specified, we construct these
        protobufs from these keywords.

    Returns:
      the session id of the flow.

    Raises:
      RuntimeError: Unknown or invalid parameters were provided.
    """

    # Build the runner args from the keywords.
    if runner_args is None:
      runner_args = rdf_flows.FlowRunnerArgs()

    cls.FilterArgsFromSemanticProtobuf(runner_args, kwargs)

    # When asked to run a flow in the future this implied it will run
    # asynchronously.
    if runner_args.start_time:
      sync = False

    # Is the required flow a known flow?
    if runner_args.flow_name not in GRRFlow.classes:
      stats.STATS.IncrementCounter("grr_flow_invalid_flow_count")
      raise RuntimeError("Unable to locate flow %s" % runner_args.flow_name)

    # If no token is specified, use the default token.
    if not runner_args.HasField("token"):
      if data_store.default_token is None:
        raise access_control.UnauthorizedAccess("A token must be specified.")

      runner_args.token = data_store.default_token.Copy()

    # Make sure we are allowed to run this flow. If not, we raise here. We
    # respect SUID (supervisor) if it is already set. SUID cannot be set by the
    # user since it isn't part of the ACLToken proto.
    data_store.DB.security_manager.CheckIfCanStartFlow(
        runner_args.token,
        runner_args.flow_name,
        with_client_id=runner_args.client_id)

    flow_cls = GRRFlow.GetPlugin(runner_args.flow_name)
    # If client id was specified and flow doesn't have exemption from ACL
    # checking policy, then check that the user has access to the client
    # where the flow is going to run.
    if flow_cls.ACL_ENFORCED and runner_args.client_id:
      data_store.DB.security_manager.CheckClientAccess(runner_args.token,
                                                       runner_args.client_id)

    # For the flow itself we use a supervisor token.
    token = runner_args.token.SetUID()

    # Extend the expiry time of this token indefinitely. Python on Windows only
    # supports dates up to the year 3000, this number corresponds to July, 2997.
    token.expiry = 32427003069 * rdfvalue.RDFDatetime.converter

    # We create an anonymous AFF4 object first, The runner will then generate
    # the appropriate URN.
    flow_obj = aff4.FACTORY.Create(
        None, aff4.AFF4Object.classes.get(runner_args.flow_name), token=token)

    # Now parse the flow args into the new object from the keywords.
    if args is None:
      args = flow_obj.args_type()

    cls.FilterArgsFromSemanticProtobuf(args, kwargs)

    # Check that the flow args are valid.
    args.Validate()

    # Store the flow args.
    flow_obj.args = args
    flow_obj.runner_args = runner_args

    # At this point we should exhaust all the keyword args. If any are left
    # over, we do not know what to do with them so raise.
    if kwargs:
      raise type_info.UnknownArg("Unknown parameters to StartFlow: %s" % kwargs)

    # Create a flow runner to run this flow with.
    if parent_flow:
      parent_runner = parent_flow.runner
    else:
      parent_runner = None

    runner = flow_obj.CreateRunner(
        parent_runner=parent_runner, runner_args=runner_args)

    logging.info(u"Scheduling %s(%s) on %s", flow_obj.urn,
                 runner_args.flow_name, runner_args.client_id)

    if sync:
      # Just run the first state inline. NOTE: Running synchronously means
      # that this runs on the thread that starts the flow. The advantage is
      # that that Start method can raise any errors immediately.
      flow_obj.Start()
    else:
      # Running Asynchronously: Schedule the start method on another worker.
      runner.CallState(next_state="Start", start_time=runner_args.start_time)

    # The flow does not need to actually remain running.
    if not runner.OutstandingRequests():
      flow_obj.Terminate()

    flow_obj.Close()

    # Publish an audit event, only for top level flows.
    if parent_flow is None:
      events.Events.PublishEvent(
          "Audit",
          events.AuditEvent(
              user=token.username,
              action="RUN_FLOW",
              flow_name=runner_args.flow_name,
              urn=flow_obj.urn,
              client=runner_args.client_id),
          token=token)

    return flow_obj.urn