Пример #1
0
    def Handle(self, args, token=None):
        if not args.username:
            raise ValueError("username can't be empty.")

        user_urn = aff4.ROOT_URN.Add("users").Add(args.username)

        events.Events.PublishEvent("Audit",
                                   rdf_events.AuditEvent(user=token.username,
                                                         action="USER_UPDATE",
                                                         urn=user_urn),
                                   token=token)

        with aff4.FACTORY.Open(user_urn,
                               aff4_type=users.GRRUser,
                               mode="rw",
                               token=token) as fd:

            if args.HasField("password"):
                fd.SetPassword(args.password)

            if args.user_type == args.UserType.USER_TYPE_ADMIN:
                fd.AddLabels(["admin"], owner="GRR")
            elif args.user_type == args.UserType.USER_TYPE_STANDARD:
                fd.RemoveLabels(["admin"], owner="GRR")

            return api_user.ApiGrrUser().InitFromAff4Object(fd)
Пример #2
0
    def Handle(self, args, token=None):
        audit_description = ",".join([
            token.username + u"." + utils.SmartUnicode(name)
            for name in args.labels
        ])
        audit_events = []

        try:
            for api_client_id in args.client_ids:
                audit_events.append(
                    rdf_events.AuditEvent(
                        user=token.username,
                        action="CLIENT_ADD_LABEL",
                        flow_name="handler.ApiAddClientsLabelsHandler",
                        client=api_client_id.ToClientURN(),
                        description=audit_description))

            for api_client_id in args.client_ids:
                cid = unicode(api_client_id)
                try:
                    data_store.REL_DB.AddClientLabels(cid, token.username,
                                                      args.labels)
                    idx = client_index.ClientIndex()
                    idx.AddClientLabels(cid, args.labels)
                except db.UnknownClientError:
                    # TODO(amoser): Remove after data migration.
                    pass

        finally:
            events.Events.PublishMultipleEvents(
                {audit.AUDIT_EVENT: audit_events}, token=token)
Пример #3
0
def AddFakeAuditLog(description=None,
                    client=None,
                    user=None,
                    action=None,
                    flow_name=None,
                    urn=None,
                    router_method_name=None,
                    http_request_path=None,
                    token=None):
  events.Events.PublishEvent(
      "Audit",
      rdf_events.AuditEvent(
          description=description,
          client=client,
          urn=urn,
          user=user,
          action=action,
          flow_name=flow_name),
      token=token)

  if data_store.RelationalDBWriteEnabled():
    data_store.REL_DB.WriteAPIAuditEntry(
        rdf_objects.APIAuditEntry(
            username=user,
            router_method_name=router_method_name,
            http_request_path=http_request_path,
        ))
Пример #4
0
    def Handle(self, args, token=None):
        audit_description = ",".join([
            token.username + u"." + utils.SmartUnicode(name)
            for name in args.labels
        ])
        audit_events = []

        try:
            for client_id in args.client_ids:
                cid = unicode(client_id)
                data_store.REL_DB.RemoveClientLabels(cid, token.username,
                                                     args.labels)
                labels_to_remove = set(args.labels)
                existing_labels = data_store.REL_DB.ReadClientLabels(cid)
                for label in existing_labels:
                    labels_to_remove.discard(label.name)
                if labels_to_remove:
                    idx = client_index.ClientIndex()
                    idx.RemoveClientLabels(cid, labels_to_remove)

                audit_events.append(
                    rdf_events.AuditEvent(
                        user=token.username,
                        action="CLIENT_REMOVE_LABEL",
                        flow_name="handler.ApiRemoveClientsLabelsHandler",
                        client=client_id.ToClientURN(),
                        description=audit_description))
        finally:
            events.Events.PublishMultipleEvents(
                {audit.AUDIT_EVENT: audit_events}, token=token)
