def update(self, contents=None, lookup_file=None, namespace="lookup_editor", owner=None, session_key=None, user=None): """ Update the given lookup file with the provided contents. """ if owner is None: owner = "nobody" if namespace is None: namespace = "lookup_editor" # Check capabilities #LookupEditor.check_capabilities(lookup_file, request_info.user, request_info.session_key) # Ensure that the file name is valid if not is_file_name_valid(lookup_file): raise LookupNameInvalidException( "The lookup filename contains disallowed characters") # Determine the final path of the file resolved_file_path = self.resolve_lookup_filename( lookup_file, namespace, owner, session_key=session_key, throw_not_found=False) # Parse the JSON parsed_contents = json.loads(contents, object_pairs_hook=OrderedDict) # Create the temporary file temp_file_handle = lookupfiles.get_temporary_lookup_file() # This is a full path already; no need to call make_splunkhome_path(). temp_file_name = temp_file_handle.name # Make the lookups directory if it does not exist destination_lookup_full_path = make_lookup_filename( lookup_file, namespace, owner) self.logger.debug("destination_lookup_full_path=%s", destination_lookup_full_path) destination_lookup_path_only, _ = os.path.split( destination_lookup_full_path) try: os.makedirs(destination_lookup_path_only, 0o755) os.chmod(destination_lookup_path_only, 0o755) except OSError: # The directory already existed, no need to create it self.logger.debug( "Destination path of lookup already existed, no need to create it; destination_lookup_path=%s", destination_lookup_path_only) # Write out the new file to a temporary location try: if temp_file_handle is not None and os.path.isfile(temp_file_name): csv_writer = csv.writer(temp_file_handle, lineterminator='\n') for row in parsed_contents: if not self.is_empty(row): # Prune empty rows csv_writer.writerow(row) finally: if temp_file_handle is not None: temp_file_handle.close() # Determine if the lookup file exists, create it if it doesn't if resolved_file_path is None: self.logger.debug( 'Creating a new lookup file, user=%s, namespace=%s, lookup_file=%s, path="%s"', owner, namespace, lookup_file, temp_file_name) lookupfiles.create_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner=owner, key=session_key) self.logger.info( 'Lookup created successfully, user=%s, namespace=%s, lookup_file=%s, path="%s"', user, namespace, lookup_file, destination_lookup_full_path) # Edit the existing lookup otherwise else: if not is_lookup_in_users_path( resolved_file_path) or owner == 'nobody': lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner="nobody", key=session_key) else: lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner=owner, key=session_key) self.logger.info( 'Lookup edited successfully, user=%s, namespace=%s, lookup_file=%s', user, namespace, lookup_file) # Tell the SHC environment to replicate the file try: self.force_lookup_replication(namespace, lookup_file, session_key) except ResourceNotFound: self.logger.info( "Unable to force replication of the lookup file to other search heads; upgrade Splunk to 6.2 or later in order to support CSV file replication" ) except AuthorizationFailed: self.logger.warn( "Unable to force replication of the lookup file (not authorized), user=%s, namespace=%s, lookup_file=%s", user, namespace, lookup_file) except: self.logger.exception( "Unable to force replication of the lookup file, user=%s, namespace=%s, lookup_file=%s", user, namespace, lookup_file) return resolved_file_path
def update(self, contents=None, lookup_file=None, namespace="lookup_editor", owner=None, session_key=None, user=None): """ Update the given lookup file with the provided contents. """ if owner is None: owner = "nobody" if namespace is None: namespace = "lookup_editor" # Check capabilities #LookupEditor.check_capabilities(lookup_file, request_info.user, request_info.session_key) # Ensure that the file name is valid if not is_file_name_valid(lookup_file): raise LookupNameInvalidException("The lookup filename contains disallowed characters") # Determine the final path of the file resolved_file_path = self.resolve_lookup_filename(lookup_file, namespace, owner, session_key=session_key, throw_not_found=False) # Parse the JSON parsed_contents = json.loads(contents, object_pairs_hook=OrderedDict) # Create the temporary file temp_file_handle = lookupfiles.get_temporary_lookup_file() # This is a full path already; no need to call make_splunkhome_path(). temp_file_name = temp_file_handle.name # Make the lookups directory if it does not exist destination_lookup_full_path = make_lookup_filename(lookup_file, namespace, owner) self.logger.debug("destination_lookup_full_path=%s", destination_lookup_full_path) destination_lookup_path_only, _ = os.path.split(destination_lookup_full_path) try: os.makedirs(destination_lookup_path_only, 0755) os.chmod(destination_lookup_path_only, 0755) except OSError: # The directory already existed, no need to create it self.logger.debug("Destination path of lookup already existed, no need to create it; destination_lookup_path=%s", destination_lookup_path_only) # Write out the new file to a temporary location try: if temp_file_handle is not None and os.path.isfile(temp_file_name): csv_writer = csv.writer(temp_file_handle, lineterminator='\n') for row in parsed_contents: if not self.is_empty(row): # Prune empty rows csv_writer.writerow(row) finally: if temp_file_handle is not None: temp_file_handle.close() # Determine if the lookup file exists, create it if it doesn't if resolved_file_path is None: self.logger.debug('Creating a new lookup file, user=%s, namespace=%s, lookup_file=%s, path="%s"', owner, namespace, lookup_file, temp_file_name) lookupfiles.create_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner=owner, key=session_key) self.logger.info('Lookup created successfully, user=%s, namespace=%s, lookup_file=%s, path="%s"', user, namespace, lookup_file, destination_lookup_full_path) # Edit the existing lookup otherwise else: if not is_lookup_in_users_path(resolved_file_path) or owner == 'nobody': lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner="nobody", key=session_key) else: lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner=owner, key=session_key) self.logger.info('Lookup edited successfully, user=%s, namespace=%s, lookup_file=%s', user, namespace, lookup_file) # Tell the SHC environment to replicate the file try: self.force_lookup_replication(namespace, lookup_file, session_key) except ResourceNotFound: self.logger.info("Unable to force replication of the lookup file to other search heads; upgrade Splunk to 6.2 or later in order to support CSV file replication") except AuthorizationFailed: self.logger.warn("Unable to force replication of the lookup file (not authorized), user=%s, namespace=%s, lookup_file=%s", user, namespace, lookup_file) except: self.logger.exception("Unable to force replication of the lookup file, user=%s, namespace=%s, lookup_file=%s", user, namespace, lookup_file) return resolved_file_path
def save(self, lookup_file, contents, namespace=None, owner=None, **kwargs): """ Save the contents of a lookup file """ logger.info("Saving lookup contents...") try: user = cherrypy.session['user']['name'] session_key = cherrypy.session.get('sessionKey') if owner is None: owner = "nobody" if namespace is None: namespace = "lookup_editor" # Check capabilities LookupEditor.check_capabilities(lookup_file, user, session_key) # Ensure that the file name is valid if not self.is_file_name_valid(lookup_file): cherrypy.response.status = 400 return self.render_error_json("The lookup filename contains disallowed characters") # Determine the final path of the file resolved_file_path = self.resolve_lookup_filename(lookup_file, namespace, owner, throw_not_found=False) # Make a backup self.backupLookupFile(lookup_file, namespace, owner) # Parse the JSON parsed_contents = json.loads(contents) # Create the temporary file temp_file_handle = lookupfiles.get_temporary_lookup_file() # This is a full path already; no need to call make_splunkhome_path(). temp_file_name = temp_file_handle.name # Make the lookups directory if it does not exist destination_lookup_full_path = self.makeLookupFilename(lookup_file, namespace, owner) logger.debug("destination_lookup_full_path=%s", destination_lookup_full_path) destination_lookup_path_only, _ = os.path.split(destination_lookup_full_path) try: os.makedirs(destination_lookup_path_only, 0755) os.chmod(destination_lookup_path_only, 0755) except OSError: # The directory already existed, no need to create it logger.debug("Destination path of lookup already existed, no need to create it; destination_lookup_path=%s", destination_lookup_path_only) # Write out the new file to a temporary location try: if temp_file_handle is not None and os.path.isfile(temp_file_name): csv_writer = csv.writer(temp_file_handle, lineterminator='\n') for row in parsed_contents: if not isEmpty(row): # Prune empty rows csv_writer.writerow(row) finally: if temp_file_handle is not None: temp_file_handle.close() # Determine if the lookup file exists, create it if it doesn't if resolved_file_path is None: shutil.move(temp_file_name, destination_lookup_full_path) logger.info('Lookup created successfully, user=%s, namespace=%s, lookup_file=%s, path="%s"', user, namespace, lookup_file, destination_lookup_full_path) # If the file is new, then make sure that the list is reloaded so that the editors # notice the change lookupfiles.SplunkLookupTableFile.reload(session_key=session_key) # Edit the existing lookup otherwise else: try: if not self.isLookupInUsersPath(resolved_file_path) or owner == 'nobody': lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner="nobody", key=session_key) else: lookupfiles.update_lookup_table(filename=temp_file_name, lookup_file=lookup_file, namespace=namespace, owner=owner, key=session_key) except AuthorizationFailed as e: cherrypy.response.status = 403 return self.render_error_json(str(e)) logger.info('Lookup edited successfully, user=%s, namespace=%s, lookup_file=%s', user, namespace, lookup_file) # Tell the SHC environment to replicate the file try: force_lookup_replication(namespace, lookup_file, session_key) except ResourceNotFound: logger.info("Unable to force replication of the lookup file to other search heads; upgrade Splunk to 6.2 or later in order to support CSV file replication") except: logger.exception("Unable to save the lookup") cherrypy.response.status = 500 return self.render_error_json("Unable to save the lookup")