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
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
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
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