cebaad
From 4ebcf9d422bef11bd5b50f421a4b30ed826d1cbb Mon Sep 17 00:00:00 2001
cebaad
From: Vladimir Slavik <vslavik@redhat.com>
cebaad
Date: Tue, 15 Sep 2020 09:57:58 +0200
cebaad
Subject: [PATCH 20001/20005] Import RPM certificates at end of installation
cebaad
cebaad
This adds code and a new config key for importing RPM certificates, and
cebaad
enables it for all of Fedora.
cebaad
cebaad
Resolves: rhbz#748320
cebaad
Resolves: rhbz#1858006
cebaad
cebaad
(cherry picked from commit 5145db39e88b08eb23ac1b96c1a14f1eb73b2e86)
cebaad
---
cebaad
 data/anaconda.conf                            |  4 +++
cebaad
 data/product.d/centos-stream.conf             |  2 ++
cebaad
 data/product.d/fedora.conf                    |  4 +++
cebaad
 pyanaconda/core/configuration/payload.py      |  5 +++
cebaad
 pyanaconda/core/regexes.py                    |  3 ++
cebaad
 pyanaconda/core/util.py                       | 20 ++++++++++++
cebaad
 pyanaconda/payload/dnf/payload.py             | 14 +++++++++
cebaad
 tests/nosetests/pyanaconda_tests/util_test.py | 31 +++++++++++++++++++
cebaad
 8 files changed, 83 insertions(+)
cebaad
cebaad
diff --git a/data/anaconda.conf b/data/anaconda.conf
cebaad
index 824f4bb56..ab6c15bb6 100644
cebaad
--- a/data/anaconda.conf
cebaad
+++ b/data/anaconda.conf
cebaad
@@ -97,6 +97,10 @@ check_supported_locales = False
cebaad
 # Enable ssl verification for all HTTP connection
cebaad
 verify_ssl = True
cebaad
 
cebaad
+# GPG keys to import to RPM database by default.
cebaad
+# Specify paths on the installed system, each on a line.
cebaad
+# Substitutions for $releasever and $basearch happen automatically.
cebaad
+default_rpm_gpg_keys =
cebaad
 
cebaad
 [Security]
cebaad
 # Enable SELinux usage in the installed system.
cebaad
diff --git a/data/product.d/centos-stream.conf b/data/product.d/centos-stream.conf
cebaad
index 723a48403..c8af2d2fe 100644
cebaad
--- a/data/product.d/centos-stream.conf
cebaad
+++ b/data/product.d/centos-stream.conf
cebaad
@@ -32,3 +32,5 @@ default_help_pages =
cebaad
 [Payload]
cebaad
 enable_closest_mirror = True
cebaad
 default_source = CLOSEST_MIRROR
cebaad
+default_rpm_gpg_keys =
cebaad
+    /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
cebaad
diff --git a/data/product.d/fedora.conf b/data/product.d/fedora.conf
cebaad
index 0b2eeeeab..31a9245c0 100644
cebaad
--- a/data/product.d/fedora.conf
cebaad
+++ b/data/product.d/fedora.conf
cebaad
@@ -15,3 +15,7 @@ default_help_pages =
cebaad
     fedora_help_placeholder.txt
cebaad
     fedora_help_placeholder.xml
cebaad
     fedora_help_placeholder.xml
cebaad
+
cebaad
+[Payload]
cebaad
+default_rpm_gpg_keys =
cebaad
+    /etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
cebaad
diff --git a/pyanaconda/core/configuration/payload.py b/pyanaconda/core/configuration/payload.py
cebaad
index 5dde92619..4cc2c0244 100644
cebaad
--- a/pyanaconda/core/configuration/payload.py
cebaad
+++ b/pyanaconda/core/configuration/payload.py
cebaad
@@ -107,3 +107,8 @@ class PayloadSection(Section):
cebaad
         this option.
