Blob Blame History Raw
From 7e9d17ca027b377c54288eb06ead7602a2a5136b Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Wed, 12 Dec 2018 17:32:06 +0100
Subject: [PATCH] Don't configure KEYRING ccache in containers

Kernel keyrings are not namespaced yet. Keyrings can leak into other
containers. Therefore keyrings should not be used in containerized
environment.

Don't configure Kerberos to use KEYRING ccache backen when a container
environment is detected by systemd-detect-virt --container.

Fixes: https://pagure.io/freeipa/issue/7807
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
Reviewed-By: Oleg Kozlov <okozlov@redhat.com>
Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
---
 ipaplatform/base/paths.py               |  1 +
 ipaplatform/base/tasks.py               |  8 +++++++
 ipaplatform/redhat/tasks.py             | 21 ++++++++++++++++
 ipapython/kernel_keyring.py             | 10 +++++++-
 ipatests/test_ipaplatform/test_tasks.py | 32 +++++++++++++++++++++++++
 5 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 ipatests/test_ipaplatform/test_tasks.py

diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 435d1b7de9083ee74e80da6fef5c3e3cdad654bb..0395e40b7fb624cd6f625a0cd959c4a216731f6d 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -30,6 +30,7 @@ class BasePathNamespace(object):
     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_DIRSRV = "/etc/dirsrv"
diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
index cd0427197aaecde0139781a564be443e59f3f9df..49c39e99b475cef2945354b2aaadf20239421d34 100644
--- a/ipaplatform/base/tasks.py
+++ b/ipaplatform/base/tasks.py
@@ -116,6 +116,14 @@ class BaseTaskNamespace(object):
 
         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 9ce0d8375c88cb3281149ef82c975d14f150e5a4..8f6dc9a0370c59a3d4a33e8699bbc8c228ca0e1d 100644
--- a/ipaplatform/redhat/tasks.py
+++ b/ipaplatform/redhat/tasks.py
@@ -30,6 +30,7 @@ import os
 import socket
 import traceback
 import errno
+import subprocess
 import sys
 
 from ctypes.util import find_library
@@ -168,6 +169,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 6ae1e74493810fa25093fe134447dd4ba0f5da74..cd47108e5846bc2f78e45f222bdfbd0ca11b7d81 100644
--- a/ipapython/kernel_keyring.py
+++ b/ipapython/kernel_keyring.py
@@ -24,6 +24,7 @@ import six
 
 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.
@@ -68,7 +69,14 @@ def get_persistent_key(key):
     return result.raw_output.rstrip()
 
 
-def is_persistent_keyring_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
new file mode 100644
index 0000000000000000000000000000000000000000..524490c78defb6ce14bf76ea296a9a33db0cbf0a
--- /dev/null
+++ b/ipatests/test_ipaplatform/test_tasks.py
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+from __future__ import absolute_import
+
+import os
+
+from ipaplatform.tasks import tasks
+
+
+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
-- 
2.20.1