tool: write systemd-boot loader.conf

To minimize the number of arguments passed to `lzbt`, the loader config
is assembled outside `lzbt` and passed as a single argument.

Instead of reimplementing `consoleMode` under the `lanzaboote`
namespace, `config.loader.systemd-boot.consoleMode` is reused as is.
This commit is contained in:
nikstur 2023-01-27 00:37:05 +01:00
parent 57b56e104c
commit ce3b2c27b5
7 changed files with 62 additions and 1 deletions

View File

@ -7,6 +7,12 @@ let
};
configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit;
timeout = if config.boot.loader.timeout == null then 0 else config.boot.loader.timeout;
systemdBootLoaderConfig = pkgs.writeText "loader.conf" ''
timeout ${toString timeout}
console-mode ${config.boot.loader.systemd-boot.consoleMode}
'';
in
{
options.boot.lanzaboote = {
@ -60,6 +66,7 @@ in
${cfg.package}/bin/lzbt install \
--systemd ${pkgs.systemd} \
--systemd-boot-loader-config ${systemdBootLoaderConfig} \
--public-key ${cfg.publicKeyFile} \
--private-key ${cfg.privateKeyFile} \
--configuration-limit ${toString configurationLimit} \

View File

@ -154,4 +154,21 @@ in
machine.succeed("efibootmgr")
'';
};
systemd-boot-loader-config = mkSecureBootTest {
name = "lanzaboote-systemd-boot-loader-config";
machine = {
boot.loader.timeout = 0;
boot.loader.systemd-boot.consoleMode = "auto";
};
testScript = ''
machine.start()
actual_loader_config = machine.succeed("cat /boot/loader/loader.conf")
expected_loader_config = "timeout 0\nconsole-mode auto\n"
assert actual_loader_config == expected_loader_config, \
f"Actual: '{actual_loader_config}' is not equal to expected: '{expected_loader_config}'"
'';
};
}

View File

@ -23,6 +23,10 @@ struct InstallCommand {
#[arg(long)]
systemd: PathBuf,
/// Systemd-boot loader config
#[arg(long)]
systemd_boot_loader_config: PathBuf,
/// sbsign Public Key
#[arg(long)]
public_key: PathBuf,
@ -65,6 +69,7 @@ fn install(args: InstallCommand) -> Result<()> {
install::Installer::new(
PathBuf::from(lanzaboote_stub),
args.systemd,
args.systemd_boot_loader_config,
key_pair,
args.configuration_limit,
args.esp,

View File

@ -15,6 +15,8 @@ pub struct EspPaths {
pub efi_fallback: PathBuf,
pub systemd: PathBuf,
pub systemd_boot: PathBuf,
pub loader: PathBuf,
pub systemd_boot_loader_config: PathBuf,
}
impl EspPaths {
@ -25,6 +27,8 @@ impl EspPaths {
let efi_linux = efi.join("Linux");
let efi_systemd = efi.join("systemd");
let efi_efi_fallback_dir = efi.join("BOOT");
let loader = esp.join("loader");
let systemd_boot_loader_config = loader.join("loader.conf");
Self {
esp: esp.to_path_buf(),
@ -35,11 +39,13 @@ impl EspPaths {
efi_fallback: efi_efi_fallback_dir.join("BOOTX64.EFI"),
systemd: efi_systemd.clone(),
systemd_boot: efi_systemd.join("systemd-bootx64.efi"),
loader,
systemd_boot_loader_config,
}
}
/// Return the used file paths to store as garbage collection roots.
pub fn to_iter(&self) -> IntoIter<&PathBuf, 8> {
pub fn to_iter(&self) -> IntoIter<&PathBuf, 10> {
[
&self.esp,
&self.efi,
@ -49,6 +55,8 @@ impl EspPaths {
&self.efi_fallback,
&self.systemd,
&self.systemd_boot,
&self.loader,
&self.systemd_boot_loader_config,
]
.into_iter()
}

View File

@ -19,6 +19,7 @@ pub struct Installer {
gc_roots: Roots,
lanzaboote_stub: PathBuf,
systemd: PathBuf,
systemd_boot_loader_config: PathBuf,
key_pair: KeyPair,
configuration_limit: usize,
esp_paths: EspPaths,
@ -29,6 +30,7 @@ impl Installer {
pub fn new(
lanzaboote_stub: PathBuf,
systemd: PathBuf,
systemd_boot_loader_config: PathBuf,
key_pair: KeyPair,
configuration_limit: usize,
esp: PathBuf,
@ -42,6 +44,7 @@ impl Installer {
gc_roots,
lanzaboote_stub,
systemd,
systemd_boot_loader_config,
key_pair,
configuration_limit,
esp_paths,
@ -221,6 +224,18 @@ impl Installer {
.with_context(|| format!("Failed to install systemd-boot binary to: {to:?}"))?;
}
}
install(
&self.systemd_boot_loader_config,
&self.esp_paths.systemd_boot_loader_config,
)
.with_context(|| {
format!(
"Failed to install systemd-boot loader.conf to {:?}",
&self.esp_paths.systemd_boot_loader_config
)
})?;
Ok(())
}
}

View File

@ -107,12 +107,18 @@ pub fn lanzaboote_install(
let test_systemd = systemd_location_from_env()?;
let test_systemd_stub = format!("{test_systemd}/lib/systemd/boot/efi/linuxx64.efi.stub");
let test_loader_config_path = tempfile::NamedTempFile::new()?;
let test_loader_config = r"timeout 0\nconsole-mode 1\n";
fs::write(test_loader_config_path.path(), test_loader_config)?;
let mut cmd = Command::cargo_bin("lzbt")?;
let output = cmd
.env("LANZABOOTE_STUB", test_systemd_stub)
.arg("install")
.arg("--systemd")
.arg(test_systemd)
.arg("--systemd-boot-loader-config")
.arg(test_loader_config_path.path())
.arg("--public-key")
.arg("tests/fixtures/uefi-keys/db.pem")
.arg("--private-key")

View File

@ -61,9 +61,11 @@ fn keep_unrelated_files_on_esp() -> Result<()> {
let output0 = common::lanzaboote_install(0, esp_mountpoint.path(), generation_links.clone())?;
assert!(output0.status.success());
let unrelated_loader_config = esp_mountpoint.path().join("loader/loader.conf");
let unrelated_uki = esp_mountpoint.path().join("EFI/Linux/ubuntu.efi");
let unrelated_os = esp_mountpoint.path().join("EFI/windows");
let unrelated_firmware = esp_mountpoint.path().join("dell");
fs::File::create(&unrelated_loader_config)?;
fs::File::create(&unrelated_uki)?;
fs::create_dir(&unrelated_os)?;
fs::create_dir(&unrelated_firmware)?;
@ -72,6 +74,7 @@ fn keep_unrelated_files_on_esp() -> Result<()> {
let output1 = common::lanzaboote_install(2, esp_mountpoint.path(), generation_links)?;
assert!(output1.status.success());
assert!(unrelated_loader_config.exists());
assert!(unrelated_uki.exists());
assert!(unrelated_os.exists());
assert!(unrelated_firmware.exists());