Пример #5
0
def AddUser(username, password=None, labels=None, token=None):
    """Implementation of the add_user command."""
    if not username:
        raise UserError("Cannot add user: User must have a non-empty name")

    token = data_store.GetDefaultToken(token)
    user_urn = "aff4:/users/%s" % username
    try:
        if aff4.FACTORY.Open(user_urn, users.GRRUser, token=token):
            raise UserError("Cannot add user %s: User already exists." %
                            username)
    except aff4.InstantiationError:
        pass

    fd = aff4.FACTORY.Create(user_urn, users.GRRUser, mode="rw", token=token)
    # Note this accepts blank passwords as valid.
    if password is None:
        password = getpass.getpass(
            prompt="Please enter password for user '%s': " % username)
    fd.SetPassword(password)

    if labels:
        fd.AddLabels(set(labels), owner="GRR")

    fd.Close()

    EPrint("Added user %s." % username)

    events.Events.PublishEvent("Audit",
                               rdf_events.AuditEvent(user=token.username,
                                                     action="USER_ADD",
                                                     urn=user_urn),
                               token=token)
Пример #6
0
    def Handle(self, args, token=None):
        if not args.username:
            raise ValueError("username can't be empty.")

        user_urn = aff4.ROOT_URN.Add("users").Add(args.username)

        events.Events.PublishEvent("Audit",
                                   rdf_events.AuditEvent(user=token.username,
                                                         action="USER_ADD",
                                                         urn=user_urn),
                                   token=token)

        if aff4.FACTORY.ExistsWithType(user_urn,
                                       aff4_type=users.GRRUser,
                                       token=token):
            raise access_control.UnauthorizedAccess(
                "Cannot add user %s: User already exists." % args.username)

        with aff4.FACTORY.Create(user_urn,
                                 aff4_type=users.GRRUser,
                                 mode="rw",
                                 token=token) as fd:

            if args.HasField("password"):
                fd.SetPassword(args.password)

            if args.user_type == args.UserType.USER_TYPE_ADMIN:
                fd.AddLabels(["admin"], owner="GRR")

            return api_user.ApiGrrUser().InitFromAff4Object(fd)
Пример #7
0
    def _CreateAuditEvent(self, event_action):
        flow_name = self.hunt_obj.args.flow_runner_args.flow_name

        event = rdf_events.AuditEvent(user=self.hunt_obj.token.username,
                                      action=event_action,
                                      urn=self.hunt_obj.urn,
                                      flow_name=flow_name,
                                      description=self.runner_args.description)
        events.Events.PublishEvent("Audit", event, token=self.hunt_obj.token)
Пример #8
0
    def testWriteAuditEventMultipleEvents(self):
        timestamp = rdfvalue.RDFDatetime.Now()

        self.db.WriteAuditEvent(
            rdf_events.AuditEvent(urn=rdfvalue.RDFURN("foo")))
        self.db.WriteAuditEvent(
            rdf_events.AuditEvent(urn=rdfvalue.RDFURN("bar")))
        self.db.WriteAuditEvent(
            rdf_events.AuditEvent(urn=rdfvalue.RDFURN("baz")))

        log = self.db.ReadAllAuditEvents()
        self.assertEqual(len(log), 3)
        self.assertEqual(log[0].urn, rdfvalue.RDFURN("foo"))
        self.assertEqual(log[1].urn, rdfvalue.RDFURN("bar"))
        self.assertEqual(log[2].urn, rdfvalue.RDFURN("baz"))
        self.assertGreater(log[0].timestamp, timestamp)
        self.assertGreater(log[1].timestamp, timestamp)
        self.assertGreater(log[2].timestamp, timestamp)
Пример #9
0
    def BuildApprovalUrn(self, approval_id):
        """Builds approval object urn."""
        event = rdf_events.AuditEvent(user=self.token.username,
                                      action="CLIENT_APPROVAL_REQUEST",
                                      client=self.subject_urn,
                                      description=self.reason)
        events.Events.PublishEvent("Audit", event, token=self.token)

        return self.ApprovalUrnBuilder(self.subject_urn.Path(),
                                       self.token.username, approval_id)
