def BuildSubjectId(self): return utils.SmartStr(self.cron_job_id)
def Seek(self, offset, whence=0): if not self.fd: self.fd = io.BytesIO(utils.SmartStr(self.value)) return self.fd.seek(offset, whence)
def CreateClientObject(self, vfs_fixture): """Make a new client object.""" # First remove the old fixture just in case its still there. aff4.FACTORY.Delete(self.client_id, token=self.token) # Create the fixture at a fixed time. with test_lib.FakeTime(self.age): for path, (aff4_type, attributes) in vfs_fixture: path %= self.args aff4_object = aff4.FACTORY.Create(self.client_id.Add(path), aff4_type, mode="rw", token=self.token) if data_store.RelationalDBWriteEnabled(): data_store.REL_DB.WriteClientMetadata( self.client_id.Basename(), fleetspeak_enabled=False) components = [ component for component in path.split("/") if component ] if components[0:2] == ["fs", "os"]: path_info = rdf_objects.PathInfo() path_info.path_type = rdf_objects.PathInfo.PathType.OS path_info.components = components[2:] if aff4_type in [ aff4_grr.VFSFile, aff4_grr.VFSMemoryFile ]: path_info.directory = False elif aff4_type == aff4_standard.VFSDirectory: path_info.directory = True else: raise ValueError("Incorrect AFF4 type: %s" % aff4_type) data_store.REL_DB.WritePathInfos( client_id=self.client_id.Basename(), path_infos=[path_info]) for attribute_name, value in iteritems(attributes): attribute = aff4.Attribute.PREDICATES[attribute_name] if isinstance(value, (str, unicode)): # Interpolate the value value %= self.args # Is this supposed to be an RDFValue array? if aff4.issubclass(attribute.attribute_type, rdf_protodict.RDFValueArray): rdfvalue_object = attribute() for item in value: new_object = rdfvalue_object.rdf_type.FromTextFormat( utils.SmartStr(item)) rdfvalue_object.Append(new_object) # It is a text serialized protobuf. elif aff4.issubclass(attribute.attribute_type, rdf_structs.RDFProtoStruct): # Use the alternate constructor - we always write protobufs in # textual form: rdfvalue_object = attribute.attribute_type.FromTextFormat( utils.SmartStr(value)) elif aff4.issubclass(attribute.attribute_type, rdfvalue.RDFInteger): rdfvalue_object = attribute(int(value)) else: rdfvalue_object = attribute(value) # If we don't already have a pathspec, try and get one from the stat. if aff4_object.Get(aff4_object.Schema.PATHSPEC) is None: # If the attribute was a stat, it has a pathspec nested in it. # We should add that pathspec as an attribute. if attribute.attribute_type == rdf_client_fs.StatEntry: stat_object = attribute.attribute_type.FromTextFormat( utils.SmartStr(value)) if stat_object.pathspec: pathspec_attribute = aff4.Attribute( "aff4:pathspec", rdf_paths.PathSpec, "The pathspec used to retrieve " "this object from the client.", "pathspec") aff4_object.AddAttribute( pathspec_attribute, stat_object.pathspec) if attribute in ["aff4:content", "aff4:content"]: # For AFF4MemoryStreams we need to call Write() instead of # directly setting the contents.. aff4_object.Write(rdfvalue_object.AsBytes()) else: aff4_object.AddAttribute(attribute, rdfvalue_object) if (isinstance(rdfvalue_object, rdf_client_fs.StatEntry) and rdfvalue_object.pathspec.pathtype != "UNSET"): if data_store.RelationalDBWriteEnabled(): client_id = self.client_id.Basename() path_info = rdf_objects.PathInfo.FromStatEntry( rdfvalue_object) data_store.REL_DB.WritePathInfos( client_id, [path_info]) # Populate the KB from the client attributes. if aff4_type == aff4_grr.VFSGRRClient: kb = rdf_client.KnowledgeBase() artifact.SetCoreGRRKnowledgeBaseValues(kb, aff4_object) aff4_object.Set(aff4_object.Schema.KNOWLEDGE_BASE, kb) # Make sure we do not actually close the object here - we only want to # sync back its attributes, not run any finalization code. aff4_object.Flush() if aff4_type == aff4_grr.VFSGRRClient: index = client_index.CreateClientIndex(token=self.token) index.AddClient(aff4_object)
def SerializeToString(self): return utils.SmartStr(self._value)
def __str__(self): return utils.SmartStr("aff4:%s" % self._string_urn)
def __str__(self): return utils.SmartStr(self.__unicode__())
def __str__(self): return utils.SmartStr(self._value)
def GetApprovalForObject(object_urn, token=None, username=""): """Looks for approvals for an object and returns available valid tokens. Args: object_urn: Urn of the object we want access to. token: The token to use to lookup the ACLs. username: The user to get the approval for, if "" we get it from the token. Returns: A token for access to the object on success, otherwise raises. Raises: UnauthorizedAccess: If there are no valid approvals available. """ if token is None: raise access_control.UnauthorizedAccess( "No token given, cannot authenticate.") if not username: username = token.username approvals_root_urn = aff4.ROOT_URN.Add("ACL").Add( object_urn.Path()).Add(username) children_urns = list(aff4.FACTORY.ListChildren(approvals_root_urn)) if not children_urns: raise access_control.UnauthorizedAccess( "No approval found for user %s" % utils.SmartStr(username), subject=object_urn) last_error = None approvals = aff4.FACTORY.MultiOpen(children_urns, mode="r", aff4_type=Approval, age=aff4.ALL_TIMES, token=token) for approval in approvals: try: test_token = access_control.ACLToken( username=username, reason=approval.Get(approval.Schema.REASON)) approval.CheckAccess(test_token) return test_token except access_control.UnauthorizedAccess as e: last_error = e if last_error: # We tried all possible approvals, but got no usable results. raise access_control.UnauthorizedAccess(last_error, subject=object_urn) else: # If last error is None, means that none of the URNs in children_urns # could be opened. This shouldn't really happen ever, but we have # to make sure to provide a meaningful error message. raise access_control.UnauthorizedAccess( "Couldn't open any of %d approvals " "for user %s" % (len(children_urns), utils.SmartStr(username)), subject=object_urn)
def ProcessMessages(self, msgs=None, token=None): """Processes this event.""" nanny_msg = "" for crash_details in msgs: client_id = crash_details.client_id # The session id of the flow that crashed. session_id = crash_details.session_id flow_obj = aff4.FACTORY.Open(session_id, token=token) # Log. logging.info("Client crash reported, client %s.", client_id) # Export. stats.STATS.IncrementCounter("grr_client_crashes") # Write crash data to AFF4. if data_store.RelationalDBReadEnabled(): client = data_store.REL_DB.ReadClientSnapshot( client_id.Basename()) client_info = client.startup_info.client_info else: client = aff4.FACTORY.Open(client_id, token=token) client_info = client.Get(client.Schema.CLIENT_INFO) crash_details.client_info = client_info crash_details.crash_type = "Client Crash" WriteAllCrashDetails(client_id, crash_details, flow_session_id=session_id, token=token) # Also send email. to_send = [] try: hunt_session_id = ExtractHuntId(session_id) if hunt_session_id and hunt_session_id != session_id: hunt_obj = aff4.FACTORY.Open( hunt_session_id, aff4_type=implementation.GRRHunt, token=token) email = hunt_obj.runner_args.crash_alert_email if email: to_send.append(email) except aff4.InstantiationError: logging.error("Failed to open hunt %s.", hunt_session_id) email = config.CONFIG["Monitoring.alert_email"] if email: to_send.append(email) for email_address in to_send: if crash_details.nanny_status: nanny_msg = "Nanny status: %s" % crash_details.nanny_status client = aff4.FACTORY.Open(client_id, token=token) hostname = client.Get(client.Schema.HOSTNAME) url = "/clients/%s" % client_id.Basename() body = self.__class__.mail_template.render( client_id=client_id, admin_ui=config.CONFIG["AdminUI.url"], hostname=utils.SmartUnicode(hostname), context=utils.SmartUnicode(flow_obj.context), state=utils.SmartUnicode(flow_obj.state), args=utils.SmartUnicode(flow_obj.args), runner_args=utils.SmartUnicode(flow_obj.runner_args), urn=url, nanny_msg=utils.SmartUnicode(nanny_msg), signature=config.CONFIG["Email.signature"]) email_alerts.EMAIL_ALERTER.SendEmail( email_address, "GRR server", "Client %s reported a crash." % client_id, utils.SmartStr(body), is_html=True) if nanny_msg: msg = "Client crashed, " + nanny_msg else: msg = "Client crashed." # Now terminate the flow. flow.GRRFlow.TerminateFlow(session_id, reason=msg, token=token, force=True)
def subject_url_path(self): return "/crons/%s" % utils.SmartStr(self.subject.cron_job_id)
def BuildSubjectId(self): return utils.SmartStr(self.hunt_id)
def review_url_path(self): return "/".join([ "users", self.requestor, "approvals", "cron-job", utils.SmartStr(self.subject.cron_job_id), utils.SmartStr(self.id) ])
def subject_url_path(self): return "/hunts/%s" % utils.SmartStr(self.subject.hunt_id)
def review_url_path(self): return "/".join([ "users", self.requestor, "approvals", "hunt", utils.SmartStr(self.subject.hunt_id), utils.SmartStr(self.id) ])
def InitFromAff4Object(self, client_obj, include_metadata=True): # TODO(amoser): Deprecate all urns. self.urn = client_obj.urn self.client_id = client_obj.urn.Basename() self.agent_info = client_obj.Get(client_obj.Schema.CLIENT_INFO) self.hardware_info = client_obj.Get(client_obj.Schema.HARDWARE_INFO) self.os_info = rdf_client.Uname( system=client_obj.Get(client_obj.Schema.SYSTEM), release=client_obj.Get(client_obj.Schema.OS_RELEASE), # TODO(user): Check if ProtoString.Validate should be fixed # to do an isinstance() check on a value. Is simple type # equality check used there for performance reasons? version=utils.SmartStr( client_obj.Get(client_obj.Schema.OS_VERSION, "")), kernel=client_obj.Get(client_obj.Schema.KERNEL), machine=client_obj.Get(client_obj.Schema.ARCH), fqdn=(client_obj.Get(client_obj.Schema.FQDN) or client_obj.Get(client_obj.Schema.HOSTNAME)), install_date=client_obj.Get(client_obj.Schema.INSTALL_DATE)) self.knowledge_base = client_obj.Get(client_obj.Schema.KNOWLEDGE_BASE) self.memory_size = client_obj.Get(client_obj.Schema.MEMORY_SIZE) self.first_seen_at = client_obj.Get(client_obj.Schema.FIRST_SEEN) if include_metadata: ping = client_obj.Get(client_obj.Schema.PING) if ping: self.last_seen_at = ping booted = client_obj.Get(client_obj.Schema.LAST_BOOT_TIME) if booted: self.last_booted_at = booted clock = client_obj.Get(client_obj.Schema.CLOCK) if clock: self.last_clock = clock last_crash = client_obj.Get(client_obj.Schema.LAST_CRASH) if last_crash is not None: self.last_crash_at = last_crash.timestamp self.fleetspeak_enabled = bool( client_obj.Get(client_obj.Schema.FLEETSPEAK_ENABLED)) self.labels = [ rdf_objects.ClientLabel(name=l.name, owner=l.owner) for l in client_obj.GetLabels() ] self.interfaces = client_obj.Get(client_obj.Schema.INTERFACES) kb = client_obj.Get(client_obj.Schema.KNOWLEDGE_BASE) if kb and kb.users: self.users = sorted(kb.users, key=lambda user: user.username) self.volumes = client_obj.Get(client_obj.Schema.VOLUMES) type_obj = client_obj.Get(client_obj.Schema.TYPE) if type_obj: # Without self.Set self.age would reference "age" attribute instead of a # protobuf field. self.Set("age", type_obj.age) self.cloud_instance = client_obj.Get(client_obj.Schema.CLOUD_INSTANCE) return self
def Control(self): """Handle POSTS.""" if not master.MASTER_WATCHER.IsMaster(): # We shouldn't be getting requests from the client unless we # are the active instance. stats_collector_instance.Get().IncrementCounter( "frontend_inactive_request_count", fields=["http"]) logging.info("Request sent to inactive frontend from %s", self.client_address[0]) # Get the api version try: api_version = int(cgi.parse_qs(self.path.split("?")[1])["api"][0]) except (ValueError, KeyError, IndexError): # The oldest api version we support if not specified. api_version = 3 try: content_length = self.headers.getheader("content-length") if not content_length: raise IOError("No content-length header provided.") length = int(content_length) request_comms = rdf_flows.ClientCommunication.FromSerializedString( self._GetPOSTData(length)) # If the client did not supply the version in the protobuf we use the get # parameter. if not request_comms.api_version: request_comms.api_version = api_version # Reply using the same version we were requested with. responses_comms = rdf_flows.ClientCommunication( api_version=request_comms.api_version) source_ip = ipaddr.IPAddress(self.client_address[0]) if source_ip.version == 6: source_ip = source_ip.ipv4_mapped or source_ip request_comms.orig_request = rdf_flows.HttpRequest( timestamp=rdfvalue.RDFDatetime.Now().AsMicrosecondsSinceEpoch( ), raw_headers=utils.SmartStr(self.headers), source_ip=utils.SmartStr(source_ip)) source, nr_messages = self.server.frontend.HandleMessageBundles( request_comms, responses_comms) server_logging.LOGGER.LogHttpFrontendAccess( request_comms.orig_request, source=source, message_count=nr_messages) self.Send(responses_comms.SerializeToString()) except communicator.UnknownClientCert: # "406 Not Acceptable: The server can only generate a response that is not # accepted by the client". This is because we can not encrypt for the # client appropriately. self.Send("Enrollment required", status=406)
def ObjectReference(self): return rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference( client_id=utils.SmartStr(self.client_id)))
def ToString(self, value): return utils.SmartStr(value)
def ParseFromString(self, initializer): # Old clients sometimes send bare well known flow ids. if not utils.SmartStr(initializer).startswith("aff4"): initializer = "aff4:/flows/" + initializer super(FlowSessionID, self).ParseFromString(initializer)
def __eq__(self, other): return (self._value == utils.SmartStr(other) or binascii.hexlify(self._value) == other)
def ParseFromString(self, string): # This handles the cases when we're initialized from Unicode strings. self._value = utils.SmartStr(string)
def BuildWithPyInstaller(self): """Use pyinstaller to build a client package.""" self.CleanDirectory( config.CONFIG.Get("PyInstaller.distpath", context=self.context)) logging.info("Copying pyinstaller support files") self.spec_file = os.path.join(self.build_dir, "grr.spec") with open(self.spec_file, "wb") as fd: fd.write( config.CONFIG.Get("PyInstaller.spec", context=self.context)) with open(os.path.join(self.build_dir, "version.txt"), "wb") as fd: fd.write( config.CONFIG.Get("PyInstaller.version", context=self.context)) shutil.copy(src=config.CONFIG.Get("PyInstaller.icon_path", context=self.context), dst=os.path.join(self.build_dir, u"grr.ico")) # We expect the onedir output at this location. self.output_dir = os.path.join( config.CONFIG.Get("PyInstaller.distpath", context=self.context), "grr-client") # Pyinstaller doesn't handle unicode strings. args = [ "--distpath", str(config.CONFIG.Get("PyInstaller.distpath", context=self.context)), "--workpath", str( config.CONFIG.Get("PyInstaller.workpath_dir", context=self.context)), str(self.spec_file) ] logging.info("Running pyinstaller: %s", args) PyInstallerMain.run(pyi_args=[utils.SmartStr(x) for x in args]) # Clear out some crud that pyinstaller includes. for path in ["tcl", "tk", "pytz"]: dir_path = os.path.join(self.output_dir, path) try: shutil.rmtree(dir_path) except OSError: logging.error("Unable to remove directory: %s", dir_path) try: os.mkdir(dir_path) except OSError: logging.error("Unable to create directory: %s", dir_path) file_path = os.path.join(dir_path, path) try: # Create an empty file so the directories get put in the installers. with open(file_path, "wb"): pass except IOError: logging.error("Unable to create file: %s", file_path) version_ini = version.VersionPath() shutil.copy(version_ini, os.path.join(self.output_dir, "version.ini")) with open(os.path.join(self.output_dir, "build.yaml"), "wb") as fd: self.WriteBuildYaml(fd)
def __eq__(self, other): return (self._value == utils.SmartStr(other) or self._value.encode("hex") == other)
def __init__(self, base_fd, pathspec=None, progress_callback=None): """Use TSK to read the pathspec. Args: base_fd: The file like object we read this component from. pathspec: An optional pathspec to open directly. progress_callback: A callback to indicate that the open call is still working but needs more time. Raises: IOError: If the file can not be opened. """ super(TSKFile, self).__init__( base_fd, pathspec=pathspec, progress_callback=progress_callback) if self.base_fd is None: raise IOError("TSK driver must have a file base.") # If our base is another tsk driver - borrow the reference to the raw # device, and replace the last pathspec component with this one after # extending its path. elif isinstance(base_fd, TSKFile) and self.base_fd.IsDirectory(): self.tsk_raw_device = self.base_fd.tsk_raw_device last_path = utils.JoinPath(self.pathspec.last.path, pathspec.path) # Replace the last component with this one. self.pathspec.Pop(-1) self.pathspec.Append(pathspec) self.pathspec.last.path = last_path # Use the base fd as a base to parse the filesystem only if its file like. elif not self.base_fd.IsDirectory(): self.tsk_raw_device = self.base_fd self.pathspec.Append(pathspec) else: # If we get here we have a directory from a non sleuthkit driver - dont # know what to do with it. raise IOError("Unable to parse base using Sleuthkit.") # If we are successful in opening this path below the path casing is # correct. self.pathspec.last.path_options = rdf_paths.PathSpec.Options.CASE_LITERAL fd_hash = self.tsk_raw_device.pathspec.SerializeToString() # Cache the filesystem using the path of the raw device try: self.filesystem = vfs.DEVICE_CACHE.Get(fd_hash) self.fs = self.filesystem.fs except KeyError: self.img = MyImgInfo( fd=self.tsk_raw_device, progress_callback=progress_callback) self.fs = pytsk3.FS_Info(self.img, 0) self.filesystem = CachedFilesystem(self.fs, self.img) vfs.DEVICE_CACHE.Put(fd_hash, self.filesystem) # We prefer to open the file based on the inode because that is more # efficient. if pathspec.HasField("inode"): self.fd = self.fs.open_meta(pathspec.inode) self.tsk_attribute = self.GetAttribute(pathspec.ntfs_type, pathspec.ntfs_id) if self.tsk_attribute: self.size = self.tsk_attribute.info.size else: self.size = self.fd.info.meta.size else: # Does the filename exist in the image? self.fd = self.fs.open(utils.SmartStr(self.pathspec.last.path)) self.size = self.fd.info.meta.size self.pathspec.last.inode = self.fd.info.meta.addr
def Read(self, length): if not self.fd: self.fd = io.BytesIO(utils.SmartStr(self.value)) return self.fd.read(length)
def HandleRequest(self, request): """Handles given HTTP request.""" impersonated_username = config.CONFIG["AdminUI.debug_impersonate_user"] if impersonated_username: logging.info("Overriding user as %s", impersonated_username) request.user = config.CONFIG["AdminUI.debug_impersonate_user"] if not aff4_users.GRRUser.IsValidUsername(request.user): return self._BuildResponse( 403, dict(message="Invalid username: %s" % request.user)) try: router, method_metadata, args = self._router_matcher.MatchRouter( request) except access_control.UnauthorizedAccess as e: logging.exception("Access denied to %s (%s): %s", request.path, request.method, e) additional_headers = { "X-GRR-Unauthorized-Access-Reason": utils.SmartStr(e.message).replace("\n", ""), "X-GRR-Unauthorized-Access-Subject": utils.SmartStr(e.subject) } return self._BuildResponse( 403, dict(message="Access denied by ACL: %s" % utils.SmartStr(e.message), subject=utils.SmartStr(e.subject)), headers=additional_headers) except ApiCallRouterNotFoundError as e: return self._BuildResponse(404, dict(message=e.message)) except werkzeug_exceptions.MethodNotAllowed as e: return self._BuildResponse(405, dict(message=e.message)) except Error as e: logging.exception("Can't match URL to router/method: %s", e) return self._BuildResponse( 500, dict(message=str(e), traceBack=traceback.format_exc())) request.method_metadata = method_metadata request.parsed_args = args # SetUID() is called here so that ACL checks done by the router do not # clash with datastore ACL checks. # TODO(user): increase token expiry time. token = self.BuildToken(request, 60).SetUID() # AFF4 edge case: if a user is issuing a request, before they are created # using CreateGRRUser (e.g. in E2E tests or with single sign-on), # AFF4's ReadGRRUsers will NEVER contain the user, because the creation # done in the following lines does not add the user to the /users/ # collection. Furthermore, subsequent CreateGrrUserHandler calls fail, # because the user technically already exists. # We send a blind-write request to ensure that the user object is created # for a user specified by the username. user_urn = rdfvalue.RDFURN("aff4:/users/").Add(request.user) # We can't use conventional AFF4 interface, since aff4.FACTORY.Create will # create a new version of the object for every call. with data_store.DB.GetMutationPool() as pool: pool.MultiSet(user_urn, { aff4_users.GRRUser.SchemaCls.TYPE: [aff4_users.GRRUser.__name__], aff4_users.GRRUser.SchemaCls.LAST: [rdfvalue.RDFDatetime.Now().SerializeToDataStore()] }, replace=True) if data_store.RelationalDBWriteEnabled(): data_store.REL_DB.WriteGRRUser(request.user) handler = None try: # ACL checks are done here by the router. If this method succeeds (i.e. # does not raise), then handlers run without further ACL checks (they're # free to do some in their own implementations, though). handler = getattr(router, method_metadata.name)(args, token=token) if handler.args_type != method_metadata.args_type: raise RuntimeError( "Handler args type doesn't match " "method args type: %s vs %s" % (handler.args_type, method_metadata.args_type)) binary_result_type = ( api_call_router.RouterMethodMetadata.BINARY_STREAM_RESULT_TYPE) if (handler.result_type != method_metadata.result_type and not (handler.result_type is None and method_metadata.result_type == binary_result_type)): raise RuntimeError( "Handler result type doesn't match " "method result type: %s vs %s" % (handler.result_type, method_metadata.result_type)) # HEAD method is only used for checking the ACLs for particular API # methods. if request.method == "HEAD": # If the request would return a stream, we add the Content-Length # header to the response. if (method_metadata.result_type == method_metadata.BINARY_STREAM_RESULT_TYPE): binary_stream = handler.Handle(args, token=token) return self._BuildResponse( 200, {"status": "OK"}, method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, content_length=binary_stream.content_length, token=token) else: return self._BuildResponse( 200, {"status": "OK"}, method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token) if (method_metadata.result_type == method_metadata.BINARY_STREAM_RESULT_TYPE): binary_stream = handler.Handle(args, token=token) return self._BuildStreamingResponse( binary_stream, method_name=method_metadata.name) else: format_mode = GetRequestFormatMode(request, method_metadata) result = self.CallApiHandler(handler, args, token=token) rendered_data = self._FormatResultAsJson( result, format_mode=format_mode) return self._BuildResponse( 200, rendered_data, method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token) except access_control.UnauthorizedAccess as e: logging.exception("Access denied to %s (%s) with %s: %s", request.path, request.method, method_metadata.name, e) additional_headers = { "X-GRR-Unauthorized-Access-Reason": utils.SmartStr(e.message).replace("\n", ""), "X-GRR-Unauthorized-Access-Subject": utils.SmartStr(e.subject) } return self._BuildResponse( 403, dict(message="Access denied by ACL: %s" % e.message, subject=utils.SmartStr(e.subject)), headers=additional_headers, method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token) except api_call_handler_base.ResourceNotFoundError as e: return self._BuildResponse( 404, dict(message=e.message), method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token) except NotImplementedError as e: return self._BuildResponse( 501, dict(message=e.message), method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token) except Exception as e: # pylint: disable=broad-except logging.exception("Error while processing %s (%s) with %s: %s", request.path, request.method, handler.__class__.__name__, e) return self._BuildResponse( 500, dict(message=str(e), traceBack=traceback.format_exc()), method_name=method_metadata.name, no_audit_log=method_metadata.no_audit_log_required, token=token)
def __str__(self): return utils.SmartStr(",".join(self.names))
def Handle(self, args, token=None): if not args.client_id: raise ValueError("client_id must be provided") runner_args = args.flow.runner_args flow_name = args.flow.name if not flow_name: flow_name = runner_args.flow_name if not flow_name: raise RuntimeError("Flow name is not specified.") # Clear all fields marked with HIDDEN, except for output_plugins - they are # marked HIDDEN, because we have a separate UI for them, not because they # shouldn't be shown to the user at all. # # TODO(user): Refactor the code to remove the HIDDEN label from # FlowRunnerArgs.output_plugins. runner_args.ClearFieldsWithLabel( rdf_structs.SemanticDescriptor.Labels.HIDDEN, exceptions="output_plugins") if args.original_flow: runner_args.original_flow = rdf_objects.FlowReference( flow_id=utils.SmartStr(args.original_flow.flow_id), client_id=utils.SmartStr(args.original_flow.client_id)) if data_store.RelationalDBFlowsEnabled(): flow_cls = registry.FlowRegistry.FlowClassByName(flow_name) cpu_limit = None if runner_args.HasField("cpu_limit"): cpu_limit = runner_args.cpu_limit network_bytes_limit = None if runner_args.HasField("network_bytes_limit"): network_bytes_limit = runner_args.network_bytes_limit flow_id = flow.StartFlow( client_id=str(args.client_id), cpu_limit=cpu_limit, creator=token.username, flow_args=args.flow.args, flow_cls=flow_cls, network_bytes_limit=network_bytes_limit, original_flow=runner_args.original_flow, output_plugins=runner_args.output_plugins, parent_flow_obj=None, ) flow_obj = data_store.REL_DB.ReadFlowObject(str(args.client_id), flow_id) res = ApiFlow().InitFromFlowObject(flow_obj) res.context = None return res else: flow_id = flow.StartAFF4Flow( client_id=args.client_id.ToClientURN(), flow_name=flow_name, token=token, args=args.flow.args, runner_args=runner_args) fd = aff4.FACTORY.Open(flow_id, aff4_type=flow.GRRFlow, token=token) return ApiFlow().InitFromAff4Object(fd, flow_id=flow_id.Basename())
def GetRegisteredArtifactNames(self): return [utils.SmartStr(x) for x in self._artifacts]
def ObjectReference(self): return rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.HUNT, hunt=rdf_objects.HuntReference( hunt_id=utils.SmartStr(self.hunt_id)))