summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/server/plugins/generators/rules.txt56
-rw-r--r--doc/server/selinux.txt39
-rw-r--r--src/lib/Bcfg2/Client/Tools/SELinux.py117
-rw-r--r--src/lib/Bcfg2/Server/Plugins/SEModules.py6
4 files changed, 91 insertions, 127 deletions
diff --git a/doc/server/plugins/generators/rules.txt b/doc/server/plugins/generators/rules.txt
index 542b38f01..65eb0c5d9 100644
--- a/doc/server/plugins/generators/rules.txt
+++ b/doc/server/plugins/generators/rules.txt
@@ -394,14 +394,12 @@ the permissions to ``0674``. When this happens, Bcfg2 will change the
permissions and set the ACLs on every run and the entry will be
eternally marked as bad.
-SELinux Tag
------------
+SELinux Entries
+---------------
-The SELinux tag has different values depending on the *type* attribute
-of the SELinux entry specified in your configuration. Below is a set
-of tables which describe the attributes available for various SELinux
-types. The types (except for ``module``) correspond to ``semanage``
-subcommands.
+Below is a set of tables which describe the attributes available
+for various SELinux types. The entry types (except for ``module``)
+correspond to ``semanage`` subcommands.
Note that the ``selinuxtype`` attribute takes only an SELinux type,
not a full context; e.g., "``etc_t``", not
@@ -411,18 +409,10 @@ As it can be very tedious to create a baseline of all existing SELinux
entries, you can use ``selinux_baseline.py`` located in the ``tools/``
directory to do that for you.
-In certain cases, it may be necessary to create multiple SELinux
-entries with the same name. For instance, "root" is both an SELinux
-user and an SELinux login record; or a given fcontext may need two
-different SELinux types depending on whether it's a symlink or a plain
-file. In these (few) cases, it is necessary to create BoundSELinux
-entries directly in Bundler rather than using abstract SELinux entries
-in Bundler and binding them with Rules.
-
See :ref:`server-selinux` for more information.
-boolean
-^^^^^^^
+SEBoolean Tag
+^^^^^^^^^^^^^
+-------+----------------------+---------+----------+
| Name | Description | Values | Required |
@@ -432,8 +422,8 @@ boolean
| value | Value of the boolean | on|off | Yes |
+-------+----------------------+---------+----------+
-port
-^^^^
+SEPort Tag
+^^^^^^^^^^
+-------------+------------------------+---------------------------+----------+
| Name | Description | Values | Required |
@@ -445,8 +435,8 @@ port
| | to this port | | |
+-------------+------------------------+---------------------------+----------+
-fcontext
-^^^^^^^^
+SEFcontext Tag
+^^^^^^^^^^^^^^
+-------------+-------------------------+---------------------+----------+
| Name | Description | Values | Required |
@@ -462,8 +452,8 @@ fcontext
| | | socket|block|char) | |
+-------------+-------------------------+---------------------+----------+
-node
-^^^^
+SENode Tag
+^^^^^^^^^^
+-------------+------------------------------------+------------------+----------+
| Name | Description | Values | Required |
@@ -477,8 +467,8 @@ node
| proto | Protocol | (ipv4|ipv6) | Yes |
+-------------+------------------------------------+------------------+----------+
-login
-^^^^^
+SELogin Tag
+^^^^^^^^^^^
+-------------+-------------------------------+-----------+----------+
| Name | Description | Values | Required |
@@ -488,8 +478,8 @@ login
| selinuxuser | SELinux username | String | Yes |
+-------------+-------------------------------+-----------+----------+
-user
-^^^^
+SEUser Tag
+^^^^^^^^^^
+-------------+-------------------------------+-----------+----------+
| Name | Description | Values | Required |
@@ -501,8 +491,8 @@ user
| prefix | Home directory context prefix | String | Yes |
+-------------+-------------------------------+-----------+----------+
-interface
-^^^^^^^^^
+SEInterface Tag
+^^^^^^^^^^^^^^^
+-------------+-------------------------+-------------+----------+
| Name | Description | Values | Required |
@@ -513,8 +503,8 @@ interface
| | to this interface | | |
+-------------+-------------------------+-------------+----------+
-permissive
-^^^^^^^^^^
+SEPermissive Tag
+^^^^^^^^^^^^^^^^
+-------------+------------------------------------+-------------+----------+
| Name | Description | Values | Required |
@@ -522,8 +512,8 @@ permissive
| name | SELinux type to make permissive | String | Yes |
+-------------+------------------------------------+-------------+----------+
-module
-^^^^^^
+SEModule Tag
+^^^^^^^^^^^^
See :ref:`server-plugins-generators-semodules`
diff --git a/doc/server/selinux.txt b/doc/server/selinux.txt
index e61a09002..9f54b0d68 100644
--- a/doc/server/selinux.txt
+++ b/doc/server/selinux.txt
@@ -135,47 +135,16 @@ will be considered extra, making ``selinux_baseline.py`` quite
necessary.
``selinux_baseline.py`` writes a bundle to stdout that contains
-``BoundSELinux`` entries for the appropriate SELinux entities. It
-does this rather than separate Bundle/Rules files because of the
-:ref:`server-selinux-duplicate-entries` problem.
+``BoundSELinux`` entries for the appropriate SELinux entities.
.. _server-selinux-duplicate-entries:
Duplicate Entries
-----------------
-In certain cases, it may be necessary to create multiple SELinux
-entries with the same name. For instance, "root" is both an SELinux
-user and an SELinux login record, so to manage both, you would have
-the following in Bundler:
-
-.. code-block:: xml
-
- <SELinux name="root"/>
- <SELinux name="root"/>
-
-And in Rules:
-
-.. code-block:: xml
-
- <SELinux type="login" selinuxuser="root" name="root"/>
- <SELinux type="user" prefix="user" name="root"
- roles="system_r sysadm_r user_r"/>
-
-But Rules has no way to tell which "root" is which, and you will get
-errors. In these cases, it is necessary to use ``BoundSELinux`` tags
-directly in Bundler. (See :ref:`boundentries` for more details on
-bound entries.) For instance:
-
-.. code-block:: xml
-
- <BoundSELinux type="login" selinuxuser="root" name="root"/>
- <BoundSELinux type="user" prefix="user" name="root"
- roles="system_r sysadm_r user_r"/>
-
-It may also be necessary to use ``BoundSELinux`` tags if a single
-fcontext needs two different SELinux types depending on whether it's a
-symlink or a plain file. For instance:
+It may be necessary to use `BoundSELinux` tags if a single fcontext
+needs two different SELinux types depending on whether it's a symlink
+or a plain file. For instance:
.. code-block:: xml
diff --git a/src/lib/Bcfg2/Client/Tools/SELinux.py b/src/lib/Bcfg2/Client/Tools/SELinux.py
index fc47883c9..7aa0e8a20 100644
--- a/src/lib/Bcfg2/Client/Tools/SELinux.py
+++ b/src/lib/Bcfg2/Client/Tools/SELinux.py
@@ -58,36 +58,44 @@ def netmask_itoa(netmask, proto="ipv4"):
class SELinux(Bcfg2.Client.Tools.Tool):
""" SELinux entry support """
name = 'SELinux'
- __handles__ = [('SELinux', 'boolean'),
- ('SELinux', 'port'),
- ('SELinux', 'fcontext'),
- ('SELinux', 'node'),
- ('SELinux', 'login'),
- ('SELinux', 'user'),
- ('SELinux', 'interface'),
- ('SELinux', 'permissive'),
- ('SELinux', 'module')]
- __req__ = dict(SELinux=dict(boolean=['name', 'value'],
- module=['name'],
- port=['name', 'selinuxtype'],
- fcontext=['name', 'selinuxtype'],
- node=['name', 'selinuxtype', 'proto'],
- login=['name', 'selinuxuser'],
- user=['name', 'roles', 'prefix'],
- interface=['name', 'selinuxtype'],
- permissive=['name']))
+ __handles__ = [('SEBoolean', None),
+ ('SEFcontext', None),
+ ('SEInterface', None),
+ ('SELogin', None),
+ ('SEModule', None),
+ ('SENode', None),
+ ('SEPermissive', None),
+ ('SEPort', None),
+ ('SEUser', None)]
+ __req__ = dict(SEBoolean=['name', 'value'],
+ SEFcontext=['name', 'selinuxtype'],
+ SEInterface=['name', 'selinuxtype'],
+ SELogin=['name', 'selinuxuser'],
+ SEModule=['name'],
+ SENode=['name', 'selinuxtype', 'proto'],
+ SEPermissive=['name'],
+ SEPort=['name', 'selinuxtype'],
+ SEUser=['name', 'roles', 'prefix'])
def __init__(self, logger, setup, config):
Bcfg2.Client.Tools.Tool.__init__(self, logger, setup, config)
self.handlers = {}
- for handles in self.__handles__:
- etype = handles[1]
+ for handler in self.__handles__:
+ etype = handler[0]
self.handlers[etype] = \
globals()["SELinux%sHandler" % etype.title()](self, logger,
setup, config)
self.txn = False
self.post_txn_queue = []
+ def __getattr__(self, attr):
+ if attr.startswith("VerifySE"):
+ return self.GenericSEVerify
+ elif attr.startswith("InstallSE"):
+ return self.GenericSEInstall
+ else:
+ return object.__getattr__(self, attr)
+
def BundleUpdated(self, _, states):
for handler in self.handlers.values():
handler.BundleUpdated(states)
@@ -100,12 +108,12 @@ class SELinux(Bcfg2.Client.Tools.Tool):
def canInstall(self, entry):
return (Bcfg2.Client.Tools.Tool.canInstall(self, entry) and
- self.handlers[entry.get('type')].canInstall(entry))
+ self.handlers[entry.tag].canInstall(entry))
def primarykey(self, entry):
""" return a string that should be unique amongst all entries
in the specification """
- return self.handlers[entry.get('type')].primarykey(entry)
+ return self.handlers[entry.tag].primarykey(entry)
def Install(self, entries, states):
# start a transaction
@@ -125,32 +133,32 @@ class SELinux(Bcfg2.Client.Tools.Tool):
for func, arg, kwargs in self.post_txn_queue:
states[arg] = func(*arg, **kwargs)
- def InstallSELinux(self, entry):
- """Dispatch install to the proper method according to type"""
- return self.handlers[entry.get('type')].Install(entry)
+ def GenericSEInstall(self, entry):
+ """Dispatch install to the proper method according to entry tag"""
+ return self.handlers[entry.tag].Install(entry)
- def VerifySELinux(self, entry, _):
- """Dispatch verify to the proper method according to type"""
- rv = self.handlers[entry.get('type')].Verify(entry)
+ def GenericSEVerify(self, entry, _):
+ """Dispatch verify to the proper method according to entry tag"""
+ rv = self.handlers[entry.tag].Verify(entry)
if entry.get('qtext') and self.setup['interactive']:
entry.set('qtext',
- '%s\nInstall SELinux %s %s: (y/N) ' %
+ '%s\nInstall %s: (y/N) ' %
(entry.get('qtext'),
- entry.get('type'),
- self.handlers[entry.get('type')].tostring(entry)))
+ self.handlers[entry.tag].tostring(entry)))
return rv
def Remove(self, entries):
- """Dispatch verify to the proper removal method according to type"""
+ """Dispatch verify to the proper removal
+ method according to entry tag"""
# sort by type
types = list()
for entry in entries:
- if entry.get('type') not in types:
- types.append(entry.get('type'))
+ if entry.tag not in types:
+ types.append(entry.tag)
for etype in types:
self.handlers[etype].Remove([e for e in entries
- if e.get('type') == etype])
+ if e.tag == etype])
class SELinuxEntryHandler(object):
@@ -253,8 +261,7 @@ class SELinuxEntryHandler(object):
def key2entry(self, key):
""" Generate an XML entry from an SELinux record key """
attrs = self._key2attrs(key)
- attrs["type"] = self.etype
- return Bcfg2.Client.XML.Element("SELinux", **attrs)
+ return Bcfg2.Client.XML.Element(self.etype, **attrs)
def _args(self, entry, method):
""" Get the argument list for invoking _modify or _add, or
@@ -279,7 +286,7 @@ class SELinuxEntryHandler(object):
""" return a string that should be unique amongst all entries
in the specification. some entry types are not universally
disambiguated by tag:type:name alone """
- return ":".join([entry.tag, entry.get("type"), entry.get("name")])
+ return ":".join([entry.tag, entry.get("name")])
def exists(self, entry):
""" return True if the entry already exists in the record list """
@@ -303,8 +310,8 @@ class SELinuxEntryHandler(object):
continue
if current_attrs[attr] != desired_attrs[attr]:
entry.set('current_%s' % attr, current_attrs[attr])
- errors.append("SELinux %s %s has wrong %s: %s, should be %s" %
- (self.etype, self.tostring(entry), attr,
+ errors.append("%s %s has wrong %s: %s, should be %s" %
+ (entry.tag, entry.get('name'), attr,
current_attrs[attr], desired_attrs[attr]))
if errors:
@@ -331,8 +338,8 @@ class SELinuxEntryHandler(object):
return True
except ValueError:
err = sys.exc_info()[1]
- self.logger.debug("Failed to %s SELinux %s %s: %s" %
- (method, self.etype, self.tostring(entry), err))
+ self.logger.info("Failed to %s SELinux %s %s: %s" %
+ (method, self.etype, self.tostring(entry), err))
return False
def Remove(self, entries):
@@ -365,7 +372,7 @@ class SELinuxEntryHandler(object):
pass
-class SELinuxBooleanHandler(SELinuxEntryHandler):
+class SELinuxSebooleanHandler(SELinuxEntryHandler):
""" handle SELinux boolean entries """
etype = "boolean"
value_format = ("value",)
@@ -414,7 +421,7 @@ class SELinuxBooleanHandler(SELinuxEntryHandler):
SELinuxEntryHandler.canInstall(self, entry))
-class SELinuxPortHandler(SELinuxEntryHandler):
+class SELinuxSeportHandler(SELinuxEntryHandler):
""" handle SELinux port entries """
etype = "port"
value_format = ('selinuxtype', None)
@@ -486,7 +493,7 @@ class SELinuxPortHandler(SELinuxEntryHandler):
return tuple(entry.get("name").split("/"))
-class SELinuxFcontextHandler(SELinuxEntryHandler):
+class SELinuxSefcontextHandler(SELinuxEntryHandler):
""" handle SELinux file context entries """
etype = "fcontext"
@@ -556,11 +563,11 @@ class SELinuxFcontextHandler(SELinuxEntryHandler):
'', '')
def primarykey(self, entry):
- return ":".join([entry.tag, entry.get("type"), entry.get("name"),
+ return ":".join([entry.tag, entry.get("name"),
entry.get("filetype", "all")])
-class SELinuxNodeHandler(SELinuxEntryHandler):
+class SELinuxSenodeHandler(SELinuxEntryHandler):
""" handle SELinux node entries """
etype = "node"
@@ -592,7 +599,7 @@ class SELinuxNodeHandler(SELinuxEntryHandler):
entry.get("selinuxtype"))
-class SELinuxLoginHandler(SELinuxEntryHandler):
+class SELinuxSeloginHandler(SELinuxEntryHandler):
""" handle SELinux login entries """
etype = "login"
@@ -603,7 +610,7 @@ class SELinuxLoginHandler(SELinuxEntryHandler):
return (entry.get("name"), entry.get("selinuxuser"), "")
-class SELinuxUserHandler(SELinuxEntryHandler):
+class SELinuxSeuserHandler(SELinuxEntryHandler):
""" handle SELinux user entries """
etype = "user"
@@ -652,7 +659,7 @@ class SELinuxUserHandler(SELinuxEntryHandler):
return tuple(rv)
-class SELinuxInterfaceHandler(SELinuxEntryHandler):
+class SELinuxSeinterfaceHandler(SELinuxEntryHandler):
""" handle SELinux interface entries """
etype = "interface"
@@ -663,7 +670,7 @@ class SELinuxInterfaceHandler(SELinuxEntryHandler):
return (entry.get("name"), '', entry.get("selinuxtype"))
-class SELinuxPermissiveHandler(SELinuxEntryHandler):
+class SELinuxSepermissiveHandler(SELinuxEntryHandler):
""" handle SELinux permissive domain entries """
etype = "permissive"
@@ -695,7 +702,7 @@ class SELinuxPermissiveHandler(SELinuxEntryHandler):
return (entry.get("name"),)
-class SELinuxModuleHandler(SELinuxEntryHandler):
+class SELinuxSemoduleHandler(SELinuxEntryHandler):
""" handle SELinux module entries """
etype = "module"
@@ -808,10 +815,9 @@ class SELinuxModuleHandler(SELinuxEntryHandler):
def Install(self, entry, _=None):
if not self.filetool.install(self._pathentry(entry)):
return False
- if hasattr(self, 'records'):
+ if hasattr(seobject, 'moduleRecords'):
# if seobject has the moduleRecords attribute, install the
# module using the seobject library
- self.records # pylint: disable=W0104
return self._install_seobject(entry)
else:
# seobject doesn't have the moduleRecords attribute, so
@@ -891,8 +897,7 @@ class SELinuxModuleHandler(SELinuxEntryHandler):
def FindExtra(self):
specified = [self._key(e)
- for e in self.tool.getSupportedEntries()
- if e.get("type") == self.etype]
+ for e in self.tool.getSupportedEntries()]
rv = []
for module in self._all_records_from_filesystem().keys():
if module not in specified:
diff --git a/src/lib/Bcfg2/Server/Plugins/SEModules.py b/src/lib/Bcfg2/Server/Plugins/SEModules.py
index 3edfb72a3..fa47f9496 100644
--- a/src/lib/Bcfg2/Server/Plugins/SEModules.py
+++ b/src/lib/Bcfg2/Server/Plugins/SEModules.py
@@ -40,8 +40,8 @@ class SEModules(Bcfg2.Server.Plugin.GroupSpool):
#: objects as its EntrySet children.
es_child_cls = SEModuleData
- #: SEModules manages ``SELinux`` entries
- entry_type = 'SELinux'
+ #: SEModules manages ``SEModule`` entries
+ entry_type = 'SEModule'
#: The SEModules plugin is experimental
experimental = True
@@ -68,7 +68,7 @@ class SEModules(Bcfg2.Server.Plugin.GroupSpool):
return name.lstrip("/")
def HandlesEntry(self, entry, metadata):
- if entry.tag in self.Entries and entry.get('type') == 'module':
+ if entry.tag in self.Entries:
return self._get_module_filename(entry) in self.Entries[entry.tag]
return Bcfg2.Server.Plugin.GroupSpool.HandlesEntry(self, entry,
metadata)