Пример #10
0
def AddFakeAuditLog(description=None,
                    client=None,
                    user=None,
                    token=None,
                    **kwargs):
  events.Events.PublishEvent(
      "Audit",
      rdf_events.AuditEvent(
          description=description, client=client, user=user, **kwargs),
      token=token)
Пример #11
0
def _EntryToEvent(entry, handlers, transformers):
    """Converts an APIAuditEntry to a legacy AuditEvent."""
    event = rdf_events.AuditEvent(timestamp=entry.timestamp,
                                  user=entry.username,
                                  action=handlers[entry.router_method_name])

    for fn in transformers:
        fn(entry, event)

    return event
Пример #12
0
    def BuildApprovalUrn(self):
        """Builds approval object URN."""
        events.Events.PublishEvent("Audit",
                                   rdf_events.AuditEvent(
                                       user=self.token.username,
                                       action="CRON_APPROVAL_GRANT",
                                       urn=self.subject_urn,
                                       description=self.reason),
                                   token=self.token)

        return self.ApprovalUrnBuilder(self.subject_urn.Path(), self.delegate,
                                       self.reason)
Пример #13
0
    def BuildApprovalUrn(self, approval_id):
        """Builds approval object URN."""
        # In this case subject_urn is a cron job's URN.
        events.Events.PublishEvent("Audit",
                                   rdf_events.AuditEvent(
                                       user=self.token.username,
                                       action="CRON_APPROVAL_REQUEST",
                                       urn=self.subject_urn,
                                       description=self.reason),
                                   token=self.token)

        return self.ApprovalUrnBuilder(self.subject_urn.Path(),
                                       self.token.username, approval_id)
Пример #14
0
    def _HandleAff4(self, args, token):
        user_urn = aff4.ROOT_URN.Add("users").Add(args.username)

        events.Events.PublishEvent("Audit",
                                   rdf_events.AuditEvent(user=token.username,
                                                         action="USER_DELETE",
                                                         urn=user_urn),
                                   token=token)

        if not aff4.FACTORY.ExistsWithType(
                user_urn, aff4_type=users.GRRUser, token=token):
            raise api_call_handler_base.ResourceNotFoundError(
                "GRR user with username '%s' could not be found." %
                args.username)

        aff4.FACTORY.Delete(user_urn, token=token)
Пример #15
0
    def Handle(self, args, token=None):
        audit_description = ",".join([
            token.username + u"." + utils.SmartUnicode(name)
            for name in args.labels
        ])
        audit_events = []

        try:
            if data_store.AFF4Enabled():
                index = client_index.CreateClientIndex(token=token)
                client_objs = aff4.FACTORY.MultiOpen(
                    [cid.ToClientURN() for cid in args.client_ids],
                    aff4_type=aff4_grr.VFSGRRClient,
                    mode="rw",
                    token=token)
                for client_obj in client_objs:
                    index.RemoveClientLabels(client_obj)
                    self.RemoveClientLabels(client_obj, args.labels)
                    index.AddClient(client_obj)
                    client_obj.Close()

            if data_store.RelationalDBWriteEnabled():
                for client_id in args.client_ids:
                    cid = unicode(client_id)
                    data_store.REL_DB.RemoveClientLabels(
                        cid, token.username, args.labels)
                    labels_to_remove = set(args.labels)
                    existing_labels = data_store.REL_DB.ReadClientLabels(cid)
                    for label in existing_labels:
                        labels_to_remove.discard(label.name)
                    if labels_to_remove:
                        idx = client_index.ClientIndex()
                        idx.RemoveClientLabels(cid, labels_to_remove)

            for client_id in args.client_ids:
                audit_events.append(
                    rdf_events.AuditEvent(
                        user=token.username,
                        action="CLIENT_REMOVE_LABEL",
                        flow_name="handler.ApiRemoveClientsLabelsHandler",
                        client=client_id.ToClientURN(),
                        description=audit_description))
        finally:
            events.Events.PublishMultipleEvents(
                {audit.AUDIT_EVENT: audit_events}, token=token)
