def _check_block(block, block_id): """ Check if a block is valid """ if not block: raise CommandExecutionError( 'Could not execute block \'{0}\', as it is not found.'.format( block_id)) if 'module' not in block: raise CommandExecutionError( 'Could not execute block \'{0}\': no \'module\' found.'.format( block_id)) acceptable_block_args = { 'return', 'module', 'xpipe_on_true', 'xpipe_on_false', 'xpipe', 'pipe', 'pipe_on_true', 'pipe_on_false', 'args', 'kwargs', } for key in block: if key not in acceptable_block_args: raise CommandExecutionError( 'Could not execute block \'{0}\': ' '\'{1}\' is not a valid block key'.format(block_id, key)) return True
def readlink(path): """ Return the path that a symlink points to This is only supported on Windows Vista or later. Inline with Unix behavior, this function will raise an error if the path is not a symlink, however, the error raised will be a SaltInvocationError, not an OSError. Args: path (str): The path to the symlink Returns: str: The path that the symlink points to CLI Example: .. code-block:: bash salt '*' file.readlink /path/to/link """ if sys.getwindowsversion().major < 6: raise HubbleInvocationError( "Symlinks are only supported on Windows Vista or later." ) try: return hubblestack.utils.path.readlink(path) except OSError as exc: if exc.errno == errno.EINVAL: raise CommandExecutionError("{0} is not a symbolic link".format(path)) raise CommandExecutionError(exc.__str__()) except Exception as exc: # pylint: disable=broad-except raise CommandExecutionError(exc)
def assign(name, value): """ Assign a single sysctl parameter for this minion CLI Example: .. code-block:: bash salt '*' sysctl.assign net.ipv4.ip_forward 1 """ value = str(value) tran_tab = name.translate("".maketrans("./", "/.")) sysctl_file = "/proc/sys/{0}".format(tran_tab) if not os.path.exists(sysctl_file): raise CommandExecutionError("sysctl {0} does not exist".format(name)) ret = {} cmd = 'sysctl -w {0}="{1}"'.format(name, value) data = __mods__["cmd.run_all"](cmd, python_shell=False) out = data["stdout"] err = data["stderr"] # Example: # # sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216" # net.ipv4.tcp_rmem = 4096 87380 16777216 regex = re.compile(r"^{0}\s+=\s+{1}$".format(re.escape(name), re.escape(value))) if not regex.match(out) or "Invalid argument" in str(err): if data["retcode"] != 0 and err: error = err else: error = out raise CommandExecutionError("sysctl -w failed: {0}".format(error)) new_name, new_value = out.split(" = ", 1) ret[new_name] = new_value return ret
def _resolve_symlink(path, max_depth=64): """ Resolves the given symlink path to its real path, up to a maximum of the `max_depth` parameter which defaults to 64. If the path is not a symlink path, it is simply returned. """ if sys.getwindowsversion().major < 6: raise HubbleInvocationError( "Symlinks are only supported on Windows Vista or later." ) # make sure we don't get stuck in a symlink loop! paths_seen = set((path,)) cur_depth = 0 while is_link(path): path = readlink(path) if path in paths_seen: raise CommandExecutionError("The given path is involved in a symlink loop.") paths_seen.add(path) cur_depth += 1 if cur_depth > max_depth: raise CommandExecutionError("Too many levels of symbolic links.") return path
def _load_yaml(self, filepath, filename): """ Load and validate yaml file File must be a valid yaml file, and content loaded must form a python-dictionary Arguments: filepath {str} -- Actual filepath of profile file filename {str} -- Filename for logging purpose Returns: [dict] -- Dictionary representation for yaml """ log.debug('Validating yaml file: %s', filename) # validating physical file existance if not filepath or not os.path.isfile(filepath): raise CommandExecutionError( 'Could not find file: {0}'.format(filepath)) yaml_data = None try: with open(filepath, 'r') as file_handle: yaml_data = yaml.safe_load(file_handle) except Exception as exc: raise CommandExecutionError( 'Could not load yaml file: {0}, Exception: {1}'.format( filepath, exc)) if not yaml_data or not isinstance(yaml_data, dict): raise CommandExecutionError( 'yaml data could not be loaded as dictionary: {0}'.format( filepath)) return yaml_data
def remove(path, force=False): """ Remove the named file or directory Args: path (str): The path to the file or directory to remove. force (bool): Remove even if marked Read-Only. Default is False Returns: bool: True if successful, False if unsuccessful CLI Example: .. code-block:: bash salt '*' file.remove C:\\Temp """ # This must be a recursive function in windows to properly deal with # Symlinks. The shutil.rmtree function will remove the contents of # the Symlink source in windows. path = os.path.expanduser(path) if not os.path.isabs(path): raise HubbleInvocationError("File path must be absolute: {0}".format(path)) # Does the file/folder exists if not os.path.exists(path) and not is_link(path): raise CommandExecutionError("Path not found: {0}".format(path)) # Remove ReadOnly Attribute if force: # Get current file attributes file_attributes = win32api.GetFileAttributes(path) win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL) try: if os.path.isfile(path): # A file and a symlinked file are removed the same way os.remove(path) elif is_link(path): # If it's a symlink directory, use the rmdir command os.rmdir(path) else: for name in os.listdir(path): item = "{0}\\{1}".format(path, name) # If its a normal directory, recurse to remove it's contents remove(item, force) # rmdir will work now because the directory is empty os.rmdir(path) except (OSError, IOError) as exc: if force: # Reset attributes to the original if delete fails. win32api.SetFileAttributes(path, file_attributes) raise CommandExecutionError("Could not remove '{0}': {1}".format(path, exc)) return True
def _validate_module_params(self, module_name, profile_id, module_args, chaining_args=None): """ A helper method to invoke module's validate_params method """ if not module_args: raise CommandExecutionError( 'Could not execute block \'{0}\', as it is not found.'.format( profile_id)) # Comparators must exist in Audit if self._caller == Caller.AUDIT: if 'args' not in module_args: raise HubbleCheckValidationError( 'No mention of args in audit-id: {0}'.format(profile_id)) if 'comparator' not in module_args: raise HubbleCheckValidationError( 'No mention of comparator in audit-id: {0}'.format( profile_id)) elif self._caller == Caller.FDG: if 'module' not in module_args: raise CommandExecutionError( 'Could not execute block \'{0}\': no \'module\' found.'. format(profile_id)) acceptable_block_args = { 'return', 'module', 'args', 'comparator', 'xpipe_on_true', 'xpipe_on_false', 'xpipe', 'pipe', 'pipe_on_true', 'pipe_on_false', } for key in module_args: if key not in acceptable_block_args: # Just doing error logging for unsupported tags log.warning('Please check block \'{0}\': ' '\'{1}\' is an unsupported block key'.format( profile_id, key)) if 'args' not in module_args and 'comparator' not in module_args: raise CommandExecutionError( 'Could not execute block \'{0}\': ' 'either \'args\' or \'comparator\' is not present in block.' .format(profile_id, key)) validate_param_method = '{0}.validate_params'.format(module_name) __hmods__[validate_param_method](profile_id, module_args, { 'chaining_args': chaining_args, 'caller': self._caller })
def _grep(pattern, path=None, string=None, args=None): """ Grep for a string in the specified file or string .. note:: This function's return value is slated for refinement in future versions of Salt pattern Pattern to match. For example: ``test``, or ``a[0-5]`` path Path to the file to be searched .. note:: Globbing is supported (i.e. ``/var/log/foo/*.log``, but if globbing is being used then the path should be quoted to keep the shell from attempting to expand the glob expression. string String to search args Optionally pass a list of flags to pass to the grep command. For example: ``-v`` or ``-i`` or ``-B2`` .. note:: The options should come after a double-dash (as shown in the examples below) to keep Salt's own argument parser from interpreting them. CLI Example: .. code-block:: bash salt '*' file.grep /etc/passwd nobody salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr '[-i, -B2]' salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr '[-i, -B2]' salt '*' file.grep "/etc/sysconfig/network-scripts/*" ipaddr '[-i, -B2]' """ if path: path = os.path.expanduser(path) options = [] if args and not isinstance(args, (list, tuple)): args = [args] for arg in args: options += arg.split() cmd = ['grep'] + options + [pattern] if path: cmd += [path] try: ret = __mods__['cmd.run_stdout'](cmd, python_shell=False, ignore_retcode=True, stdin=string) except (IOError, OSError) as exc: raise CommandExecutionError(exc.strerror) return ret
def world_writable_file(reason=''): """ Ensure no world writable files exist """ raise CommandExecutionError('Module disabled due to performance concerns') result = _execute_shell_command('df --local -P | awk {\'if (NR!=1) print $6\'} | xargs -I \'{}\' find \'{}\' -xdev -type f -perm -0002', python_shell=True) return True if result == '' else result
def unowned_files_or_dir(reason=''): """ Ensure no unowned files or directories exist """ raise CommandExecutionError('Module disabled due to performance concerns') result = _execute_shell_command('df --local -P | awk {\'if (NR!=1) print $6\'} | xargs -I \'{}\' find \'{}\' -xdev -nouser', python_shell=True) return True if result == '' else result
def _get_top_data(topfile): """ Helper method to retrieve and parse the nova topfile """ orig_topfile = topfile topfile = os.path.join(_hubble_dir()[1], topfile) log.debug('reading nova topfile=%s (%s)', topfile, orig_topfile) try: with open(topfile) as handle: topdata = yaml.safe_load(handle) except Exception as exc: log.error('error loading nova topfile: %s', exc) return list() if not isinstance(topdata, dict) or 'nova' not in topdata or \ (not isinstance(topdata['nova'], dict)): raise CommandExecutionError('Nova topfile not formatted correctly') topdata = topdata['nova'] ret = [] for match, data in topdata.items(): if __mods__['match.compound'](match): ret.extend(data) return ret
def set_mode(path, mode): """ Set the mode of a file path file or directory of which to set the mode mode mode to set the path to CLI Example: .. code-block:: bash salt '*' file.set_mode /etc/passwd 0644 """ path = os.path.expanduser(path) mode = str(mode).lstrip("0Oo") if not mode: mode = "0" if not os.path.exists(path): raise CommandExecutionError("{0}: File not found".format(path)) try: os.chmod(path, int(mode, 8)) except Exception: # pylint: disable=broad-except return "Invalid Mode " + mode return get_mode(path)
def remove(path): """ Remove the named file. If a directory is supplied, it will be recursively deleted. CLI Example: .. code-block:: bash salt '*' file.remove /tmp/foo .. versionchanged:: Neon The method now works on all types of file system entries, not just files, directories and symlinks. """ path = os.path.expanduser(path) if not os.path.isabs(path): raise HubbleInvocationError("File path must be absolute: {0}".format(path)) try: if os.path.islink(path) or (os.path.exists(path) and not os.path.isdir(path)): os.remove(path) return True elif os.path.isdir(path): shutil.rmtree(path) return True except (OSError, IOError) as exc: raise CommandExecutionError("Could not remove '{0}': {1}".format(path, exc)) return False
def refresh_db(): ''' Updates the package list - ``True``: Database updated successfully - ``False``: Problem updating database ''' ret = {} cmd = ['apk', 'update'] call = __mods__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False) if call['retcode'] == 0: errors = [] ret = True else: errors = [call['stdout']] ret = False if errors: raise CommandExecutionError( 'Problem encountered installing package(s)', info={'errors': errors, 'changes': ret} ) return ret
def persist(name, value, config="/etc/sysctl.conf", apply_change=False): """ Assign and persist a simple sysctl parameter for this minion name The name of the sysctl value to edit. value The sysctl value to apply. config The location of the sysctl configuration file. apply_change Default is False; Default behavior only creates or edits the sysctl.conf file. If apply is set to True, the changes are applied to the system. CLI Example: .. code-block:: bash salt '*' sysctl.persist net.inet.icmp.icmplim 50 salt '*' sysctl.persist coretemp_load NO config=/etc/sysctl.conf """ nlines = [] edited = False value = str(value) # If the sysctl.conf is not present, add it if not os.path.isfile(config): try: with hubblestack.utils.files.fopen(config, "w+") as _fh: _fh.write("#\n# Kernel sysctl configuration\n#\n") except (IOError, OSError): msg = "Could not write to file: {0}" raise CommandExecutionError(msg.format(config)) with hubblestack.utils.files.fopen(config, "r") as ifile: for line in ifile: line = hubblestack.utils.stringutils.to_unicode(line) if not line.startswith("{0}=".format(name)): nlines.append(line) continue else: key, rest = line.split("=", 1) if rest.startswith('"'): _, rest_v, rest = rest.split('"', 2) elif rest.startswith("'"): _, rest_v, rest = rest.split("'", 2) else: rest_v = rest.split()[0] rest = rest[len(rest_v):] if rest_v == value: return "Already set" nlines.append("{0}={1}\n".format(name, value)) edited = True if not edited: nlines.append("{0}={1}\n".format(name, value)) nlines = [hubblestack.utils.stringutils.to_str(_l) for _l in nlines] with hubblestack.utils.files.fopen(config, "w+") as ofile: ofile.writelines(nlines) # If apply_change=True, apply edits to system if apply_change is True: assign(name, value) return "Updated and applied" return "Updated"
def _grep(path, pattern, *args): """ Grep for a string in the specified file .. note:: This function's return value is slated for refinement in future versions of Salt path Path to the file to be searched .. note:: Globbing is supported (i.e. ``/var/log/foo/*.log``, but if globbing is being used then the path should be quoted to keep the shell from attempting to expand the glob expression. pattern Pattern to match. For example: ``test``, or ``a[0-5]`` opts Additional command-line flags to pass to the grep command. For example: ``-v``, or ``-i -B2`` .. note:: The options should come after a double-dash (as shown in the examples below) to keep Salt's own argument parser from interpreting them. CLI Example: .. code-block:: bash salt '*' file.grep /etc/passwd nobody salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i -B2 salt '*' file.grep "/etc/sysconfig/network-scripts/*" ipaddr -- -i -l """ path = os.path.expanduser(path) if args: options = ' '.join(args) else: options = '' cmd = ( r'''grep {options} {pattern} {path}''' .format( options=options, pattern=pattern, path=path, ) ) try: ret = __mods__['cmd.run_all'](cmd, python_shell=False, ignore_retcode=True) except (IOError, OSError) as exc: raise CommandExecutionError(exc.strerror) return ret
def __getattr__(self, k): try: return self.hkeys[k] except KeyError: msg = 'No hkey named \'{0}. Try one of {1}\'' hkeys = ', '.join(self.hkeys) raise CommandExecutionError(msg.format(k, hkeys))
def sticky_bit_on_world_writable_dirs(reason=''): """ Ensure sticky bit is set on all world-writable directories """ raise CommandExecutionError('Module disabled due to performance concerns') result = _execute_shell_command('df --local -P | awk {\'if (NR!=1) print $6\'} | xargs -I \'{}\' find \'{}\' -xdev -type d \\( -perm -0002 -a ! -perm -1000 \\) 2>/dev/null', python_shell=True) return True if result == '' else "There are failures"
def is_link(path): """ Check if the path is a symlink This is only supported on Windows Vista or later. Inline with Unix behavior, this function will raise an error if the path is not a symlink, however, the error raised will be a SaltInvocationError, not an OSError. Args: path (str): The path to a file or directory Returns: bool: True if path is a symlink, otherwise False CLI Example: .. code-block:: bash salt '*' file.is_link /path/to/link """ if sys.getwindowsversion().major < 6: raise HubbleInvocationError( "Symlinks are only supported on Windows Vista or later." ) try: return hubblestack.utils.path.islink(path) except Exception as exc: # pylint: disable=broad-except raise CommandExecutionError(exc)
def _get_top_data(topfile): """ Helper method to retrieve and parse the Audit topfile """ topfile = 'salt://' + BASE_DIR_AUDIT_PROFILES + os.sep + topfile log.debug('caching top file...') topfile_cache_path = __mods__['cp.cache_file'](topfile) if not topfile_cache_path: log.error('Could not find top file %s', topfile) return None topfile = __mods__['cp.cache_file'](topfile) if not topfile: raise CommandExecutionError('Topfile not found.') try: with open(topfile_cache_path) as handle: topdata = yaml.safe_load(handle) except Exception as exc: log.exception('Could not load topfile: {0}'.format(exc)) return None if not isinstance(topdata, dict) or 'audit' not in topdata or \ (not isinstance(topdata['audit'], dict)): log.error('Audit topfile not formatted correctly') return None topdata = topdata['audit'] ret = [] for match, data in topdata.items(): if data is None: log.error('No profiles found for one or more filters in topfile %s', topfile) return None if __mods__['match.compound'](match): ret.extend(data) return ret
def _check_available(name): ''' Returns boolean telling whether or not the named service is available ''' _status = _systemctl_status(name) sd_version = hubblestack.utils.systemd.version(__context__) if sd_version is not None and sd_version >= 231: # systemd 231 changed the output of "systemctl status" for unknown # services, and also made it return an exit status of 4. If we are on # a new enough version, check the retcode, otherwise fall back to # parsing the "systemctl status" output. # See: https://github.com/systemd/systemd/pull/3385 # Also: https://github.com/systemd/systemd/commit/3dced37 return 0 <= _status['retcode'] < 4 out = _status['stdout'].lower() if 'could not be found' in out: # Catch cases where the systemd version is < 231 but the return code # and output changes have been backported (e.g. RHEL 7.3). return False for line in hubblestack.utils.itertools.split(out, '\n'): match = re.match(r'\s+loaded:\s+(\S+)', line) if match: ret = match.group(1) != 'not-found' break else: raise CommandExecutionError( 'Failed to get information on unit \'%s\'' % name) return ret
def refresh_db(force=False): ''' Use pkg update to get latest pkg_summary force Pass -f so that the cache is always refreshed. .. versionadded:: 2018.3.0 ''' # Remove rtag file to keep multiple refreshes from happening in pkg states hubblestack.utils.pkg.clear_rtag(__opts__) pkgin = _check_pkgin() if pkgin: cmd = [pkgin, 'up'] if force: cmd.insert(1, '-f') call = __mods__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: comment = '' if 'stderr' in call: comment += call['stderr'] raise CommandExecutionError(comment) return True
def get_current_user(with_domain=True): """ Gets the user executing the process Args: with_domain (bool): ``True`` will prepend the user name with the machine name or domain separated by a backslash Returns: str: The user name """ try: user_name = win32api.GetUserNameEx(win32api.NameSamCompatible) if user_name[-1] == "$": # Make the system account easier to identify. # Fetch sid so as to handle other language than english test_user = win32api.GetUserName() if test_user == "SYSTEM": user_name = "SYSTEM" elif get_sid_from_name(test_user) == "S-1-5-18": user_name = "SYSTEM" elif not with_domain: user_name = win32api.GetUserName() except pywintypes.error as exc: raise CommandExecutionError( "Failed to get current user: {0}".format(exc)) if not user_name: return False return user_name
def stats(path, hash_type=None, follow_symlinks=True): """ Return a dict containing the stats for a given file CLI Example: .. code-block:: bash salt '*' file.stats /etc/passwd """ path = os.path.expanduser(path) ret = {} if not os.path.exists(path): try: # Broken symlinks will return False for os.path.exists(), but still # have a uid and gid pstat = os.lstat(path) except OSError: # Not a broken symlink, just a nonexistent path # NOTE: The file.directory state checks the content of the error # message in this exception. Any changes made to the message for this # exception will reflect the file.directory state as well, and will # likely require changes there. raise CommandExecutionError("Path not found: {0}".format(path)) else: if follow_symlinks: pstat = os.stat(path) else: pstat = os.lstat(path) ret["inode"] = pstat.st_ino ret["uid"] = pstat.st_uid ret["gid"] = pstat.st_gid ret["group"] = gid_to_group(pstat.st_gid) ret["user"] = uid_to_user(pstat.st_uid) ret["atime"] = pstat.st_atime ret["mtime"] = pstat.st_mtime ret["ctime"] = pstat.st_ctime ret["size"] = pstat.st_size ret["mode"] = hubblestack.utils.files.normalize_mode(oct(stat.S_IMODE(pstat.st_mode))) if hash_type: ret["sum"] = get_hash(path, hash_type) ret["type"] = "file" if stat.S_ISDIR(pstat.st_mode): ret["type"] = "dir" if stat.S_ISCHR(pstat.st_mode): ret["type"] = "char" if stat.S_ISBLK(pstat.st_mode): ret["type"] = "block" if stat.S_ISREG(pstat.st_mode): ret["type"] = "file" if stat.S_ISLNK(pstat.st_mode): ret["type"] = "link" if stat.S_ISFIFO(pstat.st_mode): ret["type"] = "pipe" if stat.S_ISSOCK(pstat.st_mode): ret["type"] = "socket" ret["target"] = os.path.realpath(path) return ret
def get_user(): """ Get the current user """ if HAS_PWD: ret = pwd.getpwuid(os.geteuid()).pw_name elif HAS_WIN_FUNCTIONS and hubblestack.utils.win_functions.HAS_WIN32: ret = hubblestack.utils.win_functions.get_current_user() else: raise CommandExecutionError( "Required external library (pwd or win32api) not installed") return hubblestack.utils.stringutils.to_unicode(ret)
def persist(name, value, config="/etc/sysctl.conf"): """ Assign and persist a simple sysctl parameter for this minion CLI Example: .. code-block:: bash salt '*' sysctl.persist net.inet.icmp.icmplim 50 """ nlines = [] edited = False value = str(value) # create /etc/sysctl.conf if not present if not os.path.isfile(config): try: with hubblestack.utils.files.fopen(config, "w+"): pass except (IOError, OSError): msg = "Could not create {0}" raise CommandExecutionError(msg.format(config)) with hubblestack.utils.files.fopen(config, "r") as ifile: for line in ifile: line = hubblestack.utils.stringutils.to_unicode(line) m = re.match(r"{0}(\??=)".format(name), line) if not m: nlines.append(line) continue else: key, rest = line.split("=", 1) if rest.startswith('"'): _, rest_v, rest = rest.split('"', 2) elif rest.startswith("'"): _, rest_v, rest = rest.split("'", 2) else: rest_v = rest.split()[0] rest = rest[len(rest_v) :] if rest_v == value: return "Already set" new_line = "{0}{1}{2}{3}".format(name, m.group(1), value, rest) nlines.append(new_line) edited = True if not edited: newline = "{0}={1}".format(name, value) nlines.append("{0}\n".format(newline)) with hubblestack.utils.files.fopen(config, "wb") as ofile: ofile.writelines(hubblestack.utils.data.encode(nlines)) assign(name, value) return "Updated"
def _get_top_data(topfile, fdg_version): """ Helper method to retrieve and parse the FDG topfile """ if not topfile.startswith('salt://'): topfile = 'salt://' + BASE_DIR_FDG_PROFILES.get( fdg_version) + os.sep + topfile cached_topfile = __mods__['cp.cache_file'](topfile) if not cached_topfile: log.debug('FDG topfile %s not found from fileserver. Aborting.', topfile) return [] try: with open(cached_topfile) as handle: topdata = yaml.safe_load(handle) except Exception as exc: raise CommandExecutionError('Could not load topfile: {0}'.format(exc)) if not isinstance(topdata, dict) or 'fdg' not in topdata: raise CommandExecutionError('fdg topfile not formatted correctly: ' 'missing ``fdg`` key or not formed as a ' 'dict: {0}'.format(topdata)) topdata = topdata['fdg'] ret = [] for match, data in topdata.items(): if data is None: log.error( 'No profiles found for one or more filters in topfile %s', topfile) return None if __mods__['match.compound'](match): ret.extend(data) return ret
def set_selinux_context( path, user=None, role=None, type=None, # pylint: disable=W0622 range=None, # pylint: disable=W0622 persist=False, ): """ .. versionchanged:: 3001 Added persist option Set a specific SELinux label on a given path CLI Example: .. code-block:: bash salt '*' file.set_selinux_context path <user> <role> <type> <range> salt '*' file.set_selinux_context /etc/yum.repos.d/epel.repo system_u object_r system_conf_t s0 """ if not any((user, role, type, range)): return False if persist: fcontext_result = __mods__["selinux.fcontext_add_policy"]( path, sel_type=type, sel_user=user, sel_level=range ) if fcontext_result.get("retcode", None) != 0: # Problem setting fcontext policy raise CommandExecutionError( "Problem setting fcontext: {0}".format(fcontext_result) ) cmd = ["chcon"] if user: cmd.extend(["-u", user]) if role: cmd.extend(["-r", role]) if type: cmd.extend(["-t", type]) if range: cmd.extend(["-l", range]) cmd.append(path) ret = not __mods__["cmd.retcode"](cmd, python_shell=False) if ret: return get_selinux_context(path) else: return ret
def get_top_data(topfile): """ Cache the topfile and process the list of configs this host should use. """ # Get topdata from filesystem if we don't have them already global TOP global TOP_STALENESS if TOP and TOP_STALENESS < 60: TOP_STALENESS += 1 topdata = TOP else: log.debug( 'Missing/stale cached topdata found for pulsar, retrieving fresh from fileserver.' ) topfile = __mods__['cp.cache_file'](topfile) try: with open(topfile) as handle: topdata = yaml.safe_load(handle) except Exception as e: raise CommandExecutionError( 'Could not load topfile: {0}'.format(e)) if not isinstance(topdata, dict) or 'pulsar' not in topdata or \ not(isinstance(topdata['pulsar'], dict)): raise CommandExecutionError( 'Pulsar topfile not formatted correctly') topdata = topdata['pulsar'] TOP = topdata TOP_STALENESS = 0 ret = [] for match, data in topdata.items(): if __mods__['match.compound'](match): ret.extend(data) return ret
def check_ungrouped_files(reason=''): """ Ensure no ungrouped files or directories exist """ raise CommandExecutionError('Module disabled due to performance concerns') ungrouped_files = _execute_shell_command("df --local -P | awk 'NR!=1 {print $6}' | xargs -I '{}' find '{}' -xdev -nogroup 2>/dev/null", python_shell=True).strip() ungrouped_files = ungrouped_files.split('\n') if ungrouped_files != "" else [] # The command above only searches local filesystems, there may still be compromised items on network # mounted partitions. # Following command will check each partition for unowned files ungrouped_partition_files = _execute_shell_command("mount | awk '{print $3}' | xargs -I '{}' find '{}' -xdev -nogroup 2>/dev/null", python_shell=True).strip() ungrouped_partition_files = ungrouped_partition_files.split('\n') if ungrouped_partition_files != "" else [] ungrouped_files = ungrouped_files + ungrouped_partition_files return True if ungrouped_files == [] else str(list(set(ungrouped_files)))