- Restore SELinux context of session_dir /etc/httpd/alias (pagure#7662)

- Restore SELinux context of template_dir /var/log/dirsrv/slapd-X (pagure#7662)
- Add "389-ds-base-legacy-tools" to requires
- Refactor os-release and platform information (#1609475)
- Don't check for systemd service (#1609475)
- Switched to upstream spec file with small adaptions
This commit is contained in:
Thomas Woerner 2018-09-03 17:50:10 +02:00
parent f6a1c1b62c
commit e7de033e9e
5 changed files with 940 additions and 444 deletions

View File

@ -0,0 +1,63 @@
commit f7516979241ed80a48250784051a82457e2df7aa
Author: Thomas Woerner <twoerner@redhat.com>
Date: Thu Aug 2 11:22:55 2018 +0200
httpinstance: Restore SELinux context of session_dir /etc/httpd/alias
The session directory /etc/httpd/alias/ could be created with the wrong
SELinux context. Therefore httpd was not able to write to this directory.
Fixes: https://pagure.io/freeipa/issue/7662
Related-to: 49b4a057f1b0459331bcec2c8d760627d00e4571 (Create missing
/etc/httpd/alias for ipasession.key)
Reviewed-By: Christian Heimes <cheimes@redhat.com>
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 62b563fb2..1b1e7a03d 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -183,6 +183,9 @@ class HTTPInstance(service.Service):
os.makedirs(session_dir)
# Must be world-readable / executable
os.chmod(session_dir, 0o755)
+ # Restore SELinux context of session_dir /etc/httpd/alias, see
+ # https://pagure.io/freeipa/issue/7662
+ tasks.restore_context(session_dir)
target_fname = paths.HTTPD_IPA_CONF
http_txt = ipautil.template_file(
commit 354d7297e8e0d97da22c0469ab96f30fdfc4a1ea
Author: Thomas Woerner <twoerner@redhat.com>
Date: Thu Aug 2 11:32:05 2018 +0200
ipa_restore: Restore SELinux context of template_dir /var/log/dirsrv/slapd-X
The template directory /var/log/dirsrv/slapd-X could be created with the
wrong SELinux context.
Related to: https://pagure.io/freeipa/issue/7662
Reviewed-By: Christian Heimes <cheimes@redhat.com>
diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
index 48b95ed18..1916d3063 100644
--- a/ipaserver/install/ipa_restore.py
+++ b/ipaserver/install/ipa_restore.py
@@ -607,10 +607,13 @@ class Restore(admintool.AdminTool):
logger.info("Waiting for LDIF to finish")
wait_for_task(conn, dn)
else:
+ template_dir = paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance
try:
- os.makedirs(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance)
+ os.makedirs(template_dir)
except OSError as e:
pass
+ # Restore SELinux context of template_dir
+ tasks.restore_context(template_dir)
args = [paths.LDIF2DB,
'-Z', instance,

View File

@ -0,0 +1,23 @@
commit 90203fb044f4e51f341781cf64a9b30c1337d2a9
Author: Michal Reznik <mreznik@redhat.com>
Date: Fri Aug 31 09:49:15 2018 +0200
Add "389-ds-base-legacy-tools" to requires.
"389-ds-base-legacy-tools" needs to be added to requires until
the switch to python installer is completed.
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
diff --git a/freeipa.spec.in b/freeipa.spec.in
index 02881b494..cffbccd72 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -329,6 +329,7 @@ Requires: python2-ipaserver = %{version}-%{release}
Requires: python2-ldap >= %{python_ldap_version}
%endif
Requires: 389-ds-base >= %{ds_version}
+Requires: 389-ds-base-legacy-tools >= %{ds_version}
Requires: openldap-clients > 2.4.35-4
Requires: nss >= %{nss_version}
Requires: nss-tools >= %{nss_version}

View File

@ -0,0 +1,454 @@
commit b8528da5a8e8cf4fdeabb77022cb511043544e9f
Author: Christian Heimes <cheimes@redhat.com>
Date: Wed Aug 29 12:43:03 2018 +0200
Refactor os-release and platform information
Move the /etc/os-release parser and platform detection code out of the
private _importhook module. The ipaplatform module now contains an
osinfo module that provides distribution, os, and vendor information.
See: https://www.freedesktop.org/software/systemd/man/os-release.html
See: https://pagure.io/freeipa/issue/7661
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
diff --git a/ipaplatform/__init__.py b/ipaplatform/__init__.py
index 06397fda1..1c22346b0 100644
--- a/ipaplatform/__init__.py
+++ b/ipaplatform/__init__.py
@@ -8,4 +8,4 @@ ignore.
"""
__import__('pkg_resources').declare_namespace(__name__)
-NAME = None # initialized by IpaMetaImporter
+NAME = None # initialized by ipaplatform.osinfo
diff --git a/ipaplatform/_importhook.py b/ipaplatform/_importhook.py
index 77c4e0d87..3f84e81fd 100644
--- a/ipaplatform/_importhook.py
+++ b/ipaplatform/_importhook.py
@@ -3,46 +3,14 @@
#
from __future__ import absolute_import
-"""Meta import hook for ipaplatform.
-
-Known Linux distros with /etc/os-release
-----------------------------------------
-
-- alpine
-- centos (like rhel, fedora)
-- debian
-- fedora
-- rhel
-- ubuntu (like debian)
-"""
import importlib
-import io
-import re
import sys
-import warnings
-
-
-import ipaplatform
-try:
- from ipaplatform.override import OVERRIDE
-except ImportError:
- OVERRIDE = None
-
-_osrelease_line = re.compile(
- u"^(?!#)(?P<name>[a-zA-Z0-9_]+)="
- u"(?P<quote>[\"\']?)(?P<value>.+)(?P=quote)$"
-)
+from ipaplatform.osinfo import osinfo
class IpaMetaImporter(object):
- """Meta import hook and platform detector.
-
- The meta import hook uses /etc/os-release to auto-detects the best
- matching ipaplatform provider. It is compatible with external namespace
- packages, too.
- """
modules = {
'ipaplatform.constants',
'ipaplatform.paths',
@@ -50,80 +18,8 @@ class IpaMetaImporter(object):
'ipaplatform.tasks'
}
- bsd_family = (
- 'freebsd',
- 'openbsd',
- 'netbsd',
- 'dragonfly',
- 'gnukfreebsd'
- )
-
- def __init__(self, override=OVERRIDE):
- self.override = override
- self.platform_ids = self._get_platform_ids(self.override)
- self.platform = self._get_platform(self.platform_ids)
-
- def _get_platform_ids(self, override):
- platforms = []
- # allow RPM and Debian packages to override platform
- if override is not None:
- platforms.append(override)
-
- if sys.platform.startswith('linux'):
- # Linux, get distribution from /etc/os-release
- try:
- platforms.extend(self._parse_platform())
- except Exception as e:
- warnings.warn("Failed to read /etc/os-release: {}".format(e))
- elif sys.platform == 'win32':
- # Windows 32 or 64bit platform
- platforms.append('win32')
- elif sys.platform == 'darwin':
- # macOS
- platforms.append('macos')
- elif sys.platform.startswith(self.bsd_family):
- # BSD family, look for e.g. ['freebsd10', 'freebsd']
- platforms.append(sys.platform)
- simple = sys.platform.rstrip('0123456789')
- if simple != sys.platform:
- platforms.append(simple)
-
- if not platforms:
- raise ValueError("Unsupported platform: {}".format(sys.platform))
-
- return platforms
-
- def parse_osrelease(self, filename='/etc/os-release'):
- release = {}
- with io.open(filename, encoding='utf-8') as f:
- for line in f:
- mo = _osrelease_line.match(line)
- if mo is not None:
- release[mo.group('name')] = mo.group('value')
- return release
-
- def _parse_platform(self, filename='/etc/os-release'):
- release = self.parse_osrelease(filename)
- platforms = [
- release['ID'],
- ]
- if "ID_LIKE" in release:
- platforms.extend(
- v.strip() for v in release['ID_LIKE'].split(' ') if v.strip()
- )
-
- return platforms
-
- def _get_platform(self, platform_ids):
- for platform in platform_ids:
- try:
- importlib.import_module('ipaplatform.{}'.format(platform))
- except ImportError:
- pass
- else:
- return platform
- raise ImportError('No ipaplatform available for "{}"'.format(
- ', '.join(platform_ids)))
+ def __init__(self, platform):
+ self.platform = platform
def find_module(self, fullname, path=None):
"""Meta importer hook"""
@@ -148,8 +44,7 @@ class IpaMetaImporter(object):
return platform_mod
-metaimporter = IpaMetaImporter()
+metaimporter = IpaMetaImporter(osinfo.platform)
sys.meta_path.insert(0, metaimporter)
fixup_module = metaimporter.load_module
-ipaplatform.NAME = metaimporter.platform
diff --git a/ipaplatform/osinfo.py b/ipaplatform/osinfo.py
new file mode 100644
index 000000000..a38165d01
--- /dev/null
+++ b/ipaplatform/osinfo.py
@@ -0,0 +1,214 @@
+#
+# Copyright (C) 2018 FreeIPA Contributors see COPYING for license
+#
+"""Distribution information
+
+Known Linux distros with /etc/os-release
+----------------------------------------
+
+- alpine
+- centos (like rhel, fedora)
+- debian
+- fedora
+- rhel
+- ubuntu (like debian)
+"""
+from __future__ import absolute_import
+
+import importlib
+import io
+import re
+import sys
+import warnings
+
+import six
+
+import ipaplatform
+try:
+ from ipaplatform.override import OVERRIDE
+except ImportError:
+ OVERRIDE = None
+
+
+# pylint: disable=no-name-in-module, import-error
+if six.PY3:
+ from collections.abc import Mapping
+else:
+ from collections import Mapping
+# pylint: enable=no-name-in-module, import-error
+
+_osrelease_line = re.compile(
+ u"^(?!#)(?P<name>[a-zA-Z0-9_]+)="
+ u"(?P<quote>[\"\']?)(?P<value>.+)(?P=quote)$"
+)
+
+
+def _parse_osrelease(filename='/etc/os-release'):
+ """Parser for /etc/os-release for Linux distributions
+
+ https://www.freedesktop.org/software/systemd/man/os-release.html
+ """
+ release = {}
+ with io.open(filename, encoding='utf-8') as f:
+ for line in f:
+ mo = _osrelease_line.match(line)
+ if mo is not None:
+ release[mo.group('name')] = mo.group('value')
+ if 'ID_LIKE' in release:
+ release['ID_LIKE'] = tuple(
+ v.strip()
+ for v in release['ID_LIKE'].split(' ')
+ if v.strip()
+ )
+ else:
+ release["ID_LIKE"] = ()
+ # defaults
+ release.setdefault('NAME', 'Linux')
+ release.setdefault('ID', 'linux')
+ release.setdefault('VERSION', '')
+ release.setdefault('VERSION_ID', '')
+ return release
+
+
+class OSInfo(Mapping):
+ __slots__ = ('_info', '_platform')
+
+ bsd_family = (
+ 'freebsd',
+ 'openbsd',
+ 'netbsd',
+ 'dragonfly',
+ 'gnukfreebsd'
+ )
+
+ def __init__(self):
+ if sys.platform.startswith('linux'):
+ # Linux, get distribution from /etc/os-release
+ info = self._handle_linux()
+ elif sys.platform == 'win32':
+ info = self._handle_win32()
+ elif sys.platform == 'darwin':
+ info = self._handle_darwin()
+ elif sys.platform.startswith(self.bsd_family):
+ info = self._handle_bsd()
+ else:
+ raise ValueError("Unsupported platform: {}".format(sys.platform))
+ self._info = info
+ self._platform = None
+
+ def _handle_linux(self):
+ """Detect Linux distribution from /etc/os-release
+ """
+ try:
+ return _parse_osrelease()
+ except Exception as e:
+ warnings.warn("Failed to read /etc/os-release: {}".format(e))
+ return {
+ 'NAME': 'Linux',
+ 'ID': 'linux',
+ }
+
+ def _handle_win32(self):
+ """Windows 32 or 64bit platform
+ """
+ return {
+ 'NAME': 'Windows',
+ 'ID': 'win32',
+ }
+
+ def _handle_darwin(self):
+ """Handle macOS / Darwin platform
+ """
+ return {
+ 'NAME': 'macOS',
+ 'ID': 'macos',
+ }
+
+ def _handle_bsd(self):
+ """Handle BSD-like platforms
+ """
+ platform = sys.platform
+ simple = platform.rstrip('0123456789')
+ id_like = []
+ if simple != platform:
+ id_like.append(simple)
+ return {
+ 'NAME': platform,
+ 'ID': platform,
+ 'ID_LIKE': tuple(id_like),
+ }
+
+ def __getitem__(self, item):
+ return self._info[item]
+
+ def __iter__(self):
+ return iter(self._info)
+
+ def __len__(self):
+ return len(self._info)
+
+ @property
+ def name(self):
+ """OS name (user)
+ """
+ return self._info['NAME']
+
+ @property
+ def id(self):
+ """Lower case OS identifier
+ """
+ return self._info['ID']
+
+ @property
+ def id_like(self):
+ """Related / similar OS
+ """
+ return self._info.get('ID_LIKE', ())
+
+ @property
+ def version(self):
+ """Version number and name of OS (for user)
+ """
+ return self._info.get('VERSION')
+
+ @property
+ def version_id(self):
+ """Version identifier
+ """
+ return self._info.get('VERSION_ID')
+
+ @property
+ def platform_ids(self):
+ """Ordered tuple of detected platforms (including override)
+ """
+ platforms = []
+ if OVERRIDE is not None:
+ # allow RPM and Debian packages to override platform
+ platforms.append(OVERRIDE)
+ if OVERRIDE != self.id:
+ platforms.append(self.id)
+ platforms.extend(self.id_like)
+ return tuple(platforms)
+
+ @property
+ def platform(self):
+ if self._platform is not None:
+ return self._platform
+ for platform in self.platform_ids:
+ try:
+ importlib.import_module('ipaplatform.{}'.format(platform))
+ except ImportError:
+ pass
+ else:
+ self._platform = platform
+ return platform
+ raise ImportError('No ipaplatform available for "{}"'.format(
+ ', '.join(self.platform_ids)))
+
+
+osinfo = OSInfo()
+ipaplatform.NAME = osinfo.platform
+
+if __name__ == '__main__':
+ import pprint
+ pprint.pprint(dict(osinfo))
diff --git a/ipatests/test_ipaplatform/test_importhook.py b/ipatests/test_ipaplatform/test_importhook.py
index c7d2626d6..eeb351ba7 100644
--- a/ipatests/test_ipaplatform/test_importhook.py
+++ b/ipatests/test_ipaplatform/test_importhook.py
@@ -13,6 +13,7 @@ import ipaplatform.paths
import ipaplatform.services
import ipaplatform.tasks
from ipaplatform._importhook import metaimporter
+from ipaplatform.osinfo import osinfo, _parse_osrelease
try:
from ipaplatform.override import OVERRIDE
except ImportError:
@@ -26,8 +27,8 @@ DATA = os.path.join(HERE, 'data')
@pytest.mark.skipif(OVERRIDE is None,
reason='test requires override')
def test_override():
- assert OVERRIDE == metaimporter.platform_ids[0]
- assert OVERRIDE == metaimporter.platform
+ assert OVERRIDE == osinfo.platform_ids[0]
+ assert OVERRIDE == osinfo.platform
@pytest.mark.parametrize('mod, name', [
@@ -46,11 +47,12 @@ def test_importhook(mod, name):
assert mod.__dict__ == sys.modules[override].__dict__
-@pytest.mark.parametrize('filename, expected_platforms', [
- (os.path.join(DATA, 'os-release-centos'), ['centos', 'rhel', 'fedora']),
- (os.path.join(DATA, 'os-release-fedora'), ['fedora']),
- (os.path.join(DATA, 'os-release-ubuntu'), ['ubuntu', 'debian']),
+@pytest.mark.parametrize('filename, id_, id_like', [
+ (os.path.join(DATA, 'os-release-centos'), 'centos', ('rhel', 'fedora')),
+ (os.path.join(DATA, 'os-release-fedora'), 'fedora', ()),
+ (os.path.join(DATA, 'os-release-ubuntu'), 'ubuntu', ('debian',)),
])
-def test_parse_os_release(filename, expected_platforms):
- parsed = metaimporter._parse_platform(filename)
- assert parsed == expected_platforms
+def test_parse_os_release(filename, id_, id_like):
+ parsed = _parse_osrelease(filename)
+ assert parsed['ID'] == id_
+ assert parsed['ID_LIKE'] == id_like
diff --git a/ipatests/test_ipapython/test_certdb.py b/ipatests/test_ipapython/test_certdb.py
index 42edfb5a9..42d48d51a 100644
--- a/ipatests/test_ipapython/test_certdb.py
+++ b/ipatests/test_ipapython/test_certdb.py
@@ -5,13 +5,12 @@ import os
import pytest
from ipapython.certdb import NSSDatabase, TRUSTED_PEER_TRUST_FLAGS
-from ipaplatform._importhook import metaimporter
+from ipaplatform.osinfo import osinfo
-OSRELEASE = metaimporter.parse_osrelease()
CERTNICK = 'testcert'
-if OSRELEASE['ID'] == 'fedora':
- if int(OSRELEASE['VERSION_ID']) >= 28:
+if osinfo.id == 'fedora':
+ if int(osinfo.version_id) >= 28:
NSS_DEFAULT = 'sql'
else:
NSS_DEFAULT = 'dbm'

View File

@ -0,0 +1,42 @@
commit 1c03181e78b8f43e7bfd32e52c5b9d161c326fd6
Author: Christian Heimes <cheimes@redhat.com>
Date: Wed Aug 29 12:58:12 2018 +0200
Don't check for systemd service
ipaplatform no longer checks for the presence of a systemd service file
to detect the name of the domainname service. Instead it uses osinfo's
version to use the old name on Fedora 28 and the new name on Fedora 29.
This fixes a SELinux violation that prevented httpd from listing systemd
service files.
Fixes: https://pagure.io/freeipa/issue/7661
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
diff --git a/ipaplatform/fedora/services.py b/ipaplatform/fedora/services.py
index 09ba2e826..5ff64f1cd 100644
--- a/ipaplatform/fedora/services.py
+++ b/ipaplatform/fedora/services.py
@@ -24,8 +24,7 @@ Contains Fedora-specific service class implementations.
from __future__ import absolute_import
-import os
-
+from ipaplatform.osinfo import osinfo
from ipaplatform.redhat import services as redhat_services
# Mappings from service names as FreeIPA code references to these services
@@ -35,9 +34,7 @@ fedora_system_units = redhat_services.redhat_system_units.copy()
# Fedora 28 and earlier have fedora-domainname.service. Starting from
# Fedora 29, the service is called nis-domainname.service as defined in
# ipaplatform.redhat.services.
-HAS_FEDORA_DOMAINNAME_SERVICE = os.path.isfile(
- "/usr/lib/systemd/system/fedora-domainname.service"
-)
+HAS_FEDORA_DOMAINNAME_SERVICE = int(osinfo.version_id) <= 28
if HAS_FEDORA_DOMAINNAME_SERVICE:
fedora_system_units['domainname'] = 'fedora-domainname.service'

File diff suppressed because it is too large Load Diff