Пример #16
0
    def Handle(self, args, token=None):
        audit_description = ",".join([
            token.username + u"." + utils.SmartUnicode(name)
            for name in args.labels
        ])
        audit_events = []

        try:
            for api_client_id in args.client_ids:
                audit_events.append(
                    rdf_events.AuditEvent(
                        user=token.username,
                        action="CLIENT_ADD_LABEL",
                        flow_name="handler.ApiAddClientsLabelsHandler",
                        client=api_client_id.ToClientURN(),
                        description=audit_description))

            if data_store.AFF4Enabled():
                index = client_index.CreateClientIndex(token=token)
                client_objs = aff4.FACTORY.MultiOpen(
                    [cid.ToClientURN() for cid in args.client_ids],
                    aff4_type=aff4_grr.VFSGRRClient,
                    mode="rw",
                    token=token)
                for client_obj in client_objs:
                    client_obj.AddLabels(args.labels)
                    index.AddClient(client_obj)
                    client_obj.Close()

            if data_store.RelationalDBWriteEnabled():
                for api_client_id in args.client_ids:
                    cid = unicode(api_client_id)
                    try:
                        data_store.REL_DB.AddClientLabels(
                            cid, token.username, args.labels)
                        idx = client_index.ClientIndex()
                        idx.AddClientLabels(cid, args.labels)
                    except db.UnknownClientError:
                        # TODO(amoser): Remove after data migration.
                        pass

        finally:
            events.Events.PublishMultipleEvents(
                {audit.AUDIT_EVENT: audit_events}, token=token)
Пример #17
0
def DeleteUser(username, token=None):
    """Deletes an existing user."""
    if not username:
        raise UserError("User must have a non-empty name")

    token = data_store.GetDefaultToken(token)
    user_urn = "aff4:/users/%s" % username
    try:
        aff4.FACTORY.Open(user_urn, users.GRRUser, token=token)
    except aff4.InstantiationError:
        EPrint("User %s not found." % username)
        return

    aff4.FACTORY.Delete(user_urn, token=token)
    EPrint("User %s has been deleted." % username)

    events.Events.PublishEvent("Audit",
                               rdf_events.AuditEvent(user=token.username,
                                                     action="USER_DELETE",
                                                     urn=user_urn),
                               token=token)
Пример #18
0
    def testWriteAuditEventFieldSerialization(self):
        client_urn = rdf_client.ClientURN("C.4815162342000000")

        event = rdf_events.AuditEvent(
            action=rdf_events.AuditEvent.Action.RUN_FLOW,
            user="******",
            flow_name="foo",
            flow_args="bar",
            client=client_urn,
            urn=client_urn.Add("flows").Add("108"),
            description="lorem ipsum")

        self.db.WriteAuditEvent(event)

        log = self.db.ReadAllAuditEvents()
        self.assertEqual(len(log), 1)
        self.assertEqual(log[0].action, rdf_events.AuditEvent.Action.RUN_FLOW)
        self.assertEqual(log[0].user, "quux")
        self.assertEqual(log[0].flow_name, "foo")
        self.assertEqual(log[0].flow_args, "bar")
        self.assertEqual(log[0].client, client_urn)
        self.assertEqual(log[0].urn, client_urn.Add("flows").Add("108"))
        self.assertEqual(log[0].description, "lorem ipsum")
