Skip to content

Commit 9f8f38a

Browse files
committed
install: Add a config knob for container sigpolicy
Surface the `--enforce-container-sigpolicy` flag as a config file option. Fixes #2112 Assisted-by: OpenCode.ai <Opus 4.6> Signed-off-by: jbtrystram <jbtrystram@redhat.com>
1 parent ce44df9 commit 9f8f38a

File tree

3 files changed

+86
-21
lines changed

3 files changed

+86
-21
lines changed

crates/lib/src/install.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,7 +1495,7 @@ async fn verify_target_fetch(
14951495
async fn prepare_install(
14961496
mut config_opts: InstallConfigOpts,
14971497
source_opts: InstallSourceOpts,
1498-
target_opts: InstallTargetOpts,
1498+
mut target_opts: InstallTargetOpts,
14991499
mut composefs_options: InstallComposefsOpts,
15001500
target_fs: Option<FilesystemEnum>,
15011501
) -> Result<Arc<State>> {
@@ -1543,6 +1543,34 @@ async fn prepare_install(
15431543
}
15441544
};
15451545

1546+
// Load install configuration from TOML drop-in files early, so that
1547+
// config values are available when constructing the target image reference.
1548+
let install_config = config::load_config()?;
1549+
if let Some(ref config) = install_config {
1550+
tracing::debug!("Loaded install configuration");
1551+
// Merge config file values into config_opts (CLI takes precedence)
1552+
// Only apply config file value if CLI didn't explicitly set it
1553+
if !config_opts.bootupd_skip_boot_uuid {
1554+
config_opts.bootupd_skip_boot_uuid = config
1555+
.bootupd
1556+
.as_ref()
1557+
.and_then(|b| b.skip_boot_uuid)
1558+
.unwrap_or(false);
1559+
}
1560+
1561+
if config_opts.bootloader.is_none() {
1562+
config_opts.bootloader = config.bootloader.clone();
1563+
}
1564+
1565+
if !target_opts.enforce_container_sigpolicy {
1566+
target_opts.enforce_container_sigpolicy = config
1567+
.enforce_container_sigpolicy
1568+
.unwrap_or(false);
1569+
}
1570+
} else {
1571+
tracing::debug!("No install configuration found");
1572+
}
1573+
15461574
// Parse the target CLI image reference options and create the *target* image
15471575
// reference, which defaults to pulling from a registry.
15481576
if target_opts.target_no_signature_verification {
@@ -1630,26 +1658,6 @@ async fn prepare_install(
16301658
println!("Digest: {digest}");
16311659
}
16321660

1633-
let install_config = config::load_config()?;
1634-
if let Some(ref config) = install_config {
1635-
tracing::debug!("Loaded install configuration");
1636-
// Merge config file values into config_opts (CLI takes precedence)
1637-
// Only apply config file value if CLI didn't explicitly set it
1638-
if !config_opts.bootupd_skip_boot_uuid {
1639-
config_opts.bootupd_skip_boot_uuid = config
1640-
.bootupd
1641-
.as_ref()
1642-
.and_then(|b| b.skip_boot_uuid)
1643-
.unwrap_or(false);
1644-
}
1645-
1646-
if config_opts.bootloader.is_none() {
1647-
config_opts.bootloader = config.bootloader.clone();
1648-
}
1649-
} else {
1650-
tracing::debug!("No install configuration found");
1651-
}
1652-
16531661
let root_filesystem = target_fs
16541662
.or(install_config
16551663
.as_ref()

crates/lib/src/install/config.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ pub(crate) struct InstallConfiguration {
119119
pub(crate) bootupd: Option<Bootupd>,
120120
/// Bootloader to use (grub, systemd, none)
121121
pub(crate) bootloader: Option<Bootloader>,
122+
/// Enforce that the containers-storage stack has a non-default
123+
/// (i.e. not `insecureAcceptAnything`) container image signature policy.
124+
pub(crate) enforce_container_sigpolicy: Option<bool>,
122125
}
123126

124127
fn merge_basic<T>(s: &mut Option<T>, o: Option<T>, _env: &EnvProperties) {
@@ -203,6 +206,11 @@ impl Mergeable for InstallConfiguration {
203206
merge_basic(&mut self.boot_mount_spec, other.boot_mount_spec, env);
204207
self.bootupd.merge(other.bootupd, env);
205208
merge_basic(&mut self.bootloader, other.bootloader, env);
209+
merge_basic(
210+
&mut self.enforce_container_sigpolicy,
211+
other.enforce_container_sigpolicy,
212+
env,
213+
);
206214
if let Some(other_kargs) = other.kargs {
207215
self.kargs
208216
.get_or_insert_with(Default::default)
@@ -876,3 +884,46 @@ bootloader = "grub"
876884
install.merge(other, &env);
877885
assert_eq!(install.bootloader, Some(Bootloader::None));
878886
}
887+
888+
#[test]
889+
fn test_parse_enforce_container_sigpolicy() {
890+
let env = EnvProperties {
891+
sys_arch: "x86_64".to_string(),
892+
};
893+
894+
// Test parsing true and false
895+
for (input, expected) in [("true", true), ("false", false)] {
896+
let toml_str = format!(
897+
r#"[install]
898+
enforce-container-sigpolicy = {input}
899+
"#
900+
);
901+
let c: InstallConfigurationToplevel = toml::from_str(&toml_str).unwrap();
902+
assert_eq!(
903+
c.install.unwrap().enforce_container_sigpolicy.unwrap(),
904+
expected
905+
);
906+
}
907+
908+
// Default (not specified) is None
909+
let c: InstallConfigurationToplevel = toml::from_str(
910+
r#"[install]
911+
root-fs-type = "xfs"
912+
"#,
913+
)
914+
.unwrap();
915+
assert!(c.install.unwrap().enforce_container_sigpolicy.is_none());
916+
917+
// Test merging: last write wins
918+
let mut install: InstallConfiguration = toml::from_str(
919+
r#"enforce-container-sigpolicy = false
920+
"#,
921+
)
922+
.unwrap();
923+
let other = InstallConfiguration {
924+
enforce_container_sigpolicy: Some(true),
925+
..Default::default()
926+
};
927+
install.merge(other, &env);
928+
assert_eq!(install.enforce_container_sigpolicy.unwrap(), true);
929+
}

docs/src/man/bootc-install-config.5.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ The `install` section supports these subfields:
3333
- `boot-mount-spec`: A string specifying the /boot filesystem mount specification.
3434
If not provided and /boot is a separate mount, its UUID will be used.
3535
An empty string signals to omit boot mount kargs entirely.
36+
- `enforce-container-sigpolicy`: A boolean that controls whether to enforce that
37+
`/etc/containers/policy.json` includes a default policy which requires signatures.
38+
When `true`, image pulls will be rejected if the policy file specifies
39+
`insecureAcceptAnything` as the default. Defaults to `false`.
40+
This is equivalent to the `--enforce-container-sigpolicy` CLI flag.
3641

3742
# filesystem
3843

@@ -73,6 +78,7 @@ kargs = ["nosmt", "console=tty0"]
7378
stateroot = "myos"
7479
root-mount-spec = "LABEL=rootfs"
7580
boot-mount-spec = "UUID=abcd-1234"
81+
enforce-container-sigpolicy = true
7682

7783
[install.ostree]
7884
bls-append-except-default = 'grub_users=""'

0 commit comments

Comments
 (0)