diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 5919855a9..52fc8597f 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -30,6 +30,7 @@ class BasePathNamespace: LS = "/bin/ls" SH = "/bin/sh" SYSTEMCTL = "/bin/systemctl" + SYSTEMD_DETECT_VIRT = "/bin/systemd-detect-virt" TAR = "/bin/tar" AUTOFS_LDAP_AUTH_CONF = "/etc/autofs_ldap_auth.conf" ETC_FEDORA_RELEASE = "/etc/fedora-release" diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index a5e59ef2e..6afd542f1 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -106,6 +106,14 @@ class BaseTaskNamespace: raise NotImplementedError() + def detect_container(self): + """Check if running inside a container + + :returns: container runtime or None + :rtype: str, None + """ + raise NotImplementedError + def restore_hostname(self, fstore, statestore): """ Restores the original hostname as backed up in the diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index 8fa79f896..07c0f18f6 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -32,6 +32,7 @@ import socket import traceback import errno import urllib +import subprocess import sys from ctypes.util import find_library @@ -183,6 +184,26 @@ class RedHatTaskNamespace(BaseTaskNamespace): "resolution to 'lo' interface. You might need to enable IPv6 " "on the interface 'lo' in sysctl.conf.") + def detect_container(self): + """Check if running inside a container + + :returns: container runtime or None + :rtype: str, None + """ + try: + output = subprocess.check_output( + [paths.SYSTEMD_DETECT_VIRT, '--container'], + stderr=subprocess.STDOUT + ) + except subprocess.CalledProcessError as e: + if e.returncode == 1: + # No container runtime detected + return None + else: + raise + else: + return output.decode('utf-8').strip() + def restore_pre_ipa_client_configuration(self, fstore, statestore, was_sssd_installed, was_sssd_configured): diff --git a/ipapython/kernel_keyring.py b/ipapython/kernel_keyring.py index ce0df7724..20cf57789 100644 --- a/ipapython/kernel_keyring.py +++ b/ipapython/kernel_keyring.py @@ -23,6 +23,7 @@ import os from ipapython.ipautil import run from ipaplatform.paths import paths +from ipaplatform.tasks import tasks # NOTE: Absolute path not required for keyctl since we reset the environment # in ipautil.run. @@ -73,10 +74,14 @@ def get_persistent_key(key): return result.raw_output.rstrip() -def is_persistent_keyring_supported(): - """ - Returns True if the kernel persistent keyring is supported. +def is_persistent_keyring_supported(check_container=True): + """Returns True if the kernel persistent keyring is supported. + + If check_container is True and a containerized environment is detected, + return False. There is no support for keyring namespace isolation yet. """ + if check_container and tasks.detect_container() is not None: + return False uid = os.geteuid() try: get_persistent_key(str(uid)) diff --git a/ipatests/test_ipaplatform/test_tasks.py b/ipatests/test_ipaplatform/test_tasks.py index 5adb5838b..bc1e37ebf 100644 --- a/ipatests/test_ipaplatform/test_tasks.py +++ b/ipatests/test_ipaplatform/test_tasks.py @@ -3,6 +3,8 @@ # from __future__ import absolute_import +import os + from ipaplatform.tasks import tasks @@ -28,3 +30,27 @@ def test_ipa_version(): assert not v3 == v4 assert v4 > v3 assert v4 >= v3 + + +def test_detect_container(): + container = None + # naive detection, may fail for OpenVZ and other container runtimes + if os.path.isfile('/run/systemd/container'): + with open('/run/systemd/container') as f: + container = f.read().strip() + elif os.geteuid() == 0: + with open('/proc/1/environ') as f: + environ = f.read() + for item in environ.split('\x00'): + if not item: + continue + k, v = item.split('=', 1) + if k == 'container': + container = v + + detected = tasks.detect_container() + if container == 'oci': + # systemd doesn't know about podman + assert detected in {'container-other', container} + else: + assert detected == container