mirror of
https://github.com/containers/bootc.git
synced 2026-02-05 15:45:53 +01:00
sdboot: add support for key enrollment in bootc install
systemd-boot has support for automatically enrolling keys for Secure Boot, this adds support for copying these keys as embedded in the input container image into the location where systemd-boot can perform automatic enrollment on them. Commit-message-written-by: Colin Walters <walters@verbum.org> Signed-off-by: Gareth Widlansky <gareth.widlansky@proton.me>
This commit is contained in:
committed by
Colin Walters
parent
3efcbddeb3
commit
439deff2f7
@@ -66,7 +66,7 @@ use std::fs::create_dir_all;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use bootc_blockdev::find_parent_devices;
|
||||
use bootc_kernel_cmdline::utf8::{Cmdline, Parameter};
|
||||
use bootc_mount::inspect_filesystem_of_dir;
|
||||
@@ -137,6 +137,10 @@ const SYSTEMD_LOADER_CONF_PATH: &str = "loader/loader.conf";
|
||||
const INITRD: &str = "initrd";
|
||||
const VMLINUZ: &str = "vmlinuz";
|
||||
|
||||
const BOOTC_AUTOENROLL_PATH: &str = "usr/lib/bootc/install/secureboot-keys";
|
||||
|
||||
const AUTH_EXT: &str = "auth";
|
||||
|
||||
/// We want to be able to control the ordering of UKIs so we put them in a directory that's not the
|
||||
/// directory specified by the BLS spec. We do this because we want systemd-boot to only look at
|
||||
/// our config files and not show the actual UKIs in the bootloader menu
|
||||
@@ -1146,6 +1150,52 @@ pub(crate) fn setup_composefs_uki_boot(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct SecurebootKeys {
|
||||
pub dir: Dir,
|
||||
pub keys: Vec<Utf8PathBuf>,
|
||||
}
|
||||
|
||||
fn get_secureboot_keys(fs: &Dir, p: &str) -> Result<Option<SecurebootKeys>> {
|
||||
let mut entries = vec![];
|
||||
|
||||
// if the dir doesn't exist, return None
|
||||
let keys_dir = match fs.open_dir_optional(p)? {
|
||||
Some(d) => d,
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
||||
// https://github.com/systemd/systemd/blob/26b2085d54ebbfca8637362eafcb4a8e3faf832f/man/systemd-boot.xml#L392
|
||||
|
||||
for entry in keys_dir.entries()? {
|
||||
let dir_e = entry?;
|
||||
let dirname = dir_e.file_name();
|
||||
if !dir_e.file_type()?.is_dir() {
|
||||
bail!("/{p}/{dirname:?} is not a directory");
|
||||
}
|
||||
|
||||
let dir_path: Utf8PathBuf = dirname.try_into()?;
|
||||
let dir = dir_e.open_dir()?;
|
||||
for entry in dir.entries()? {
|
||||
let e = entry?;
|
||||
let local: Utf8PathBuf = e.file_name().try_into()?;
|
||||
let path = dir_path.join(local);
|
||||
|
||||
if path.extension() != Some(AUTH_EXT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !e.file_type()?.is_file() {
|
||||
bail!("/{p}/{path:?} is not a file");
|
||||
}
|
||||
entries.push(path);
|
||||
}
|
||||
}
|
||||
return Ok(Some(SecurebootKeys {
|
||||
dir: keys_dir,
|
||||
keys: entries,
|
||||
}));
|
||||
}
|
||||
|
||||
#[context("Setting up composefs boot")]
|
||||
pub(crate) async fn setup_composefs_boot(
|
||||
root_setup: &RootSetup,
|
||||
@@ -1185,6 +1235,7 @@ pub(crate) async fn setup_composefs_boot(
|
||||
&root_setup.physical_root_path,
|
||||
&state.config_opts,
|
||||
None,
|
||||
get_secureboot_keys(&mounted_fs, BOOTC_AUTOENROLL_PATH)?,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::fs::create_dir_all;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
@@ -9,7 +10,7 @@ use fn_error_context::context;
|
||||
use bootc_blockdev::{Partition, PartitionTable};
|
||||
use bootc_mount as mount;
|
||||
|
||||
use crate::bootc_composefs::boot::mount_esp;
|
||||
use crate::bootc_composefs::boot::{mount_esp, SecurebootKeys};
|
||||
use crate::{discoverable_partition_specification, utils};
|
||||
|
||||
/// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel)
|
||||
@@ -19,6 +20,9 @@ pub(crate) const EFI_DIR: &str = "efi";
|
||||
#[allow(dead_code)]
|
||||
const BOOTUPD_UPDATES: &str = "usr/lib/bootupd/updates";
|
||||
|
||||
// from: https://github.com/systemd/systemd/blob/26b2085d54ebbfca8637362eafcb4a8e3faf832f/man/systemd-boot.xml#L392
|
||||
const SYSTEMD_KEY_DIR: &str = "loader/keys";
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn esp_in(device: &PartitionTable) -> Result<&Partition> {
|
||||
device
|
||||
@@ -74,6 +78,7 @@ pub(crate) fn install_systemd_boot(
|
||||
_rootfs: &Utf8Path,
|
||||
_configopts: &crate::install::InstallConfigOpts,
|
||||
_deployment_path: Option<&str>,
|
||||
autoenroll: Option<SecurebootKeys>,
|
||||
) -> Result<()> {
|
||||
let esp_part = device
|
||||
.find_partition_of_type(discoverable_partition_specification::ESP)
|
||||
@@ -87,7 +92,35 @@ pub(crate) fn install_systemd_boot(
|
||||
Command::new("bootctl")
|
||||
.args(["install", "--esp-path", esp_path.as_str()])
|
||||
.log_debug()
|
||||
.run_inherited_with_cmd_context()
|
||||
.run_inherited_with_cmd_context()?;
|
||||
|
||||
if let Some(SecurebootKeys { dir, keys }) = autoenroll {
|
||||
let path = esp_path.join(SYSTEMD_KEY_DIR);
|
||||
create_dir_all(&path)?;
|
||||
|
||||
let keys_dir = esp_mount
|
||||
.fd
|
||||
.open_dir(SYSTEMD_KEY_DIR)
|
||||
.with_context(|| format!("Opening {path}"))?;
|
||||
|
||||
for filename in keys.iter() {
|
||||
let p = path.join(&filename);
|
||||
|
||||
// create directory if it doesn't already exist
|
||||
if let Some(parent) = p.parent() {
|
||||
create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
dir.copy(&filename, &keys_dir, &filename)
|
||||
.with_context(|| format!("Copying secure boot key: {p}"))?;
|
||||
println!("Wrote Secure Boot key: {p}");
|
||||
}
|
||||
if keys.is_empty() {
|
||||
tracing::debug!("No Secure Boot keys provided for systemd-boot enrollment");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[context("Installing bootloader using zipl")]
|
||||
|
||||
@@ -28,6 +28,10 @@ updates.
|
||||
An installation is not simply a copy of the container filesystem, but
|
||||
includes other setup and metadata.
|
||||
|
||||
## Secure Boot Keys
|
||||
|
||||
When installing with `systemd-boot`, bootc can let `systemd-boot` can handle enrollment of Secure Boot keys by putting signed EFI signature lists in `/usr/lib/bootc/install/secureboot-keys` which will copy over into `ESP/loader/keys` after bootloader installation. The keys will be copied to `loader/keys` subdirectory of the ESP. after installing `systemd-boot` to the system. More information on how key enrollment works with `systemd-boot` is available in the [systemd-boot](https://github.com/systemd/systemd/blob/26b2085d54ebbfca8637362eafcb4a8e3faf832f/man/systemd-boot.xml#L392) man page.
|
||||
|
||||
<!-- BEGIN GENERATED OPTIONS -->
|
||||
<!-- END GENERATED OPTIONS -->
|
||||
|
||||
|
||||
Reference in New Issue
Block a user