Skip to content

Commit 8d18d19

Browse files
committed
wip! wip! tool(signd): add integration testing
personal todo: - returns stub parameters in the toplevel setup - verify paths for local keypair - build and sign a stub, verify it using the API, verify it locally (?) - build a stub, sign a "store path" (actually a temporary location on the same system), verify it using the API - sign a random file, verify it using the API
1 parent a8ca76f commit 8d18d19

File tree

4 files changed

+112
-121
lines changed

4 files changed

+112
-121
lines changed

rust/signd/Cargo.lock

+2-121
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/signd/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ rouille = "3.6.2"
1818
serde = { version = "1.0.163", features = ["derive"] }
1919
serde_json = "1.0.107"
2020
thiserror = "1.0.49"
21+
22+
[dev-dependencies]
23+
ureq = "2.9.1"

rust/signd/tests/basic_integration.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use lanzaboote_tool::pe::StubParameters;
2+
3+
mod common;
4+
5+
#[test]
6+
fn test_sign_and_verify() {
7+
let (server, remote_signer) = common::setup();
8+
let stub_parameters = common::setup_toplevel(tmpdir());
9+
remote_signer.build_and_sign_stub(stub_parameters);
10+
}

rust/signd/tests/common/mod.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use std::{fs, path::Path};
2+
3+
use lanzaboote_signd::{handlers::Handlers, policy::Policy, route};
4+
use lanzaboote_tool::{
5+
architecture::Architecture,
6+
pe::StubParameters,
7+
signature::{local::LocalKeyPair, remote::RemoteSigningServer},
8+
};
9+
use rouille::{Request, Response};
10+
11+
/// Returns the host platform system
12+
/// in the system double format for
13+
/// our usual targets.
14+
#[cfg(target_arch = "aarch64")]
15+
pub static SYSTEM: &str = "aarch64-linux";
16+
17+
// We do not actually care much about 32 bit. However we can use this to easily test that lzbt
18+
// works with another architecture.
19+
#[cfg(target_arch = "x86")]
20+
pub static SYSTEM: &str = "i686-linux";
21+
22+
#[cfg(target_arch = "x86_64")]
23+
pub static SYSTEM: &str = "x86_64-linux";
24+
25+
/// An policy that should never ever be used in production.
26+
pub struct AbsolutelyInsecurePolicy;
27+
28+
impl Policy for AbsolutelyInsecurePolicy {
29+
fn trusted_store_path(&self, store_path: &std::path::Path) -> bool {
30+
true
31+
}
32+
33+
fn trusted_stub_parameters(&self, parameters: &lanzaboote_tool::pe::StubParameters) -> bool {
34+
true
35+
}
36+
}
37+
38+
pub fn setup_keypair() -> LocalKeyPair {
39+
LocalKeyPair::new(
40+
Path::new("../../tool/tests/fixtures/uefi-keys/db.pem"),
41+
Path::new("../../tool/tests/fixtures/uefi-keys/db.key"),
42+
)
43+
}
44+
45+
pub fn setup() -> (
46+
rouille::Server<impl Fn(&Request) -> Response>,
47+
RemoteSigningServer,
48+
) {
49+
let keypair = setup_keypair();
50+
51+
let handlers = Handlers::new(keypair, AbsolutelyInsecurePolicy);
52+
let server = rouille::Server::new("localhost:0", route(handlers))
53+
.expect("Failed to start the HTTP server");
54+
let server_url = format!("http://localhost:{}", server.server_addr().port());
55+
let remote_signer = RemoteSigningServer::new(&server_url, "rustc/integration testing")
56+
.expect("Failed to build the remote signer");
57+
58+
(server, remote_signer)
59+
}
60+
61+
/// Stolen from `tool` setup.
62+
/// Setup a mock toplevel inside a temporary directory.
63+
///
64+
/// Accepts the temporary directory as a parameter so that the invoking function retains control of
65+
/// it (and when it goes out of scope).
66+
pub fn setup_toplevel(tmpdir: &Path) -> std::io::Result<StubParameters> {
67+
let system = Architecture::from_nixos_system(SYSTEM)?;
68+
69+
// Generate a random toplevel name so that multiple toplevel paths can live alongside each
70+
// other in the same directory.
71+
let toplevel = tmpdir.join(format!("toplevel-{}", random_string(8)));
72+
let fake_store_path = toplevel.join("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-6.1.1");
73+
fs::create_dir_all(&fake_store_path)?;
74+
75+
let test_systemd = systemd_location_from_env()?;
76+
let systemd_stub_filename = system.systemd_stub_filename();
77+
let test_systemd_stub = format!(
78+
"{test_systemd}/lib/systemd/boot/efi/{systemd_stub_filename}",
79+
systemd_stub_filename = systemd_stub_filename.display()
80+
);
81+
82+
let initrd_path = fake_store_path.join("initrd");
83+
let kernel_path = fake_store_path.join("kernel");
84+
let nixos_version_path = toplevel.join("nixos-version");
85+
let kernel_modules_path = toplevel.join("kernel-modules/lib/modules/6.1.1");
86+
87+
// To simplify the test setup, we use the systemd stub for all PE binaries used by lanzatool.
88+
// Lanzatool doesn't care whether its actually a kernel or initrd but only whether it can
89+
// manipulate the PE binary with objcopy and/or sign it with sbsigntool. For testing lanzatool
90+
// in isolation this should suffice.
91+
fs::copy(&test_systemd_stub, initrd_path)?;
92+
fs::copy(&test_systemd_stub, kernel_path)?;
93+
fs::write(nixos_version_path, b"23.05")?;
94+
fs::create_dir_all(kernel_modules_path)?;
95+
96+
Ok(toplevel)
97+
}

0 commit comments

Comments
 (0)