]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Rework crypto-policies again
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 21 Jan 2025 21:21:38 +0000 (22:21 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 22 Jan 2025 10:02:49 +0000 (11:02 +0100)
Currently, we only write our own rpm-sequoia crypto policy if one
isn't provided by the tools tree. However, the centos stream 10 crypto
policy is restrictive enough that we can't build older centos releases
or opensuse images with it.

To fix this, let's switch things around again and go back to copying
the crypto policy from the tools tree into the sandbox tree and modifying
the rpm-sequoia policy to fit our needs. For mkosi sandbox, we do reuse
the crypto policies from the tools tree unmodified.

Note that we copy from /usr/share/crypto-policies/DEFAULT instead of
/etc/crypto-policies, as when using mkosi sandbox, we get
/etc/crypto-policies from the host which is full of symlink's to the host's
/usr, even if the tools tree might not be using crypto policies at all.

We also rename finalize_crypto_mounts() to finalize_certificate_mounts()
as it only handles certificates now.

mkosi/__init__.py
mkosi/curl.py
mkosi/distributions/opensuse.py
mkosi/installer/__init__.py
mkosi/installer/rpm.py
mkosi/mounts.py

index 3a13440c02d5e35357a71cb95a2eb50aa1c6f68f..31f5b10a8537c4c1daeba72d70408ad3d6dd9b64 100644 (file)
@@ -83,7 +83,7 @@ from mkosi.installer import clean_package_manager_metadata
 from mkosi.kmod import gen_required_kernel_modules, loaded_modules, process_kernel_modules
 from mkosi.log import ARG_DEBUG, complete_step, die, log_notice, log_step
 from mkosi.manifest import Manifest
-from mkosi.mounts import finalize_crypto_mounts, finalize_source_mounts, mount_overlay
+from mkosi.mounts import finalize_certificate_mounts, finalize_source_mounts, mount_overlay
 from mkosi.pager import page
 from mkosi.partition import Partition, finalize_root, finalize_roothash
 from mkosi.qemu import (
@@ -612,7 +612,7 @@ def run_sync_scripts(config: Config) -> None:
 
         for script in config.sync_scripts:
             options = [
-                *finalize_crypto_mounts(config),
+                *finalize_certificate_mounts(config),
                 "--ro-bind", script, "/work/sync",
                 "--ro-bind", json, "/work/config.json",
                 "--dir", "/work/src",
@@ -1083,7 +1083,9 @@ def install_sandbox_trees(config: Config, dst: Path) -> None:
     # Ensure /etc exists in the sandbox
     (dst / "etc").mkdir(exist_ok=True)
 
-    (dst / "etc/crypto-policies").mkdir(exist_ok=True)
+    if (p := config.tools() / "usr/share/crypto-policies/DEFAULT").exists():
+        Path(dst / "etc/crypto-policies").mkdir(exist_ok=True)
+        copy_tree(p, dst / "etc/crypto-policies/back-ends", sandbox=config.sandbox)
 
     if config.sandbox_trees:
         with complete_step("Copying in sandbox trees…"):
@@ -3824,7 +3826,10 @@ def run_sandbox(args: Args, config: Config) -> None:
     if not args.cmdline:
         die("Please specify a command to execute in the sandbox")
 
-    mounts = finalize_crypto_mounts(config, relaxed=True)
+    mounts = finalize_certificate_mounts(config, relaxed=True)
+
+    if config.tools() != Path("/") and (config.tools() / "etc/crypto-policies").exists():
+        mounts += ["--ro-bind", config.tools() / "etc/crypto-policies", Path("/etc/crypto-policies")]
 
     # Since we reuse almost every top level directory from the host except /usr, the crypto mountpoints
     # have to exist already in these directories or we'll fail with a permission error. Let's check this
index 8d39acc970a5cde54a0684aea8b89d926bf2f2c5..eb8caadea2f1d82700de82a0a718a89599f650fe 100644 (file)
@@ -3,7 +3,7 @@
 from pathlib import Path
 
 from mkosi.config import Config
-from mkosi.mounts import finalize_crypto_mounts
+from mkosi.mounts import finalize_certificate_mounts
 from mkosi.run import run, workdir
 
 
@@ -25,6 +25,6 @@ def curl(config: Config, url: str, output_dir: Path) -> None:
         ],
         sandbox=config.sandbox(
             network=True,
-            options=["--bind", output_dir, workdir(output_dir), *finalize_crypto_mounts(config)],
+            options=["--bind", output_dir, workdir(output_dir), *finalize_certificate_mounts(config)],
         ),
     )  # fmt: skip
index 6b07ef53023f2d496cba8b72b075df3dd44e3145..9df535ddd7a8f7051c4d74831dc7d8d44e6a6d77 100644 (file)
@@ -14,7 +14,7 @@ from mkosi.installer.dnf import Dnf
 from mkosi.installer.rpm import RpmRepository, find_rpm_gpgkey, setup_rpm
 from mkosi.installer.zypper import Zypper
 from mkosi.log import die
-from mkosi.mounts import finalize_crypto_mounts
+from mkosi.mounts import finalize_certificate_mounts
 from mkosi.run import run
 from mkosi.util import sort_packages
 
@@ -117,7 +117,7 @@ class Installer(DistributionInstaller):
                     sandbox=context.sandbox(
                         options=[
                             "--bind", context.root, "/buildroot",
-                            *finalize_crypto_mounts(context.config),
+                            *finalize_certificate_mounts(context.config),
                         ],
                     ),
                 )  # fmt: skip
