feature: support initrd secrets

This commit is contained in:
Raito Bezarius 2022-11-26 01:50:51 +01:00
parent a3150dca11
commit 9f65f75289
4 changed files with 51 additions and 23 deletions

View File

@ -226,6 +226,29 @@
assert "Secure Boot: enabled (user)" in machine.succeed("bootctl status")
'';
};
# So, this is the responsibility of the lanzatool install
# to run the append-initrd-secret script
# This test assert that lanzatool still do the right thing
# preDeviceCommands should not have any root filesystem mounted
# so it should not be able to find /etc/iamasecret, other than the
# initrd's one.
# which should exist IF lanzatool do the right thing.
lanzaboote-with-initrd-secrets = mkSecureBootTest {
name = "signed-files-boot-with-secrets-under-secureboot";
machine = { ... }: {
boot.initrd.secrets = {
"/etc/iamasecret" = (pkgs.writeText "iamsecret" "this is a very secure secret");
};
boot.initrd.preDeviceCommands = ''
grep "this is a very secure secret" /etc/iamasecret
'';
};
testScript = ''
machine.start()
assert "Secure Boot: enabled (user)" in machine.succeed("bootctl status")
'';
};
is-initrd-secured = mkUnsignedTest {
name = "unsigned-initrd-do-not-boot-under-secureboot";
path = {

View File

@ -33,6 +33,9 @@ in
};
config = mkIf cfg.enable {
# bootspec is putting at false
# until we fix this upstream, we will mkForce it.
boot.loader.supportsInitrdSecrets = mkForce true;
boot.loader.external = {
enable = true;
passBootspec = true;

View File

@ -12,6 +12,8 @@ use crate::signer::Signer;
use tempfile::tempdir;
use std::process::Command;
pub fn install(
public_key: &Path,
private_key: &Path,
@ -48,15 +50,20 @@ pub fn install(
&kernel_cmdline,
&esp_paths.kernel,
&esp_paths.initrd,
&bootspec_doc.initrd_secrets,
&esp_paths.esp,
)
.context("Failed to assemble stub")?;
println!("Wrapping initrd into a PE binary...");
let initrd_location = secure_temp_dir.path().join("initrd");
copy(&bootspec_doc.initrd, &initrd_location)?;
if let Some(initrd_secrets_script) = bootspec_doc.initrd_secrets {
append_initrd_secrets(&initrd_secrets_script,
&initrd_location)?;
}
let wrapped_initrd =
pe::wrap_initrd(&secure_temp_dir, initrd_stub, &bootspec_doc.initrd).context("Failed to assemble stub")?;
pe::wrap_initrd(&secure_temp_dir, initrd_stub, &initrd_location).context("Failed to assemble stub")?;
println!("Copy files to EFI system partition...");
@ -108,6 +115,20 @@ pub fn install(
Ok(())
}
pub fn append_initrd_secrets(append_initrd_secrets_path: &Path, initrd_path: &PathBuf) -> Result<()> {
let status = Command::new(append_initrd_secrets_path)
.args(vec![
initrd_path
])
.status()
.context("Failed to append initrd secrets")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to append initrd secrets with args `{:?}`", vec![append_initrd_secrets_path, initrd_path]).into());
}
Ok(())
}
fn assemble_kernel_cmdline(init: PathBuf, kernel_params: Vec<String>) -> Vec<String> {
let init_string = init
.into_os_string()

View File

@ -19,7 +19,6 @@ pub fn lanzaboote_image(
kernel_cmdline: &[String],
kernel_path: &Path,
initrd_path: &Path,
append_initrd_secrets_path: &Option<PathBuf>,
esp: &Path,
) -> Result<PathBuf> {
// objcopy copies files into the PE binary. That's why we have to write the contents
@ -28,16 +27,12 @@ pub fn lanzaboote_image(
"kernel-cmdline",
kernel_cmdline.join(" "))?;
let (kernel_path_file, _) = write_to_tmp(&target_dir,
"kernel",
"kernel-esp-path",
esp_relative_path_string(esp, kernel_path))?;
let (initrd_path_file, _) = write_to_tmp(&target_dir,
"initrd",
"initrd-esp-path",
esp_relative_path_string(esp, initrd_path))?;
if let Some(initrd_secret_script) = append_initrd_secrets_path {
append_initrd_secrets(&initrd_secret_script, &initrd_path_file)?;
}
let os_release_offs = stub_offset(lanzaboote_stub)?;
let kernel_cmdline_offs = os_release_offs + file_size(&os_release)?;
let initrd_path_offs = kernel_cmdline_offs + file_size(&kernel_cmdline_file)?;
@ -53,20 +48,6 @@ pub fn lanzaboote_image(
wrap_in_pe(&target_dir, "lanzaboote-stub.efi", &lanzaboote_stub, sections)
}
pub fn append_initrd_secrets(append_initrd_secrets_path: &Path, initrd_path: &PathBuf) -> Result<()> {
let status = Command::new(append_initrd_secrets_path)
.args(vec![
initrd_path
])
.status()
.context("Failed to append initrd secrets")?;
if !status.success() {
return Err(anyhow::anyhow!("Failed to append initrd secrets with args `{:?}`", vec![append_initrd_secrets_path, initrd_path]).into());
}
Ok(())
}
pub fn wrap_initrd(target_dir: &TempDir, initrd_stub: &Path, initrd: &Path) -> Result<PathBuf> {
let initrd_offs = stub_offset(initrd_stub)?;
let sections = vec![s(".initrd", initrd, initrd_offs)];