From 9f8f38a222fa58da0b200eddf0578247aeceec6a Mon Sep 17 00:00:00 2001 From: jbtrystram Date: Thu, 2 Apr 2026 09:43:02 +0200 Subject: [PATCH] install: Add a config knob for container sigpolicy Surface the `--enforce-container-sigpolicy` flag as a config file option. Fixes https://github.com/bootc-dev/bootc/issues/2112 Assisted-by: OpenCode.ai Signed-off-by: jbtrystram --- crates/lib/src/install.rs | 50 ++++++++++++++----------- crates/lib/src/install/config.rs | 51 ++++++++++++++++++++++++++ docs/src/man/bootc-install-config.5.md | 6 +++ 3 files changed, 86 insertions(+), 21 deletions(-) diff --git a/crates/lib/src/install.rs b/crates/lib/src/install.rs index 6d0dcc607..4214d1bf9 100644 --- a/crates/lib/src/install.rs +++ b/crates/lib/src/install.rs @@ -1495,7 +1495,7 @@ async fn verify_target_fetch( async fn prepare_install( mut config_opts: InstallConfigOpts, source_opts: InstallSourceOpts, - target_opts: InstallTargetOpts, + mut target_opts: InstallTargetOpts, mut composefs_options: InstallComposefsOpts, target_fs: Option, ) -> Result> { @@ -1543,6 +1543,34 @@ async fn prepare_install( } }; + // Load install configuration from TOML drop-in files early, so that + // config values are available when constructing the target image reference. + let install_config = config::load_config()?; + if let Some(ref config) = install_config { + tracing::debug!("Loaded install configuration"); + // Merge config file values into config_opts (CLI takes precedence) + // Only apply config file value if CLI didn't explicitly set it + if !config_opts.bootupd_skip_boot_uuid { + config_opts.bootupd_skip_boot_uuid = config + .bootupd + .as_ref() + .and_then(|b| b.skip_boot_uuid) + .unwrap_or(false); + } + + if config_opts.bootloader.is_none() { + config_opts.bootloader = config.bootloader.clone(); + } + + if !target_opts.enforce_container_sigpolicy { + target_opts.enforce_container_sigpolicy = config + .enforce_container_sigpolicy + .unwrap_or(false); + } + } else { + tracing::debug!("No install configuration found"); + } + // Parse the target CLI image reference options and create the *target* image // reference, which defaults to pulling from a registry. if target_opts.target_no_signature_verification { @@ -1630,26 +1658,6 @@ async fn prepare_install( println!("Digest: {digest}"); } - let install_config = config::load_config()?; - if let Some(ref config) = install_config { - tracing::debug!("Loaded install configuration"); - // Merge config file values into config_opts (CLI takes precedence) - // Only apply config file value if CLI didn't explicitly set it - if !config_opts.bootupd_skip_boot_uuid { - config_opts.bootupd_skip_boot_uuid = config - .bootupd - .as_ref() - .and_then(|b| b.skip_boot_uuid) - .unwrap_or(false); - } - - if config_opts.bootloader.is_none() { - config_opts.bootloader = config.bootloader.clone(); - } - } else { - tracing::debug!("No install configuration found"); - } - let root_filesystem = target_fs .or(install_config .as_ref() diff --git a/crates/lib/src/install/config.rs b/crates/lib/src/install/config.rs index 07acd2b5e..154f5229c 100644 --- a/crates/lib/src/install/config.rs +++ b/crates/lib/src/install/config.rs @@ -119,6 +119,9 @@ pub(crate) struct InstallConfiguration { pub(crate) bootupd: Option, /// Bootloader to use (grub, systemd, none) pub(crate) bootloader: Option, + /// Enforce that the containers-storage stack has a non-default + /// (i.e. not `insecureAcceptAnything`) container image signature policy. + pub(crate) enforce_container_sigpolicy: Option, } fn merge_basic(s: &mut Option, o: Option, _env: &EnvProperties) { @@ -203,6 +206,11 @@ impl Mergeable for InstallConfiguration { merge_basic(&mut self.boot_mount_spec, other.boot_mount_spec, env); self.bootupd.merge(other.bootupd, env); merge_basic(&mut self.bootloader, other.bootloader, env); + merge_basic( + &mut self.enforce_container_sigpolicy, + other.enforce_container_sigpolicy, + env, + ); if let Some(other_kargs) = other.kargs { self.kargs .get_or_insert_with(Default::default) @@ -876,3 +884,46 @@ bootloader = "grub" install.merge(other, &env); assert_eq!(install.bootloader, Some(Bootloader::None)); } + +#[test] +fn test_parse_enforce_container_sigpolicy() { + let env = EnvProperties { + sys_arch: "x86_64".to_string(), + }; + + // Test parsing true and false + for (input, expected) in [("true", true), ("false", false)] { + let toml_str = format!( + r#"[install] +enforce-container-sigpolicy = {input} +"# + ); + let c: InstallConfigurationToplevel = toml::from_str(&toml_str).unwrap(); + assert_eq!( + c.install.unwrap().enforce_container_sigpolicy.unwrap(), + expected + ); + } + + // Default (not specified) is None + let c: InstallConfigurationToplevel = toml::from_str( + r#"[install] +root-fs-type = "xfs" +"#, + ) + .unwrap(); + assert!(c.install.unwrap().enforce_container_sigpolicy.is_none()); + + // Test merging: last write wins + let mut install: InstallConfiguration = toml::from_str( + r#"enforce-container-sigpolicy = false +"#, + ) + .unwrap(); + let other = InstallConfiguration { + enforce_container_sigpolicy: Some(true), + ..Default::default() + }; + install.merge(other, &env); + assert_eq!(install.enforce_container_sigpolicy.unwrap(), true); +} diff --git a/docs/src/man/bootc-install-config.5.md b/docs/src/man/bootc-install-config.5.md index a6f5156c5..138c0ef67 100644 --- a/docs/src/man/bootc-install-config.5.md +++ b/docs/src/man/bootc-install-config.5.md @@ -33,6 +33,11 @@ The `install` section supports these subfields: - `boot-mount-spec`: A string specifying the /boot filesystem mount specification. If not provided and /boot is a separate mount, its UUID will be used. An empty string signals to omit boot mount kargs entirely. +- `enforce-container-sigpolicy`: A boolean that controls whether to enforce that + `/etc/containers/policy.json` includes a default policy which requires signatures. + When `true`, image pulls will be rejected if the policy file specifies + `insecureAcceptAnything` as the default. Defaults to `false`. + This is equivalent to the `--enforce-container-sigpolicy` CLI flag. # filesystem @@ -73,6 +78,7 @@ kargs = ["nosmt", "console=tty0"] stateroot = "myos" root-mount-spec = "LABEL=rootfs" boot-mount-spec = "UUID=abcd-1234" +enforce-container-sigpolicy = true [install.ostree] bls-append-except-default = 'grub_users=""'