Пример #19
0
def StartAFF4Flow(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_flow_runner.FlowRunnerArgs()

    FilterArgsFromSemanticProtobuf(runner_args, kwargs)

    # Is the required flow a known flow?
    try:
        flow_cls = registry.AFF4FlowRegistry.FlowClassByName(
            runner_args.flow_name)
    except ValueError:
        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")

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

    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 StartAFF4Flow: %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")

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

    flow_obj.Close()

    # Publish an audit event, only for top level flows.
    if parent_flow is None:
        events.Events.PublishEvent("Audit",
                                   rdf_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
Пример #20
0
def StartFlow(client_id=None,
              cpu_limit=None,
              creator=None,
              flow_args=None,
              flow_cls=None,
              network_bytes_limit=None,
              original_flow=None,
              output_plugins=None,
              start_at=None,
              parent_flow_obj=None,
              parent_hunt_id=None,
              **kwargs):
    """The main factory function for creating and executing a new flow.

  Args:
    client_id: ID of the client this flow should run on.
    cpu_limit: CPU limit in seconds for this flow.
    creator: Username that requested this flow.
    flow_args: An arg protocol buffer which is an instance of the required
      flow's args_type class attribute.
    flow_cls: Class of the flow that should be started.
    network_bytes_limit: Limit on the network traffic this flow can generated.
    original_flow: A FlowReference object in case this flow was copied from
      another flow.
    output_plugins: An OutputPluginDescriptor object indicating what output
      plugins should be used for this flow.
    start_at: If specified, flow will be started not immediately, but at a given
      time.
    parent_flow_obj: A parent flow object. None if this is a top level flow.
    parent_hunt_id: String identifying parent hunt. Can't be passed together
      with parent_flow_obj.
    **kwargs: If args or runner_args are not specified, we construct these
      protobufs from these keywords.

  Returns:
    the flow id of the new flow.

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

    if parent_flow_obj is not None and parent_hunt_id is not None:
        raise ValueError(
            "parent_flow_obj and parent_hunt_id are mutually exclusive.")

    # Is the required flow a known flow?
    try:
        registry.FlowRegistry.FlowClassByName(flow_cls.__name__)
    except ValueError:
        stats_collector_instance.Get().IncrementCounter(
            "grr_flow_invalid_flow_count")
        raise ValueError("Unable to locate flow %s" % flow_cls.__name__)

    if not client_id:
        raise ValueError("Client_id is needed to start a flow.")

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

    FilterArgsFromSemanticProtobuf(flow_args, kwargs)
    # 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)

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

    rdf_flow = rdf_flow_objects.Flow(client_id=client_id,
                                     flow_class_name=flow_cls.__name__,
                                     args=flow_args,
                                     create_time=rdfvalue.RDFDatetime.Now(),
                                     creator=creator,
                                     output_plugins=output_plugins,
                                     original_flow=original_flow,
                                     flow_state="RUNNING")

    if parent_hunt_id is not None and parent_flow_obj is None:
        rdf_flow.flow_id = parent_hunt_id
        if IsLegacyHunt(parent_hunt_id):
            rdf_flow.flow_id = rdf_flow.flow_id[2:]
    else:
        rdf_flow.flow_id = RandomFlowId()

    # For better performance, only do conflicting IDs check for top-level flows.
    if not parent_flow_obj:
        try:
            data_store.REL_DB.ReadFlowObject(client_id, rdf_flow.flow_id)
            raise CanNotStartFlowWithExistingIdError(client_id,
                                                     rdf_flow.flow_id)
        except db.UnknownFlowError:
            pass

    if parent_flow_obj:  # A flow is a nested flow.
        parent_rdf_flow = parent_flow_obj.rdf_flow
        rdf_flow.long_flow_id = "%s/%s" % (parent_rdf_flow.long_flow_id,
                                           rdf_flow.flow_id)
        rdf_flow.parent_flow_id = parent_rdf_flow.flow_id
        rdf_flow.parent_hunt_id = parent_rdf_flow.parent_hunt_id
        rdf_flow.parent_request_id = parent_flow_obj.GetCurrentOutboundId()
        if parent_rdf_flow.creator:
            rdf_flow.creator = parent_rdf_flow.creator
    elif parent_hunt_id:  # A flow is a root-level hunt-induced flow.
        rdf_flow.long_flow_id = "%s/%s" % (client_id, rdf_flow.flow_id)
        rdf_flow.parent_hunt_id = parent_hunt_id
    else:  # A flow is a root-level non-hunt flow.
        rdf_flow.long_flow_id = "%s/%s" % (client_id, rdf_flow.flow_id)

    if output_plugins:
        rdf_flow.output_plugins_states = GetOutputPluginStates(
            output_plugins,
            rdf_flow.long_flow_id,
            token=access_control.ACLToken(username=rdf_flow.creator))

    if network_bytes_limit is not None:
        rdf_flow.network_bytes_limit = network_bytes_limit
    if cpu_limit is not None:
        rdf_flow.cpu_limit = cpu_limit

    logging.info(u"Scheduling %s(%s) on %s (%s)", rdf_flow.long_flow_id,
                 rdf_flow.flow_class_name, client_id, start_at or "now")

    rdf_flow.current_state = "Start"

    flow_obj = flow_cls(rdf_flow)
    if start_at is None:

        # Store an initial version of the flow straight away. This is needed so the
        # database doesn't raise consistency errors due to missing parent keys when
        # writing logs / errors / results which might happen in Start().
        data_store.REL_DB.WriteFlowObject(flow_obj.rdf_flow)

        # 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()

        # The flow does not need to actually remain running.
        if not flow_obj.outstanding_requests:
            flow_obj.RunStateMethod("End")
            # Additional check for the correct state in case the End method raised and
            # terminated the flow.
            if flow_obj.IsRunning():
                flow_obj.MarkDone()
    else:
        flow_obj.CallState("Start", start_time=start_at)

    flow_obj.PersistState()

    data_store.REL_DB.WriteFlowObject(flow_obj.rdf_flow)

    if parent_flow_obj is not None:
        # We can optimize here and not write requests/responses to the database
        # since we have to do this for the parent flow at some point anyways.
        parent_flow_obj.MergeQueuedMessages(flow_obj)
    else:
        flow_obj.FlushQueuedMessages()

        # Publish an audit event, only for top level flows.
        # TODO(amoser): split urn field into dedicated strings.
        events.Events.PublishEvent(
            "Audit",
            rdf_events.AuditEvent(user=creator,
                                  action="RUN_FLOW",
                                  flow_name=rdf_flow.flow_class_name,
                                  urn=rdf_flow.long_flow_id,
                                  client=client_id))

    return rdf_flow.flow_id
Пример #21
0
def UpdateUser(username,
               password,
               add_labels=None,
               delete_labels=None,
               token=None):
    """Implementation of the update_user command."""
    if not username:
        raise UserError("User must have a non-empty name")

    token = data_store.GetDefaultToken(token)

    user_urn = "aff4:/users/%s" % username
    try:
        fd = aff4.FACTORY.Open(user_urn, users.GRRUser, mode="rw", token=token)
    except aff4.InstantiationError:
        raise UserError("User %s does not exist." % username)

    # Note this accepts blank passwords as valid.
    if password:
        if not isinstance(password, basestring):
            password = getpass.getpass(
                prompt="Please enter password for user '%s': " % username)
        fd.SetPassword(password)

    # Use sets to dedup input.
    current_labels = set()

    # Build a list of existing labels.
    for label in fd.GetLabels():
        current_labels.add(label.name)

    # Build a list of labels to be added.
    expanded_add_labels = set()
    if add_labels:
        for label in add_labels:
            # Split up any space or comma separated labels in the list.
            labels = label.split(",")
            expanded_add_labels.update(labels)

    # Build a list of labels to be removed.
    expanded_delete_labels = set()
    if delete_labels:
        for label in delete_labels:
            # Split up any space or comma separated labels in the list.
            labels = label.split(",")
            expanded_delete_labels.update(labels)

    # Set subtraction to remove labels being added and deleted at the same time.
    clean_add_labels = expanded_add_labels - expanded_delete_labels
    clean_del_labels = expanded_delete_labels - expanded_add_labels

    # Create final list using difference to only add new labels.
    final_add_labels = clean_add_labels - current_labels

    # Create final list using intersection to only remove existing labels.
    final_del_labels = clean_del_labels & current_labels

    if final_add_labels:
        fd.AddLabels(final_add_labels, owner="GRR")

    if final_del_labels:
        fd.RemoveLabels(final_del_labels, owner="GRR")

    fd.Close()

    EPrint("Updated user %s" % username)

    ShowUser(username, token=token)

    events.Events.PublishEvent("Audit",
                               rdf_events.AuditEvent(user=token.username,
                                                     action="USER_UPDATE",
                                                     urn=user_urn),
                               token=token)
Пример #22
0
def StartFlow(client_id=None,
              cpu_limit=7200,
              creator=None,
              flow_args=None,
              flow_cls=None,
              network_bytes_limit=None,
              original_flow=None,
              output_plugins=None,
              parent_flow_obj=None,
              **kwargs):
    """The main factory function for creating and executing a new flow.

  Args:
    client_id: ID of the client this flow should run on.
    cpu_limit: CPU limit in seconds for this flow.
    creator: Username that requested this flow.
    flow_args: An arg protocol buffer which is an instance of the required
      flow's args_type class attribute.
    flow_cls: Class of the flow that should be started.
    network_bytes_limit: Limit on the network traffic this flow can generated.
    original_flow: A FlowReference object in case this flow was copied from
      another flow.
    output_plugins: An OutputPluginDescriptor object indicating what output
      plugins should be used for this flow.
    parent_flow_obj: A parent flow object. None if this is a top level flow.
    **kwargs: If args or runner_args are not specified, we construct these
      protobufs from these keywords.

  Returns:
    the flow id of the new flow.

  Raises:
    ValueError: Unknown or invalid parameters were provided.
  """
    # Is the required flow a known flow?
    try:
        registry.FlowRegistry.FlowClassByName(flow_cls.__name__)
    except ValueError:
        stats.STATS.IncrementCounter("grr_flow_invalid_flow_count")
        raise ValueError("Unable to locate flow %s" % flow_cls.__name__)

    if not client_id:
        raise ValueError("Client_id is needed to start a flow.")

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

    FilterArgsFromSemanticProtobuf(flow_args, kwargs)
    # 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)

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

    rdf_flow = rdf_flow_objects.Flow(client_id=client_id,
                                     flow_class_name=flow_cls.__name__,
                                     args=flow_args,
                                     create_time=rdfvalue.RDFDatetime.Now(),
                                     creator=creator,
                                     output_plugins=output_plugins,
                                     original_flow=original_flow,
                                     flow_state="RUNNING")

    rdf_flow.flow_id = "%08X" % utils.PRNG.GetUInt32()

    if parent_flow_obj:
        parent_rdf_flow = parent_flow_obj.rdf_flow
        rdf_flow.long_flow_id = "%s/%s" % (parent_rdf_flow.long_flow_id,
                                           rdf_flow.flow_id)
        rdf_flow.parent_flow_id = parent_rdf_flow.flow_id
        rdf_flow.parent_request_id = parent_flow_obj.GetCurrentOutboundId()
        if parent_rdf_flow.creator:
            rdf_flow.creator = parent_rdf_flow.creator
    else:
        rdf_flow.long_flow_id = "%s/%s" % (client_id, rdf_flow.flow_id)

    if output_plugins:
        rdf_flow.output_plugins_states = GetOutputPluginStates(
            output_plugins,
            rdf_flow.long_flow_id,
            token=access_control.ACLToken(username=rdf_flow.creator))

    if network_bytes_limit is not None:
        rdf_flow.network_bytes_limit = network_bytes_limit
    if cpu_limit is not None:
        rdf_flow.cpu_limit = cpu_limit

    logging.info(u"Scheduling %s(%s) on %s", rdf_flow.long_flow_id,
                 rdf_flow.flow_class_name, client_id)

    flow_obj = flow_cls(rdf_flow)
    # 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()
    flow_obj.PersistState()

    # The flow does not need to actually remain running.
    if not flow_obj.outstanding_requests:
        flow_obj.RunStateMethod("End")
        flow_obj.MarkDone()

    data_store.REL_DB.WriteFlowObject(flow_obj.rdf_flow)

    if parent_flow_obj is not None:
        # We can optimize here and not write requests/responses to the database
        # since we have to do this for the parent flow at some point anyways.
        parent_flow_obj.MergeQueuedMessages(flow_obj)
    else:
        flow_obj.FlushQueuedMessages()

        # Publish an audit event, only for top level flows.
        # TODO(amoser): split urn field into dedicated strings.
        events.Events.PublishEvent(
            "Audit",
            rdf_events.AuditEvent(user=creator,
                                  action="RUN_FLOW",
                                  flow_name=rdf_flow.flow_class_name,
                                  urn=rdf_flow.long_flow_id,
                                  client=client_id))

    return rdf_flow.flow_id
Пример #23
0
Файл: hunt.py Проект: hfakar/grr
    def Handle(self, args, token=None):
        hunt_urn = args.hunt_id.ToURN()
        try:
            hunt = aff4.FACTORY.Open(hunt_urn,
                                     aff4_type=implementation.GRRHunt,
                                     mode="rw",
                                     token=token)
        except aff4.InstantiationError:
            raise HuntNotFoundError("Hunt with id %s could not be found" %
                                    args.hunt_id)

        current_state = hunt.Get(hunt.Schema.STATE)
        hunt_changes = []
        runner = hunt.GetRunner()

        if args.HasField("client_limit"):
            hunt_changes.append(
                "Client Limit: Old=%s, New=%s" %
                (runner.runner_args.client_limit, args.client_limit))
            runner.runner_args.client_limit = args.client_limit

        if args.HasField("client_rate"):
            hunt_changes.append(
                "Client Rate: Old=%s, New=%s" %
                (runner.runner_args.client_rate, args.client_limit))
            runner.runner_args.client_rate = args.client_rate

        if args.HasField("expires"):
            hunt_changes.append("Expires: Old=%s, New=%s" %
                                (runner.context.expires, args.expires))
            runner.context.expires = args.expires

        if hunt_changes and current_state != "PAUSED":
            raise HuntNotModifiableError(
                "Hunt's client limit/client rate/expiry time attributes "
                "can only be changed if hunt's current state is "
                "PAUSED")

        if args.HasField("state"):
            hunt_changes.append("State: Old=%s, New=%s" %
                                (current_state, args.state))

            if args.state == ApiHunt.State.STARTED:
                if current_state != "PAUSED":
                    raise HuntNotStartableError(
                        "Hunt can only be started from PAUSED state.")
                hunt.Run()

            elif args.state == ApiHunt.State.STOPPED:
                if current_state not in ["PAUSED", "STARTED"]:
                    raise HuntNotStoppableError(
                        "Hunt can only be stopped from STARTED or "
                        "PAUSED states.")
                hunt.Stop()

            else:
                raise InvalidHuntStateError(
                    "Hunt's state can only be updated to STARTED or STOPPED")

        # Publish an audit event.
        # TODO(user): this should be properly tested.
        event = rdf_events.AuditEvent(user=token.username,
                                      action="HUNT_MODIFIED",
                                      urn=hunt_urn,
                                      description=", ".join(hunt_changes))
        events.Events.PublishEvent("Audit", event, token=token)

        hunt.Close()

        hunt = aff4.FACTORY.Open(hunt_urn,
                                 aff4_type=implementation.GRRHunt,
                                 mode="rw",
                                 token=token)
        return ApiHunt().InitFromAff4Object(hunt, with_full_summary=True)