pgreco / rpms / ipa

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