index 18352c6c39da9e7d55d1bab8cd7d1766a6d92ea2..50c659f84ab5477927f658681fe57cf415dc1367 100644 (file)
@@ -6,7 +6,7 @@ from pathlib import Path
 
 from mkosi.config import Config, ConfigFeature, OutputFormat
 from mkosi.context import Context
-from mkosi.mounts import finalize_crypto_mounts
+from mkosi.mounts import finalize_certificate_mounts
 from mkosi.run import apivfs_options, finalize_interpreter, finalize_passwd_symlinks, find_binary
 from mkosi.tree import rmtree
 from mkosi.types import PathString
@@ -68,7 +68,7 @@ class PackageManager:
     @classmethod
     def mounts(cls, context: Context) -> list[PathString]:
         mounts = [
-            *finalize_crypto_mounts(context.config),
+            *finalize_certificate_mounts(context.config),
             "--bind", context.repository, "/repository",
         ]  # fmt: skip
 
index a0bc60321cd894b7cd4ba187b52e3fbfe992c054..d3f614af486bf5bacc536f16a937375525f4c796 100644 (file)
@@ -7,6 +7,7 @@ from pathlib import Path
 from typing import Literal, Optional, overload
 
 from mkosi.context import Context
+from mkosi.distributions import Distribution
 from mkosi.log import die
 from mkosi.run import run
 from mkosi.types import PathString
@@ -100,25 +101,38 @@ def setup_rpm(
             for plugin in plugindir.iterdir():
                 f.write(f"%__transaction_{plugin.stem} %{{nil}}\n")
 
-    # Write an rpm sequoia policy that allows SHA1 as various distribution GPG keys (openSUSE) still use SHA1
-    # for various things.
-    # TODO: Remove when all rpm distribution GPG keys have stopped using SHA1.
-    if not (context.config.tools() / "etc/crypto-policies").exists():
+    if context.config.distribution == Distribution.opensuse or (
+        context.config.distribution.is_centos_variant() and context.config.release == "9"
+    ):
+        # Write an rpm sequoia policy that makes sure "sha1.second_preimage_resistance = always" is
+        # configured and makes sure that a minimal config is in place to make sure builds succeed.
+        # TODO: Remove when distributions GPG keys are accepted by the default rpm-sequoia config everywhere.
+
         p = context.sandbox_tree / "etc/crypto-policies/back-ends/rpm-sequoia.config"
         p.parent.mkdir(parents=True, exist_ok=True)
-        p.write_text(
-            textwrap.dedent(
-                """
-                [hash_algorithms]
-                sha1.second_preimage_resistance = "always"
-                sha224 = "always"
-                sha256 = "always"
-                sha384 = "always"
-                sha512 = "always"
-                default_disposition = "never"
-                """
-            )
-        )
+        prev = p.read_text() if p.exists() else ""
+
+        with p.open("w") as f:
+            for line in prev.splitlines(keepends=True):
+                if line.startswith("sha1.second_preimage_resistance"):
+                    f.write('sha1.second_preimage_resistance = "always"\n')
+                else:
+                    f.write(line)
+
+            if not any(line.startswith("[hash_algorithms]") for line in prev.splitlines()):
+                f.write(
+                    textwrap.dedent(
+                        """
+                        [hash_algorithms]
+                        sha1.second_preimage_resistance = "always"
+                        sha224 = "always"
+                        sha256 = "always"
+                        sha384 = "always"
+                        sha512 = "always"
+                        default_disposition = "never"
+                        """
+                    )
+                )
 
 
 def rpm_cmd() -> list[PathString]:
index 78ab8fc62e90686da97550dec050722ec4f83a24..31eb9c7de540b1cd7fda11a38c266f49da73caa4 100644 (file)
@@ -86,7 +86,7 @@ def finalize_source_mounts(config: Config, *, ephemeral: bool) -> Iterator[list[
         yield options
 
 
-def finalize_crypto_mounts(config: Config, relaxed: bool = False) -> list[PathString]:
+def finalize_certificate_mounts(config: Config, relaxed: bool = False) -> list[PathString]:
     mounts = []
     root = config.tools() if config.tools_tree_certificates else Path("/")
 
@@ -102,8 +102,4 @@ def finalize_crypto_mounts(config: Config, relaxed: bool = False) -> list[PathSt
             if (root / subdir).exists() and any(p for p in (root / subdir).rglob("*") if not p.is_dir())
         ]
 
-    if not relaxed or config.tools() != Path("/"):
-        if (config.tools() / "etc/crypto-policies").exists():
-            mounts += [(config.tools() / "etc/crypto-policies", Path("/etc/crypto-policies"))]
-
     return flatten(("--ro-bind", src, target) for src, target in sorted(set(mounts), key=lambda s: s[1]))