937546
From 7e9d17ca027b377c54288eb06ead7602a2a5136b Mon Sep 17 00:00:00 2001
937546
From: Christian Heimes <cheimes@redhat.com>
937546
Date: Wed, 12 Dec 2018 17:32:06 +0100
937546
Subject: [PATCH] Don't configure KEYRING ccache in containers
937546
937546
Kernel keyrings are not namespaced yet. Keyrings can leak into other
937546
containers. Therefore keyrings should not be used in containerized
937546
environment.
937546
937546
Don't configure Kerberos to use KEYRING ccache backen when a container
937546
environment is detected by systemd-detect-virt --container.
937546
937546
Fixes: https://pagure.io/freeipa/issue/7807
937546
Signed-off-by: Christian Heimes <cheimes@redhat.com>
937546
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
937546
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
937546
Reviewed-By: Oleg Kozlov <okozlov@redhat.com>
937546
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
937546
---
937546
 ipaplatform/base/paths.py               |  1 +
937546
 ipaplatform/base/tasks.py               |  8 +++++++
937546
 ipaplatform/redhat/tasks.py             | 21 ++++++++++++++++
937546
 ipapython/kernel_keyring.py             | 10 +++++++-
937546
 ipatests/test_ipaplatform/test_tasks.py | 32 +++++++++++++++++++++++++
937546
 5 files changed, 71 insertions(+), 1 deletion(-)
937546
 create mode 100644 ipatests/test_ipaplatform/test_tasks.py
937546
937546
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
937546
index 435d1b7de9083ee74e80da6fef5c3e3cdad654bb..0395e40b7fb624cd6f625a0cd959c4a216731f6d 100644
937546
--- a/ipaplatform/base/paths.py
937546
+++ b/ipaplatform/base/paths.py
937546
@@ -30,6 +30,7 @@ class BasePathNamespace(object):
937546
     LS = "/bin/ls"
937546
     SH = "/bin/sh"
937546
     SYSTEMCTL = "/bin/systemctl"
937546
+    SYSTEMD_DETECT_VIRT = "/bin/systemd-detect-virt"
937546
     TAR = "/bin/tar"
937546
     AUTOFS_LDAP_AUTH_CONF = "/etc/autofs_ldap_auth.conf"
937546
     ETC_DIRSRV = "/etc/dirsrv"
937546
diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
937546
index cd0427197aaecde0139781a564be443e59f3f9df..49c39e99b475cef2945354b2aaadf20239421d34 100644
937546
--- a/ipaplatform/base/tasks.py
937546
+++ b/ipaplatform/base/tasks.py
937546
@@ -116,6 +116,14 @@ class BaseTaskNamespace(object):
937546
 
937546
         raise NotImplementedError()
937546
 
937546
+    def detect_container(self):
937546
+        """Check if running inside a container
937546
+
937546
+        :returns: container runtime or None
937546
+        :rtype: str, None
937546
+        """
937546
+        raise NotImplementedError
937546
+
937546
     def restore_hostname(self, fstore, statestore):
937546
         """
937546
         Restores the original hostname as backed up in the
937546
diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
937546
index 9ce0d8375c88cb3281149ef82c975d14f150e5a4..8f6dc9a0370c59a3d4a33e8699bbc8c228ca0e1d 100644
937546
--- a/ipaplatform/redhat/tasks.py
937546
+++ b/ipaplatform/redhat/tasks.py
937546
@@ -30,6 +30,7 @@ import os
937546
 import socket
937546
 import traceback
937546
 import errno
937546
+import subprocess
937546
 import sys
937546
 
937546
 from ctypes.util import find_library
937546
@@ -168,6 +169,26 @@ class RedHatTaskNamespace(BaseTaskNamespace):
937546
                  "resolution to 'lo' interface. You might need to enable IPv6 "
937546
                  "on the interface 'lo' in sysctl.conf.")
937546
 
937546
+    def detect_container(self):
937546
+        """Check if running inside a container
937546
+
937546
+        :returns: container runtime or None
937546
+        :rtype: str, None
937546
+        """
937546
+        try:
937546
+            output = subprocess.check_output(
937546
+                [paths.SYSTEMD_DETECT_VIRT, '--container'],
937546
+                stderr=subprocess.STDOUT
937546
+            )
937546
+        except subprocess.CalledProcessError as e:
937546
+            if e.returncode == 1:
937546
+                # No container runtime detected
937546
+                return None
937546
+            else:
937546
+                raise
937546
+        else:
937546
+            return output.decode('utf-8').strip()
937546
+
937546
     def restore_pre_ipa_client_configuration(self, fstore, statestore,
937546
                                              was_sssd_installed,
937546
                                              was_sssd_configured):
937546
diff --git a/ipapython/kernel_keyring.py b/ipapython/kernel_keyring.py
937546
index 6ae1e74493810fa25093fe134447dd4ba0f5da74..cd47108e5846bc2f78e45f222bdfbd0ca11b7d81 100644
937546
--- a/ipapython/kernel_keyring.py
937546
+++ b/ipapython/kernel_keyring.py
937546
@@ -24,6 +24,7 @@ import six
937546
 
937546
 from ipapython.ipautil import run
937546
 from ipaplatform.paths import paths
937546
+from ipaplatform.tasks import tasks
937546
 
937546
 # NOTE: Absolute path not required for keyctl since we reset the environment
937546
 #       in ipautil.run.
937546
@@ -68,7 +69,14 @@ def get_persistent_key(key):
937546
     return result.raw_output.rstrip()
937546
 
937546
 
937546
-def is_persistent_keyring_supported():
937546
+def is_persistent_keyring_supported(check_container=True):
937546
+    """Returns True if the kernel persistent keyring is supported.
937546
+
937546
+    If check_container is True and a containerized environment is detected,
937546
+    return False. There is no support for keyring namespace isolation yet.
937546
+    """
937546
+    if check_container and tasks.detect_container() is not None:
937546
+        return False
937546
     uid = os.geteuid()
937546
     try:
937546
         get_persistent_key(str(uid))
937546
diff --git a/ipatests/test_ipaplatform/test_tasks.py b/ipatests/test_ipaplatform/test_tasks.py
937546
new file mode 100644
937546
index 0000000000000000000000000000000000000000..524490c78defb6ce14bf76ea296a9a33db0cbf0a
937546
--- /dev/null
937546
+++ b/ipatests/test_ipaplatform/test_tasks.py
937546
@@ -0,0 +1,32 @@
937546
+#
937546
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
937546
+#
937546
+from __future__ import absolute_import
937546
+
937546
+import os
937546
+
937546
+from ipaplatform.tasks import tasks
937546
+
937546
+
937546
+def test_detect_container():
937546
+    container = None
937546
+    # naive detection, may fail for OpenVZ and other container runtimes
937546
+    if os.path.isfile('/run/systemd/container'):
937546
+        with open('/run/systemd/container') as f:
937546
+            container = f.read().strip()
937546
+    elif os.geteuid() == 0:
937546
+        with open('/proc/1/environ') as f:
937546
+            environ = f.read()
937546
+        for item in environ.split('\x00'):
937546
+            if not item:
937546
+                continue
937546
+            k, v = item.split('=', 1)
937546
+            if k == 'container':
937546
+                container = v
937546
+
937546
+    detected = tasks.detect_container()
937546
+    if container == 'oci':
937546
+        # systemd doesn't know about podman
937546
+        assert detected in {'container-other', container}
937546
+    else:
937546
+        assert detected == container
937546
-- 
937546
2.20.1
937546