diff --git a/.github/buildomat/jobs/build-and-test.sh b/.github/buildomat/jobs/build-and-test.sh index 5f101c8..acd6b00 100644 --- a/.github/buildomat/jobs/build-and-test.sh +++ b/.github/buildomat/jobs/build-and-test.sh @@ -12,11 +12,7 @@ set -o xtrace cargo --version rustc --version -# dependencies used by `build.rs` to build test PKI, measurement log, & corpus -cargo install --locked \ - --git https://github.com/oxidecomputer/pki-playground \ - --rev 0c121f9c1e84868e2331173107c2b7ed6f59b13a - +# dependency used by `build.rs` to build measurement log & corpus cargo install --locked \ --git https://github.com/oxidecomputer/dice-util \ --rev 4b408edc1d00f108ddf635415d783e6f12fe9641 \ diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b97036b..d802c5a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -43,11 +43,6 @@ jobs: run: cargo --version - name: Report rustc version run: rustc --version - - name: Install pki-playground - run: | - cargo install --locked \ - --git https://github.com/oxidecomputer/pki-playground \ - --rev 0c121f9c1e84868e2331173107c2b7ed6f59b13a - name: Install attest-mock run: | cargo install --locked \ diff --git a/Cargo.lock b/Cargo.lock index 15f2567..d457f92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1952,6 +1952,7 @@ dependencies = [ "hubpack", "libipcc 0.1.0 (git+https://github.com/oxidecomputer/ipcc-rs?rev=524eb8f125003dff50b9703900c6b323f00f9e1b)", "pem-rfc7468", + "pki-playground", "rustls", "secrecy", "serde", diff --git a/tls/Cargo.toml b/tls/Cargo.toml index 891b660..249950c 100644 --- a/tls/Cargo.toml +++ b/tls/Cargo.toml @@ -32,9 +32,11 @@ zeroize.workspace = true [build-dependencies] anyhow.workspace = true +camino = { workspace = true, optional = true } +pki-playground = { workspace = true, optional = true } [features] -unittest = [] +unittest = ["camino", "pki-playground"] [dev-dependencies] sprockets-tls = { path = ".", features = ["unittest"] } diff --git a/tls/build.rs b/tls/build.rs index 7f72682..4bd3e8f 100644 --- a/tls/build.rs +++ b/tls/build.rs @@ -5,36 +5,16 @@ use anyhow::Result; #[cfg(feature = "unittest")] use anyhow::{anyhow, Context}; +#[cfg(feature = "unittest")] +use camino::Utf8PathBuf; +#[cfg(feature = "unittest")] +use pki_playground::{config, OutputFileExistsBehavior}; /// This path is where Oxide specific libraries live on helios systems. /// This is needed for linking with libipcc #[cfg(target_os = "illumos")] static OXIDE_PLATFORM: &str = "/usr/platform/oxide/lib/amd64/"; -/// Execute one of the `pki-playground` commands to generate part of the PKI -/// used for testing. -#[cfg(feature = "unittest")] -fn pki_gen_cmd(command: &str) -> Result<()> { - let mut cmd = std::process::Command::new("pki-playground"); - cmd.arg(command); - let output = cmd - .output() - .context("executing command \"pki-playground\"")?; - - if !output.status.success() { - let stdout = String::from_utf8(output.stdout) - .context("String from pki-playground stdout")?; - println!("stdout: {stdout}"); - let stderr = String::from_utf8(output.stderr) - .context("String from pki-playground stderr")?; - println!("stderr: {stderr}"); - - return Err(anyhow!("cmd failed: {cmd:?}")); - } - - Ok(()) -} - /// Execute one of the `attest-mock` commands to generate attestation /// artifacts used in testing. #[cfg(feature = "unittest")] @@ -65,15 +45,29 @@ fn main() -> Result<()> { #[cfg(feature = "unittest")] { + // output directory where we put data generated test inputs + let out = Utf8PathBuf::from( + std::env::var("OUT_DIR") + .context("Get OUT_DIR from the environment")?, + ); + + let config_path = "test-keys/config.kdl"; + let doc = + config::load_and_validate(config_path.as_ref()).map_err(|e| { + anyhow!("Loading config from \"{}\" failed: {e:?}", config_path) + })?; + + doc.write_key_pairs(out.clone(), OutputFileExistsBehavior::Skip) + .map_err(|e| anyhow!("writing key pairs failed: {e:?}"))?; + doc.write_certificates(out.clone(), OutputFileExistsBehavior::Skip) + .map_err(|e| anyhow!("writing certificates failed: {e:?}"))?; + doc.write_certificate_lists(out, OutputFileExistsBehavior::Skip) + .map_err(|e| anyhow!("writing cert chains failed: {e:?}"))?; + let start_dir = std::env::current_dir().context("get current dir")?; std::env::set_current_dir("test-keys/") .context("chdir to test keys")?; - // generate keys, certs, and cert chains / lists used by `cargo test` - pki_gen_cmd("generate-key-pairs")?; - pki_gen_cmd("generate-certificates")?; - pki_gen_cmd("generate-certificate-lists")?; - // generate measurement log used by `cargo test` attest_gen_cmd("log", "log.kdl", "log.bin")?; diff --git a/tls/src/client.rs b/tls/src/client.rs index b4885b7..0b64f1d 100644 --- a/tls/src/client.rs +++ b/tls/src/client.rs @@ -449,8 +449,7 @@ mod tests { #[test] // Ensure the test certs can be loaded and verified fn test_client_verifier() { - let mut pki_keydir = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")); - pki_keydir.push("test-keys"); + let pki_keydir = Utf8PathBuf::from(env!("OUT_DIR")); let root = load_root_cert(&pki_keydir.join("test-root-a.cert.pem")).unwrap(); let verifier = RotCertVerifier::new(vec![root], logger()).unwrap(); diff --git a/tls/src/lib.rs b/tls/src/lib.rs index 9a6f5c5..3dcfb73 100644 --- a/tls/src/lib.rs +++ b/tls/src/lib.rs @@ -344,9 +344,13 @@ mod tests { } pub fn pki_keydir() -> Utf8PathBuf { - let mut pki_keydir = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")); - pki_keydir.push("test-keys"); - pki_keydir + Utf8PathBuf::from(env!("OUT_DIR")) + } + + pub fn mock_datadir() -> Utf8PathBuf { + let mut mock_datadir = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")); + mock_datadir.push("test-keys"); + mock_datadir } fn local_config( @@ -364,11 +368,13 @@ mod tests { let resolve_cert_chain = pki_keydir.join(format!("test-sprockets-auth-{n}.certlist.pem")); + let mock_datadir = mock_datadir(); + keys::SprocketsConfig { attest: keys::AttestConfig::Local { priv_key: attest_priv_key, cert_chain: attest_cert_chain, - log: pki_keydir.join("log.bin"), + log: mock_datadir.join("log.bin"), test_corpus: vec![], }, roots: vec![pki_keydir.join("test-root-a.cert.pem")], @@ -470,7 +476,7 @@ mod tests { #[tokio::test] async fn basic() { let log = logger(); - let pki_keydir = pki_keydir(); + let mock_datadir = mock_datadir(); let addr: SocketAddrV6 = SocketAddrV6::from_str("[::1]:46456").unwrap(); let server_config = local_config(1, MeasurementConnectionPolicy::Enforced); @@ -481,8 +487,8 @@ mod tests { let (done_tx, done_rx) = tokio::sync::oneshot::channel(); let log2 = log.clone(); let corpus = vec![ - pki_keydir.join("corim-rot.cbor"), - pki_keydir.join("corim-sp.cbor"), + mock_datadir.join("corim-rot.cbor"), + mock_datadir.join("corim-sp.cbor"), ]; tokio::spawn(async move { @@ -512,8 +518,8 @@ mod tests { local_config(2, MeasurementConnectionPolicy::Enforced); let corpus = vec![ - pki_keydir.join("corim-rot.cbor"), - pki_keydir.join("corim-sp.cbor"), + mock_datadir.join("corim-rot.cbor"), + mock_datadir.join("corim-sp.cbor"), ]; if let Ok(stream) = @@ -539,6 +545,7 @@ mod tests { async fn unattested_client() { let log = logger(); let pki_keydir = pki_keydir(); + let mock_datadir = mock_datadir(); let addr: SocketAddrV6 = SocketAddrV6::from_str("[::1]:46459").unwrap(); let server_config = @@ -550,8 +557,8 @@ mod tests { let (done_tx, done_rx) = tokio::sync::oneshot::channel::<()>(); let log2 = log.clone(); let corpus = vec![ - pki_keydir.join("corim-rot.cbor"), - pki_keydir.join("corim-sp.cbor"), + mock_datadir.join("corim-rot.cbor"), + mock_datadir.join("corim-sp.cbor"), ]; let handle = tokio::spawn(async move { @@ -611,7 +618,7 @@ mod tests { #[tokio::test] async fn spawn_accept() { let log = logger(); - let pki_keydir = pki_keydir(); + let mock_datadir = mock_datadir(); let addr: SocketAddrV6 = SocketAddrV6::from_str("[::1]:46466").unwrap(); @@ -623,8 +630,8 @@ mod tests { let log2 = log.clone(); let corpus = vec![ - pki_keydir.join("corim-rot.cbor"), - pki_keydir.join("corim-sp.cbor"), + mock_datadir.join("corim-rot.cbor"), + mock_datadir.join("corim-sp.cbor"), ]; // Accept connections from `max_connections` clients in different tasks @@ -656,8 +663,8 @@ mod tests { // Spawn `max_connections` tasks to concurrently connect for _ in 0..max_connections { - let pki_keydir = pki_keydir.clone(); let log = log.clone(); + let mock_datadir = mock_datadir.clone(); tokio::spawn(async move { // Loop until we succesfully connect let mut stream = loop { @@ -665,8 +672,8 @@ mod tests { local_config(2, MeasurementConnectionPolicy::Enforced); let corpus = vec![ - pki_keydir.join("corim-rot.cbor"), - pki_keydir.join("corim-sp.cbor"), + mock_datadir.join("corim-rot.cbor"), + mock_datadir.join("corim-sp.cbor"), ]; if let Ok(stream) = Client::connect(