def _WrapContentGenerator(self, generator, args, username): if args.file_path: path_type, components = rdf_objects.ParseCategorizedPath( args.file_path) vfs_file_ref = rdf_objects.VfsFileReference( client_id=args.client_id, path_type=path_type, path_components=components) else: vfs_file_ref = rdf_objects.VfsFileReference( client_id=args.client_id) object_reference = rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=vfs_file_ref) try: for item in generator: yield item notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATED, "Downloaded an archive of folder %s from client %s." % (args.file_path, args.client_id), object_reference) except Exception as e: notification.Notify( username, rdf_objects.UserNotification.Type. TYPE_FILE_ARCHIVE_GENERATION_FAILED, "Archive generation failed for folder %s on client %s: %s" % (args.file_path, args.client_id, e), object_reference) raise
def NotifyAboutEnd(self): super(GetFile, self).NotifyAboutEnd() stat_entry = self.state.stat_entry if not stat_entry: stat_entry = rdf_client_fs.StatEntry(pathspec=self.args.pathspec) urn = stat_entry.AFF4Path(self.client_urn) components = urn.Split() file_ref = None if len(components) > 3: file_ref = rdf_objects.VfsFileReference( client_id=components[0], path_type=components[2].upper(), path_components=components[3:]) if not self.state.get("success"): notification.Notify( self.token.username, rdf_objects.UserNotification.Type. TYPE_VFS_FILE_COLLECTION_FAILED, "File transfer failed.", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref)) else: notification.Notify( self.token.username, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File transferred successfully.", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref))
def _WrapContentGeneratorWithMappings(self, generator, mappings, args, context=None): flow_ref = rdf_objects.FlowReference( client_id=args.client_id, flow_id=args.flow_id) object_reference = rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref) try: for item in generator.Generate(mappings): yield item notification.Notify( context.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATED, "Downloaded archive of flow %s from client %s (archived %d files, " "archive size is %d)" % (args.flow_id, args.client_id, generator.num_archived_files, generator.output_size), object_reference) except Exception as e: notification.Notify( context.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATION_FAILED, "Archive generation failed for flow %s on client %s: %s" % (args.flow_id, args.client_id, e), object_reference) raise
def setUp(self): super(ApiDeletePendingUserNotificationHandlerTest, self).setUp() self.handler = user_plugin.ApiDeletePendingUserNotificationHandler() self.client_id = self.SetupClient(0) with test_lib.FakeTime(self.TIME_0): notification.Notify( self.context.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "<some message>", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=self.client_id))) notification.Notify( self.context.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "<some message with identical time>", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=self.client_id))) with test_lib.FakeTime(self.TIME_1): notification.Notify( self.context.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_APPROVAL_GRANTED, "<some other message>", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=self.client_id)))
def _WrapContentGenerator(self, generator, flow_results, args, token=None): flow_ref = rdf_objects.FlowReference(client_id=args.client_id, flow_id=args.flow_id) object_reference = rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref) try: for item in generator.Generate(flow_results): yield item notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATED, "Downloaded archive of flow %s from client %s (archived %d " "out of %d items, archive size is %d)" % (args.flow_id, args.client_id, len(generator.archived_files), generator.total_files, generator.output_size), object_reference) except Exception as e: notification.Notify( token.username, rdf_objects.UserNotification.Type. TYPE_FILE_ARCHIVE_GENERATION_FAILED, "Archive generation failed for flow %s on client %s: %s" % (args.flow_id, args.client_id, e), object_reference) raise
def GenerateNotifications(cls, client_id, token): """Generates fake notifications of different notification types.""" session_id = flow_test_lib.StartFlow(discovery.Interrogate, client_id=client_id, creator=token.username) notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "Fake discovery message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference( client_id=client_id.Basename()))) # ViewObject: VirtualFileSystem notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File fetch completed", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=rdf_objects.VfsFileReference( client_id=client_id.Basename(), path_type=rdf_objects.PathInfo.PathType.OS, path_components=["proc", "10", "exe"]))) gui_test_lib.CreateFileVersion(client_id, "fs/os/proc/10/exe", b"", timestamp=gui_test_lib.TIME_0, token=token) # ViewObject: Flow notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED, "Fake view flow message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=rdf_objects.FlowReference(client_id=client_id.Basename(), flow_id=session_id))) # FlowError if data_store.RelationalDBEnabled(): flow_base.TerminateFlow(client_id.Basename(), session_id, "Fake flow error") else: with aff4.FACTORY.Open(client_id.Add("flows").Add(session_id), mode="rw", token=token) as flow_obj: flow_obj.GetRunner().Error("Fake flow error") return session_id
def NotifyAboutEnd(self): status_text = "Recursive Directory Listing complete %d nodes, %d dirs" urn = self.state.first_directory if not urn: try: urn = self.args.pathspec.AFF4Path(self.client_urn) except ValueError: pass if urn: components = urn.Split() file_ref = None if len(components) > 3: file_ref = rdf_objects.VfsFileReference( client_id=components[0], path_type=components[2].upper(), path_components=components[3:]) notification.Notify( self.token.username, rdf_objects.UserNotification.Type. TYPE_VFS_RECURSIVE_LIST_DIRECTORY_COMPLETED, status_text % (self.state.file_count, self.state.dir_count), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref))
def NotifyAboutEnd(self): """Sends a notification that this flow is done.""" if not self.state.urn: super(ListDirectory, self).NotifyAboutEnd() return st = self.state.stat ps_path_type = st.pathspec.last.pathtype path_type = rdf_objects.PathInfo.PathTypeFromPathspecPathType( ps_path_type) full_path = st.pathspec.CollapsePath() path_components = full_path.strip("/").split("/") file_ref = rdf_objects.VfsFileReference( client_id=self.client_id, path_type=path_type, path_components=path_components) notification.Notify( self.token.username, rdf_objects.UserNotification.Type. TYPE_VFS_LIST_DIRECTORY_COMPLETED, "Listed {0}".format(full_path), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref))
def NotifyAboutEnd(self): notification.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=self.client_id)))
def StopHunt(hunt_id, reason=None): """Stops a hunt with a given id.""" def UpdateFn(h): if h.hunt_state not in [h.HuntState.STARTED, h.HuntState.PAUSED]: raise OnlyStartedOrPausedHuntCanBeStoppedError(h) h.hunt_state = h.HuntState.STOPPED if reason is not None: h.hunt_state_comment = reason return h # If the hunt was not started or paused, the exception from UpdateFn is # guaranteed to be propagated by UpdateHuntObject implementation. hunt_obj = data_store.REL_DB.UpdateHuntObject(hunt_id, UpdateFn) data_store.REL_DB.RemoveForemanRule(hunt_id=hunt_obj.hunt_id) flows = data_store.REL_DB.ReadHuntFlows(hunt_obj.hunt_id, 0, sys.maxsize) data_store.REL_DB.UpdateFlows( [(f.client_id, f.flow_id) for f in flows], pending_termination=rdf_flow_objects.PendingFlowTermination( reason="Parent hunt stopped.")) if (reason is not None and hunt_obj.creator not in aff4_users.GRRUser.SYSTEM_USERS): notification.Notify( hunt_obj.creator, rdf_objects.UserNotification.Type.TYPE_HUNT_STOPPED, reason, rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.HUNT, hunt=rdf_objects.HuntReference(hunt_id=hunt_obj.hunt_id))) return hunt_obj
def InitFromObj_(self, notification_type, reference, message=None): self.CreateUser(self.context.username) notification.Notify(self.context.username, notification_type, message or "", reference) ns = self.GetUserNotifications(self.context.username) # Treat the notification as an object coming from REL_DB. return user_plugin.ApiNotification().InitFromUserNotification(ns[0])
def testNotifyDoesNotNotifySystemUsers(self): # Implicitly test that Notify does not throw Exception because system users # might not exist in the database. notification.Notify( "Cron", rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "Fake discovery message", rdf_objects.ObjectReference()) self.assertEmpty(data_store.REL_DB.ReadUserNotifications("Cron"))
def NotifyAboutEnd(self): notification.Notify( self.token.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference( client_id=self.client_id.Basename())))
def GenerateNotifications(cls, client_id, username): """Generates fake notifications of different notification types.""" session_id = flow_test_lib.StartFlow(discovery.Interrogate, client_id=client_id, creator=username) notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "Fake discovery message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=client_id))) # ViewObject: VirtualFileSystem notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File fetch completed", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=rdf_objects.VfsFileReference( client_id=client_id, path_type=rdf_objects.PathInfo.PathType.OS, path_components=["proc", "10", "exe"]))) gui_test_lib.CreateFileVersion(client_id, "fs/os/proc/10/exe", b"", timestamp=gui_test_lib.TIME_0) # ViewObject: Flow notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED, "Fake view flow message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=rdf_objects.FlowReference(client_id=client_id, flow_id=session_id))) # FlowError flow_base.TerminateFlow(client_id, session_id, "Fake flow error") return session_id
def CreateApprovalNotification(self, approval): for user in approval.notified_users: try: notification_lib.Notify( user.strip(), self.__class__.approval_notification_type, "Please grant access to %s" % approval.subject_title, approval.ObjectReference()) except db.UnknownGRRUserError: # The relational db does not allow sending notifications to users that # don't exist. This should happen rarely but we need to catch this case. logging.error("Notification sent for unknown user %s!", user.strip())
def _SendNotifications(username, client_id): with test_lib.FakeTime(42): notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "<some message>", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference(client_id=client_id.Basename()))) with test_lib.FakeTime(44): notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTION_FAILED, "<some other message>", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=rdf_objects.VfsFileReference( client_id=client_id.Basename(), path_type=rdf_objects.PathInfo.PathType.OS, path_components=["foo"])))
def _WrapContentGenerator(self, generator, collection, args, context=None): try: for item in generator.Generate(collection): yield item notification.Notify( context.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATED, "Downloaded archive of hunt %s results (archived %d " "out of %d items, archive size is %d)" % (args.hunt_id, len(generator.archived_files), generator.total_files, generator.output_size), None) except Exception as e: notification.Notify( context.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATION_FAILED, "Archive generation failed for hunt %s: %s" % (args.hunt_id, e), None) raise
def NotifyAboutEnd(self): super().NotifyAboutEnd() stat_entry = self.state.stat_entry if not stat_entry: stat_entry = rdf_client_fs.StatEntry(pathspec=self.state.target_pathspec) urn = stat_entry.AFF4Path(self.client_urn) components = urn.Split() file_ref = None if len(components) > 3: file_ref = rdf_objects.VfsFileReference( client_id=components[0], path_type=components[2].upper(), path_components=components[3:]) if self.state.num_bytes_collected >= self.state.file_size: notification.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File transferred successfully.", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref)) elif self.state.num_bytes_collected > 0: notification.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File transferred partially (%d bytes out of %d)." % (self.state.num_bytes_collected, self.state.file_size), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref)) else: notification.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTION_FAILED, "File transfer failed.", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref))
def InitFromObj_(self, notification_type, reference, message=None): self.CreateUser(self.token.username) notification.Notify(self.token.username, notification_type, message or "", reference) ns = self.GetUserNotifications(self.token.username) if data_store.RelationalDBReadEnabled(): # Treat the notification as an object coming from REL_DB. return user_plugin.ApiNotification().InitFromUserNotification(ns[0]) else: # Treat the notification as an old-style notification object. return user_plugin.ApiNotification().InitFromNotification(ns[0])
def NotifyCreatorOfError(self): if self.ShouldSendNotifications(): client_id = self.rdf_flow.client_id flow_id = self.rdf_flow.flow_id flow_ref = rdf_objects.FlowReference(client_id=client_id, flow_id=flow_id) notification_lib.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_FAILED, "Flow %s on %s terminated due to error" % (flow_id, client_id), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref))
def _WrapContentGenerator(self, generator, collection, args, token=None): try: for item in generator.Generate(collection, token=token): yield item notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_FILE_ARCHIVE_GENERATED, "Downloaded archive of flow %s from client %s (archived %d " "out of %d items, archive size is %d)" % (args.flow_id, args.client_id, generator.archived_files, generator.total_files, generator.output_size), None) except Exception as e: notification.Notify( token.username, rdf_objects.UserNotification.Type. TYPE_FILE_ARCHIVE_GENERATION_FAILED, "Archive generation failed for flow %s on client %s: %s" % (args.flow_id, args.client_id, utils.SmartStr(e)), None) raise
def NotifyAboutEnd(self): """Send out a final notification about the end of this flow.""" flow_ref = None if self.runner_args.client_id: flow_ref = rdf_objects.FlowReference( client_id=self.client_id, flow_id=self.urn.Basename()) num_results = len(self.ResultCollection()) notification_lib.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED, "Flow %s completed with %d %s" % (self.__class__.__name__, num_results, num_results == 1 and "result" or "results"), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref))
def NotifyAboutEnd(self): # Sum up number of replies to write with the number of already # written results. num_results = ( len(self.replies_to_write) + data_store.REL_DB.CountFlowResults( self.rdf_flow.client_id, self.rdf_flow.flow_id)) flow_ref = rdf_objects.FlowReference( client_id=self.rdf_flow.client_id, flow_id=self.rdf_flow.flow_id) notification_lib.Notify( self.creator, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED, "Flow %s completed with %d %s" % (self.__class__.__name__, num_results, num_results == 1 and "result" or "results"), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref))
def testCronJobNotificationIsShownAndClickable(self): notification.Notify( self.token.username, rdf_objects.UserNotification.Type.TYPE_CRON_JOB_APPROVAL_GRANTED, "Test CronJob notification", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CRON_JOB, cron_job=rdf_objects.CronJobReference(cron_job_id=u"OSBreakDown"))) self.Open("/") self.Click("css=button[id=notification_button]") self.Click("css=a:contains('Test CronJob notification')") self.WaitUntil(self.IsElementPresent, "css=tr.row-selected td:contains('OSBreakDown')") self.WaitUntil(self.IsElementPresent, "css=dd:contains('OSBreakDown')")
def Error(self, backtrace, client_id=None, status_code=None): """Terminates this flow with an error.""" try: self.queue_manager.DestroyFlowStates(self.session_id) except queue_manager.MoreDataException: pass if not self.IsRunning(): return # Set an error status reply = rdf_flows.GrrStatus() if status_code is None: reply.status = rdf_flows.GrrStatus.ReturnedStatus.GENERIC_ERROR else: reply.status = status_code client_id = client_id or self.runner_args.client_id if backtrace: reply.error_message = backtrace logging.error("Error in flow %s (%s). Trace: %s", self.session_id, client_id, backtrace) self.context.backtrace = backtrace else: logging.error("Error in flow %s (%s).", self.session_id, client_id) self._SendTerminationMessage(reply) self.context.state = rdf_flow_runner.FlowContext.State.ERROR if self.ShouldSendNotifications(): flow_ref = None if client_id: flow_ref = rdf_objects.FlowReference( client_id=client_id.Basename(), flow_id=self.session_id.Basename()) notification_lib.Notify( self.token.username, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_FAILED, "Flow (%s) terminated due to error" % self.session_id, rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=flow_ref)) self.flow_obj.Flush()
def NotifyAboutEnd(self): """Sends a notification that this flow is done.""" if not self.state.urn: super(ListDirectoryMixin, self).NotifyAboutEnd() return components = self.state.urn.Split() file_ref = None if len(components) > 3: file_ref = rdf_objects.VfsFileReference( client_id=components[0], path_type=components[2].upper(), path_components=components[3:]) notification.Notify( self.token.username, rdf_objects.UserNotification.Type. TYPE_VFS_LIST_DIRECTORY_COMPLETED, "Listed {0}".format(self.args.pathspec.CollapsePath()), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref))
def NotifyAboutEnd(self): if not self.runner.ShouldSendNotifications(): return if self.state.urn: components = self.state.urn.Split() file_ref = None if len(components) > 3: file_ref = rdf_objects.VfsFileReference( client_id=components[0], path_type=components[2].upper(), path_components=components[3:]) notification.Notify( self.token.username, notification.UserNotification.Type.TYPE_VFS_LIST_DIRECTORY_COMPLETED, "List of {0} completed.".format(utils.SmartStr(self.args.pathspec)), rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=file_ref)) else: super(IteratedListDirectory, self).NotifyAboutEnd()
def _WrapContentGenerator(self, generator, args, username): try: for item in generator: yield item except Exception as e: path_type, components = rdf_objects.ParseCategorizedPath( args.file_path) vfs_file_ref = rdf_objects.VfsFileReference( client_id=args.client_id, path_type=path_type, path_components=components) object_reference = rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=vfs_file_ref) notification.Notify( username, rdf_objects.UserNotification.Type.TYPE_FILE_BLOB_FETCH_FAILED, "File blob fetch failed for path %s on client %s: %s" % (args.client_id, args.file_path, e), object_reference) raise
def StopHunt(hunt_id, reason=None): """Stops a hunt with a given id.""" hunt_obj = data_store.REL_DB.ReadHuntObject(hunt_id) if hunt_obj.hunt_state not in [ hunt_obj.HuntState.STARTED, hunt_obj.HuntState.PAUSED ]: raise OnlyStartedOrPausedHuntCanBeStoppedError(hunt_obj) data_store.REL_DB.UpdateHuntObject( hunt_id, hunt_state=hunt_obj.HuntState.STOPPED, hunt_state_comment=reason) data_store.REL_DB.RemoveForemanRule(hunt_id=hunt_obj.hunt_id) if (reason is not None and hunt_obj.creator not in access_control.SYSTEM_USERS): notification.Notify( hunt_obj.creator, rdf_objects.UserNotification.Type.TYPE_HUNT_STOPPED, reason, rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.HUNT, hunt=rdf_objects.HuntReference(hunt_id=hunt_obj.hunt_id))) return data_store.REL_DB.ReadHuntObject(hunt_id)
def CreateGrantNotification(self, approval, token=None): notification_lib.Notify( approval.requestor, self.__class__.approval_notification_type, "%s has granted you access to %s." % (token.username, approval.subject_title), approval.subject.ObjectReference())