From: Daan De Meyer Date: Tue, 21 Jan 2025 21:21:38 +0000 (+0100) Subject: Rework crypto-policies again X-Git-Tag: v25~12^2~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=881800df74ddf19853796596e59bef84b7bde387;p=thirdparty%2Fmkosi.git Rework crypto-policies again 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. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index 3a13440c0..31f5b10a8 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -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 diff --git a/mkosi/curl.py b/mkosi/curl.py index 8d39acc97..eb8caadea 100644 --- a/mkosi/curl.py +++ b/mkosi/curl.py @@ -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 diff --git a/mkosi/distributions/opensuse.py b/mkosi/distributions/opensuse.py index 6b07ef530..9df535ddd 100644 --- a/mkosi/distributions/opensuse.py +++ b/mkosi/distributions/opensuse.py @@ -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 diff --git a/mkosi/installer/__init__.py b/mkosi/installer/__init__.py index 18352c6c3..50c659f84 100644 --- a/mkosi/installer/__init__.py +++ b/mkosi/installer/__init__.py @@ -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 diff --git a/mkosi/installer/rpm.py b/mkosi/installer/rpm.py index a0bc60321..d3f614af4 100644 --- a/mkosi/installer/rpm.py +++ b/mkosi/installer/rpm.py @@ -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]: diff --git a/mkosi/mounts.py b/mkosi/mounts.py index 78ab8fc62..31eb9c7de 100644 --- a/mkosi/mounts.py +++ b/mkosi/mounts.py @@ -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]))