feature: support initrd secrets
This commit is contained in:
parent
a3150dca11
commit
9f65f75289
23
flake.nix
23
flake.nix
|
@ -226,6 +226,29 @@
|
||||||
assert "Secure Boot: enabled (user)" in machine.succeed("bootctl status")
|
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 {
|
is-initrd-secured = mkUnsignedTest {
|
||||||
name = "unsigned-initrd-do-not-boot-under-secureboot";
|
name = "unsigned-initrd-do-not-boot-under-secureboot";
|
||||||
path = {
|
path = {
|
||||||
|
|
|
@ -33,6 +33,9 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
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 = {
|
boot.loader.external = {
|
||||||
enable = true;
|
enable = true;
|
||||||
passBootspec = true;
|
passBootspec = true;
|
||||||
|
|
|
@ -12,6 +12,8 @@ use crate::signer::Signer;
|
||||||
|
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
pub fn install(
|
pub fn install(
|
||||||
public_key: &Path,
|
public_key: &Path,
|
||||||
private_key: &Path,
|
private_key: &Path,
|
||||||
|
@ -48,15 +50,20 @@ pub fn install(
|
||||||
&kernel_cmdline,
|
&kernel_cmdline,
|
||||||
&esp_paths.kernel,
|
&esp_paths.kernel,
|
||||||
&esp_paths.initrd,
|
&esp_paths.initrd,
|
||||||
&bootspec_doc.initrd_secrets,
|
|
||||||
&esp_paths.esp,
|
&esp_paths.esp,
|
||||||
)
|
)
|
||||||
.context("Failed to assemble stub")?;
|
.context("Failed to assemble stub")?;
|
||||||
|
|
||||||
println!("Wrapping initrd into a PE binary...");
|
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 =
|
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...");
|
println!("Copy files to EFI system partition...");
|
||||||
|
|
||||||
|
@ -108,6 +115,20 @@ pub fn install(
|
||||||
Ok(())
|
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> {
|
fn assemble_kernel_cmdline(init: PathBuf, kernel_params: Vec<String>) -> Vec<String> {
|
||||||
let init_string = init
|
let init_string = init
|
||||||
.into_os_string()
|
.into_os_string()
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub fn lanzaboote_image(
|
||||||
kernel_cmdline: &[String],
|
kernel_cmdline: &[String],
|
||||||
kernel_path: &Path,
|
kernel_path: &Path,
|
||||||
initrd_path: &Path,
|
initrd_path: &Path,
|
||||||
append_initrd_secrets_path: &Option<PathBuf>,
|
|
||||||
esp: &Path,
|
esp: &Path,
|
||||||
) -> Result<PathBuf> {
|
) -> Result<PathBuf> {
|
||||||
// objcopy copies files into the PE binary. That's why we have to write the contents
|
// 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",
|
||||||
kernel_cmdline.join(" "))?;
|
kernel_cmdline.join(" "))?;
|
||||||
let (kernel_path_file, _) = write_to_tmp(&target_dir,
|
let (kernel_path_file, _) = write_to_tmp(&target_dir,
|
||||||
"kernel",
|
"kernel-esp-path",
|
||||||
esp_relative_path_string(esp, kernel_path))?;
|
esp_relative_path_string(esp, kernel_path))?;
|
||||||
let (initrd_path_file, _) = write_to_tmp(&target_dir,
|
let (initrd_path_file, _) = write_to_tmp(&target_dir,
|
||||||
"initrd",
|
"initrd-esp-path",
|
||||||
esp_relative_path_string(esp, initrd_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 os_release_offs = stub_offset(lanzaboote_stub)?;
|
||||||
let kernel_cmdline_offs = os_release_offs + file_size(&os_release)?;
|
let kernel_cmdline_offs = os_release_offs + file_size(&os_release)?;
|
||||||
let initrd_path_offs = kernel_cmdline_offs + file_size(&kernel_cmdline_file)?;
|
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)
|
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> {
|
pub fn wrap_initrd(target_dir: &TempDir, initrd_stub: &Path, initrd: &Path) -> Result<PathBuf> {
|
||||||
let initrd_offs = stub_offset(initrd_stub)?;
|
let initrd_offs = stub_offset(initrd_stub)?;
|
||||||
let sections = vec![s(".initrd", initrd, initrd_offs)];
|
let sections = vec![s(".initrd", initrd, initrd_offs)];
|
||||||
|
|
Loading…
Reference in New Issue