"""
SELinux
=======
Combiner for more complex handling of SELinux being disabled by any means
available to the users. It uses results of
:class:`insights.parsers.sestatus.SEStatus`, and
:class:`insights.parsers.selinux_config.SelinuxConfig` parsers and
:class:`insights.combiners.grub_conf.GrubConf` combiner.
It contains a dictionary ``problems`` in which it stores detected problems with
keys as follows and values are parsed lines with detected problem:
* ``sestatus_disabled`` - SELinux is disabled on runtime.
* ``sestatus_not_enforcing`` - SELinux is not in enforcing mode.
* ``grub_disabled`` - SELinux is set in Grub to be disabled.
* ``grub_not_enforcing`` - SELinux is set in Grub to not be in enforcing mode.
* ``selinux_conf_disabled`` - SELinux is set in configuration file to be disabled.
* ``sestatus_not_enforcing`` - SELinux is set in configuration file to not be in enforcing mode.
Examples:
>>> selinux = shared[SELinux]
>>> selinux.ok()
False
>>> selinux.problems
{'grub_disabled': ['/vmlinuz-2.6.32-642.el6.x86_64 selinux=0 ro root= ...'],
'selinux_conf_disabled': 'disabled',
'sestatus_not_enforcing': 'permissive'}
"""
from ..core.plugins import combiner
from ..parsers.sestatus import SEStatus
from ..combiners.grub_conf import GrubConf
from ..parsers.selinux_config import SelinuxConfig
GRUB_DISABLED = 'grub_disabled'
GRUB_NOT_ENFORCING = 'grub_not_enforcing'
RUNTIME_DISABLED = 'sestatus_disabled'
RUNTIME_NOT_ENFORCING = 'sestatus_not_enforcing'
BOOT_DISABLED = 'selinux_conf_disabled'
BOOT_NOT_ENFORCING = 'selinux_conf_not_enforcing'
[docs]
@combiner(SEStatus, SelinuxConfig, optional=[GrubConf])
class SELinux(object):
"""
A combiner for detecting that SELinux is enabled and running and also enabled at boot time.
"""
def __init__(self, se_status, selinux_config, grub_conf):
self.problems = {}
self.sestatus = se_status
self.selinux_config = selinux_config
self.grub_config = grub_conf.grub if grub_conf else None
self._check_sestatus()
self._check_boot_config()
self._check_grub_config()
def _check_sestatus(self):
"""
Check runtime SELinux configuration from sestatus output.
Values of output from sestatus command are always lowercase.
"""
if self.sestatus.data['selinux_status'] != 'enabled':
self.problems[RUNTIME_DISABLED] = self.sestatus.data['selinux_status']
elif self.sestatus.data['current_mode'] != 'enforcing':
self.problems[RUNTIME_NOT_ENFORCING] = self.sestatus.data['current_mode']
def _check_boot_config(self):
"""
Check that SELinux is not disabled in /etc/sysconfig/selinux.
This file determines the boot configuration for SELinux.
"""
opt_value = self.selinux_config.get('SELINUX')
if opt_value is None:
self.problems[BOOT_NOT_ENFORCING] = 'Missing in config (Permissive by default)'
elif opt_value == 'disabled':
self.problems[BOOT_DISABLED] = opt_value
elif opt_value != 'enforcing':
self.problems[BOOT_NOT_ENFORCING] = opt_value
def _check_grub_config(self):
"""
Check grub and grub 2 for kernel boot options if selinux settings is not overriden.
Experiments confirmed that only lowercase is accepted in grub configuration.
grub is in rhel-6 and the boot line looks usually like
kernel /boot/vmlinuz-2.4.20-selinux-2003040709 ro root=/dev/hda1 nousb selinux=0
grub 2 is in rhel-7 and rhel-8, the boot line of grub 2 in rhel-7 looks usually like
linux16 /vmlinuz-0-rescue-9f20b35c9faa49aebe171f62a11b236f root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet
the boot line of grub 2 in rhel-8 looks usually like
options root=/dev/mapper/rhel_vm37--146-root ro crashkernel=auto resume=/dev/mapper/rhel_vm37--146-swap rd.lvm.lv=rhel_vm37-146/root rd.lvm.lv=rhel_vm37-146/swap $tuned_params
"""
conf = self.grub_config.boot_entries if self.grub_config is not None else []
se_dis = [e.cmdline for e in conf if 'selinux=0' in e.cmdline]
if se_dis:
self.problems[GRUB_DISABLED] = se_dis
se_noe = [e.cmdline for e in conf if 'enforcing=0' in e.cmdline]
if se_noe:
self.problems[GRUB_NOT_ENFORCING] = se_noe
[docs]
def ok(self):
"""
Checks if there are any problems with SELinux configuration.
Returns
bool: True if SELinux is enabled and functional, false otherwise.
"""
return not bool(self.problems)