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", 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)
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", events.AuditEvent(user=token.username, action="USER_ADD", urn=user_urn), token=token)
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", 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)
def _CreateAuditEvent(self, event_action): flow_name = self.hunt_obj.args.flow_runner_args.flow_name event = 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)
def AddFakeAuditLog(description=None, client=None, user=None, token=None, **kwargs): events.Events.PublishEventInline( "Audit", events.AuditEvent( description=description, client=client, user=user, **kwargs), token=token)
def BuildApprovalUrn(self, approval_id): """Builds approval object urn.""" event = 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)
def BuildApprovalUrn(self): """Builds approval object URN.""" events.Events.PublishEvent("Audit", 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)
def BuildApprovalUrn(self, approval_id): """Builds approval object URN.""" # In this case subject_urn is a cron job's URN. events.Events.PublishEvent("Audit", 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)
def BuildApprovalUrn(self, approval_id): """Builds approval object URN.""" # In this case subject_urn is hunt's URN. events.Events.PublishEvent("Audit", events.AuditEvent( user=self.token.username, action="HUNT_APPROVAL_GRANT", urn=self.subject_urn, description=self.reason), token=self.token) return self.ApprovalUrnBuilder(self.subject_urn.Path(), self.delegate, approval_id)
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", 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)
def Handle(self, args, token=None): audit_description = ",".join([ token.username + u"." + utils.SmartUnicode(name) for name in args.labels ]) audit_events = [] try: 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: if data_store.RelationalDBWriteEnabled(): cid = client_obj.urn.Basename() 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) index.RemoveClientLabels(client_obj) self.RemoveClientLabels(client_obj, args.labels) index.AddClient(client_obj) client_obj.Close() audit_events.append( events.AuditEvent( user=token.username, action="CLIENT_REMOVE_LABEL", flow_name="handler.ApiRemoveClientsLabelsHandler", client=client_obj.urn, description=audit_description)) finally: events.Events.PublishMultipleEvents( {audit.AUDIT_EVENT: audit_events}, token=token)
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", events.AuditEvent(user=token.username, action="USER_DELETE", urn=user_urn), token=token)
def Handle(self, args, token=None): audit_description = ",".join([ token.username + u"." + utils.SmartUnicode(name) for name in args.labels ]) audit_events = [] try: 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: if data_store.RelationalDBWriteEnabled(): cid = client_obj.urn.Basename() 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 client_obj.AddLabels(args.labels) index.AddClient(client_obj) client_obj.Close() audit_events.append( events.AuditEvent( user=token.username, action="CLIENT_ADD_LABEL", flow_name="handler.ApiAddClientsLabelsHandler", client=client_obj.urn, description=audit_description)) finally: events.Events.PublishMultipleEvents( {audit.AUDIT_EVENT: audit_events}, token=token)
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 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", events.AuditEvent(user=token.username, action="USER_UPDATE", urn=user_urn), token=token)
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 = 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)