From a870523a6cf7cf4ed6fd092884ad57c0e769b564 Mon Sep 17 00:00:00 2001 From: David 425 Date: Tue, 24 Nov 2015 07:33:37 -0800 Subject: [PATCH 1/2] Adding basic control for selinux modules --- salt/modules/selinux.py | 69 ++++++++++++++++++++++++++++++++++++----- salt/states/selinux.py | 69 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 7 deletions(-) diff --git a/salt/modules/selinux.py b/salt/modules/selinux.py index 4017827905..0330521d48 100644 --- a/salt/modules/selinux.py +++ b/salt/modules/selinux.py @@ -3,12 +3,12 @@ Execute calls on selinux .. note:: - This module requires the ``semanage`` and ``setsebool`` commands to be - available on the minion. On RHEL-based distros, this means that the - ``policycoreutils`` and ``policycoreutils-python`` packages must be - installed. If not on a RHEL-based distribution, consult the selinux - documentation for your distro to ensure that the proper packages are - installed. + This module requires the ``semanage``, ``setsebool`` and ``semodule`` + commands to be available on the minion. On RHEL-based distros, this + means that the ``policycoreutils`` and ``policycoreutils-python`` + packages must be installed. If not on a RHEL-based distribution, + consult the selinux documentation for your distro to ensure that the + proper packages are installed. ''' # Import python libs @@ -29,7 +29,7 @@ def __virtual__(): Check if the os is Linux, and then if selinux is running in permissive or enforcing mode. ''' - required_cmds = ('semanage', 'setsebool') + required_cmds = ('semanage', 'setsebool', 'semodule') # Iterate over all of the commands this module uses and make sure # each of them are available in the standard PATH to prevent breakage @@ -191,3 +191,58 @@ def list_sebool(): 'Default': comps[3][:-1], 'Description': ' '.join(comps[4:])} return ret + +def getsemod(module): + ''' + Return the information on a specific selinux module + + CLI Example: + + .. code-block:: bash + + salt '*' selinux.getsemod mysql + ''' + return list_semod().get(module, {}) + + +def setsemod(module, state): + ''' + Enable or disable an SELinux module. + + CLI Example: + + .. code-block:: bash + + salt '*' selinux.setsemod nagios Enabled + ''' + if state.lower() == 'enabled': + cmd = 'semodule -e {0}'.format(module) + elif state.lower() == 'disabled': + cmd = 'semodule -d {0}'.format(module) + return not __salt__['cmd.retcode'](cmd) + + +def list_semod(): + ''' + Return a structure listing all of the selinux modules on the system and + what state they are in + + CLI Example: + + .. code-block:: bash + + salt '*' selinux.list_semod + ''' + mdata = __salt__['cmd.run']('semodule -l').splitlines() + ret = {} + for line in mdata[1:]: + if not line.strip(): + continue + comps = line.split() + if len(comps) == 3: + ret[comps[0]] = {'Enabled': False, + 'Version': comps[1]} + else: + ret[comps[0]] = {'Enabled': True, + 'Version': comps[1]} + return ret diff --git a/salt/states/selinux.py b/salt/states/selinux.py index 2f34194bfc..02a4b62445 100644 --- a/salt/states/selinux.py +++ b/salt/states/selinux.py @@ -16,6 +16,10 @@ booleans can be set. - value: True - persist: True + nginx: + selinux.module: + - enabled: False + .. note:: Use of these states require that the :mod:`selinux ` execution module is available. @@ -56,6 +60,17 @@ def _refine_value(value): return 'off' return None +def _refine_module_state(module_state): + ''' + Return a predictable value, or allow us to error out + ''' + module_state = str(module_state).lower() + if module_state in ('1', 'on', 'yes', 'true', 'enabled'): + return 'enabled' + if module_state in ('0', 'off', 'no', 'false', 'disabled'): + return 'disabled' + return 'unknown' + def mode(name): ''' @@ -144,3 +159,57 @@ def boolean(name, value, persist=False): return ret ret['comment'] = 'Failed to set the boolean {0} to {1}'.format(name, rvalue) return ret + + +def module(name, module_state='Enabled', version='any'): + ''' + Enable/Disable and optionally force a specific version for an SELinux module + + name + The name of the module to control + + module_state + Should the module be enabled or disabled? + + version + Defaults to no preference, set to a specified value if required. + Currently can only alert if the version is incorrect. + ''' + ret = {'name': name, + 'result': True, + 'comment': '', + 'changes': {}} + modules = __salt__['selinux.list_semod']() + if name not in modules: + ret['comment'] = 'Module {0} is not available'.format(name) + ret['result'] = False + return ret + rmodule_state = _refine_module_state(module_state) + if rmodule_state == 'unknown': + ret['comment'] = '{0} is not a valid state for the ' \ + '{1} module.'.format(module_state, module) + ret['result'] = False + return ret + if not version == 'any': + installed_version = modules[name]['Version'] + if not installed_version == version: + ret['comment'] = 'Module version is {0} and does not match ' \ + 'the desired version of {1}'.format(installed_version, version) + ret['result'] = False + return ret + current_module_state = _refine_module_state(modules[name]['Enabled']) + if rmodule_state == current_module_state: + ret['comment'] = 'Module {0} is in the desired state'.format(name) + return ret + if __opts__['test']: + ret['result'] = None + ret['comment'] = 'Module {0} is set to be togggled to {1}'.format( + name, module_state) + return ret + + if __salt__['selinux.setsemod'](name, rmodule_state): + ret['comment'] = 'Module {0} has been set to {1}'.format(name, module_state) + return ret + ret['result'] = False + ret['comment'] = 'Failed to set the Module {0} to {1}'.format(name, module_state) + return ret From 01b4e47356d8eaa8c4c560c69643eaac82331074 Mon Sep 17 00:00:00 2001 From: David 425 Date: Tue, 24 Nov 2015 18:29:49 -0800 Subject: [PATCH 2/2] adding versionadded and fixing minor lint errors --- salt/modules/selinux.py | 7 +++++++ salt/states/selinux.py | 10 +++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/salt/modules/selinux.py b/salt/modules/selinux.py index 0330521d48..5e28f3941e 100644 --- a/salt/modules/selinux.py +++ b/salt/modules/selinux.py @@ -192,6 +192,7 @@ def list_sebool(): 'Description': ' '.join(comps[4:])} return ret + def getsemod(module): ''' Return the information on a specific selinux module @@ -201,6 +202,8 @@ def getsemod(module): .. code-block:: bash salt '*' selinux.getsemod mysql + + .. versionadded:: Boron ''' return list_semod().get(module, {}) @@ -214,6 +217,8 @@ def setsemod(module, state): .. code-block:: bash salt '*' selinux.setsemod nagios Enabled + + .. versionadded:: Boron ''' if state.lower() == 'enabled': cmd = 'semodule -e {0}'.format(module) @@ -232,6 +237,8 @@ def list_semod(): .. code-block:: bash salt '*' selinux.list_semod + + .. versionadded:: Boron ''' mdata = __salt__['cmd.run']('semodule -l').splitlines() ret = {} diff --git a/salt/states/selinux.py b/salt/states/selinux.py index 02a4b62445..3ae1650396 100644 --- a/salt/states/selinux.py +++ b/salt/states/selinux.py @@ -60,9 +60,11 @@ def _refine_value(value): return 'off' return None + def _refine_module_state(module_state): ''' Return a predictable value, or allow us to error out + .. versionadded:: Boron ''' module_state = str(module_state).lower() if module_state in ('1', 'on', 'yes', 'true', 'enabled'): @@ -174,6 +176,8 @@ def module(name, module_state='Enabled', version='any'): version Defaults to no preference, set to a specified value if required. Currently can only alert if the version is incorrect. + + .. versionadded:: Boron ''' ret = {'name': name, 'result': True, @@ -199,12 +203,12 @@ def module(name, module_state='Enabled', version='any'): return ret current_module_state = _refine_module_state(modules[name]['Enabled']) if rmodule_state == current_module_state: - ret['comment'] = 'Module {0} is in the desired state'.format(name) - return ret + ret['comment'] = 'Module {0} is in the desired state'.format(name) + return ret if __opts__['test']: ret['result'] = None ret['comment'] = 'Module {0} is set to be togggled to {1}'.format( - name, module_state) + name, module_state) return ret if __salt__['selinux.setsemod'](name, rmodule_state):