cebaad
         """
cebaad
         return self._get_option("verify_ssl", bool)
cebaad
+
cebaad
+    @property
cebaad
+    def default_rpm_gpg_keys(self):
cebaad
+        """List of GPG keys to import into RPM database at end of installation."""
cebaad
+        return self._get_option("default_rpm_gpg_keys", str).split()
cebaad
diff --git a/pyanaconda/core/regexes.py b/pyanaconda/core/regexes.py
cebaad
index ab4cd900b..17d56b752 100644
cebaad
--- a/pyanaconda/core/regexes.py
cebaad
+++ b/pyanaconda/core/regexes.py
cebaad
@@ -197,3 +197,6 @@ MAC_OCTET = re.compile(r'[a-fA-F0-9][a-fA-F0-9]')
cebaad
 
cebaad
 # Name of initramfs connection created by NM based on MAC
cebaad
 NM_MAC_INITRAMFS_CONNECTION = re.compile(r'^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$')
cebaad
+
cebaad
+# OS version in os-release file
cebaad
+OS_RELEASE_OS_VERSION = re.compile(r"VERSION_ID=[\"']?([0-9a-z._-]+)[\"']?")
cebaad
diff --git a/pyanaconda/core/util.py b/pyanaconda/core/util.py
cebaad
index 6fab33ed5..73c9d5ba3 100644
cebaad
--- a/pyanaconda/core/util.py
cebaad
+++ b/pyanaconda/core/util.py
cebaad
@@ -47,6 +47,7 @@ from pyanaconda.core.constants import DRACUT_SHUTDOWN_EJECT, TRANSLATIONS_UPDATE
cebaad
     IPMI_ABORTED, X_TIMEOUT, TAINT_HARDWARE_UNSUPPORTED, TAINT_SUPPORT_REMOVED, \
cebaad
     WARNING_HARDWARE_UNSUPPORTED, WARNING_SUPPORT_REMOVED
cebaad
 from pyanaconda.core.constants import SCREENSHOTS_DIRECTORY, SCREENSHOTS_TARGET_DIRECTORY
cebaad
+from pyanaconda.core.regexes import OS_RELEASE_OS_VERSION
cebaad
 from pyanaconda.errors import RemovedModuleError
cebaad
 
cebaad
 from pyanaconda.anaconda_logging import program_log_lock
cebaad
@@ -1489,3 +1490,22 @@ def is_smt_enabled():
cebaad
     except (IOError, ValueError):
cebaad
         log.warning("Failed to detect SMT.")
cebaad
         return False
cebaad
+
cebaad
+
cebaad
+def get_os_version(sysroot=""):
cebaad
+    """Find version of the OS from the os-release file.
cebaad
+
cebaad
+    See os-release(5).
cebaad
+
cebaad
+    :param str sysroot: Where to look.
cebaad
+    :return str: The version
cebaad
+    """
cebaad
+    for filename in ("/etc/os-release", "/usr/lib/os-release"):
cebaad
+        try:
cebaad
+            with open(sysroot + filename, "r") as f:
cebaad
+                data = f.read(4096)  # 4 kB should be enough for everyone!
cebaad
+            return OS_RELEASE_OS_VERSION.findall(data)[0]
cebaad
+        except (FileNotFoundError, IndexError):
cebaad
+            pass
cebaad
+
cebaad
+    return None
cebaad
diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py
cebaad
index 47e00a49b..ac717e793 100644
cebaad
--- a/pyanaconda/payload/dnf/payload.py
cebaad
+++ b/pyanaconda/payload/dnf/payload.py
cebaad
@@ -2037,6 +2037,17 @@ class DNFPayload(Payload):
cebaad
         """Should we write the storage before doing the installation?"""
cebaad
         return True
cebaad
 
cebaad
+    def _import_rpm_keys(self):
cebaad
+        """Import GPG keys to RPM database."""
cebaad
+        if conf.payload.default_rpm_gpg_keys:
cebaad
+            # TODO: replace the interpolation with DNF once possible
cebaad
+            arch = util.execWithCapture("uname", ["-i"]).strip().replace("'", "")
cebaad
+            vers = util.get_os_version(conf.target.system_root)
cebaad
+            for key in conf.payload.default_rpm_gpg_keys:
cebaad
+                interpolated_key = key.replace("$releasever", vers).replace("$basearch", arch)
cebaad
+                log.info("Importing GPG key to RPM database: %s", interpolated_key)
cebaad
+                util.execInSysroot("rpm", ["--import", interpolated_key])
cebaad
+
cebaad
     def post_setup(self):
cebaad
         """Perform post-setup tasks.
cebaad
 
cebaad
@@ -2076,6 +2087,9 @@ class DNFPayload(Payload):
cebaad
         self._base.close()
cebaad
         super().post_install()
cebaad
 
cebaad
+        # rpm needs importing installed certificates manually, see rhbz#748320 and rhbz#185800
cebaad
+        self._import_rpm_keys()
cebaad
+
cebaad
     @property
cebaad
     def kernel_version_list(self):
cebaad
         # Find all installed rpms that provide 'kernel'
cebaad
diff --git a/tests/nosetests/pyanaconda_tests/util_test.py b/tests/nosetests/pyanaconda_tests/util_test.py
cebaad
index f047a1e66..c2c3c0c0f 100644
cebaad
--- a/tests/nosetests/pyanaconda_tests/util_test.py
cebaad
+++ b/tests/nosetests/pyanaconda_tests/util_test.py
cebaad
@@ -855,3 +855,34 @@ class MiscTests(unittest.TestCase):
cebaad
         )
cebaad
         self.assertEqual(get_anaconda_version_string(), "1.0")
cebaad
         self.assertEqual(get_anaconda_version_string(build_time_version=True), "1.0-1")
cebaad
+
cebaad
+    def get_os_version_test(self):
cebaad
+        """Test get_os_version."""
cebaad
+        with tempfile.TemporaryDirectory() as root:
cebaad
+            # prepare paths
cebaad
+            util.mkdirChain(root + "/usr/lib")
cebaad
+            util.mkdirChain(root + "/etc")
cebaad
+
cebaad
+            # backup file only
cebaad
+            with open(root + "/usr/lib/os-release", "w") as f:
cebaad
+                f.write("# blah\nVERSION_ID=foo256bar  \n VERSION_ID = wrong\n\n")
cebaad
+            version = util.get_os_version(root)
cebaad
+            self.assertEqual(version, "foo256bar")
cebaad
+
cebaad
+            # main file and backup too
cebaad
+            with open(root + "/etc/os-release", "w") as f:
cebaad
+                f.write("# blah\nVERSION_ID=more-important\n")
cebaad
+            version = util.get_os_version(root)
cebaad
+            self.assertEqual(version, "more-important")
cebaad
+
cebaad
+            # both, main file twice
cebaad
+            with open(root + "/etc/os-release", "w") as f:
cebaad
+                f.write("# blah\nVERSION_ID=more-important\nVERSION_ID=not-reached\n \n")
cebaad
+            version = util.get_os_version(root)
cebaad
+            self.assertEqual(version, "more-important")
cebaad
+
cebaad
+            # no files
cebaad
+            os.remove(root + "/usr/lib/os-release")
cebaad
+            os.remove(root + "/etc/os-release")
cebaad
+            version = util.get_os_version(root)
cebaad
+            self.assertEqual(version, None)
cebaad
-- 
cebaad
2.31.1
cebaad