use std::error::Error; use std::io::prelude::*; use std::path::Path; use std::sync::Once; use rand_core::OsRng; use ssh_key::{Algorithm, Fingerprint, PrivateKey, PublicKey}; use tempfile::NamedTempFile; use tracing_subscriber::EnvFilter; use sshca::config::{Configuration, OidcConfig}; static INIT: Once = Once::new(); fn gen_machine_ids() -> Result> { let f = NamedTempFile::new()?; let map = serde_json::json!({ "test.example.org": "b75e9126-d73a-4ae0-9a0d-63cb3552e6cd", }); serde_json::to_writer(&f, &map)?; Ok(f) } fn gen_config(machine_ids: &Path, host_key: &Path) -> Configuration { let mut config = Configuration { machine_ids: machine_ids.to_str().unwrap().into(), oidc: Some(OidcConfig { discovery_url: "https://auth.example.org".into(), client_id: "sshca".into(), client_secret: None, }), ..Default::default() }; config.ca.host.private_key_file = host_key.to_str().unwrap().into(); config } fn gen_ca_key() -> Result<(NamedTempFile, PublicKey), Box> { let key = PrivateKey::random(&mut OsRng, Algorithm::Ed25519)?; let mut f = NamedTempFile::new()?; f.write_all(key.to_openssh(Default::default())?.as_bytes())?; Ok((f, key.public_key().clone())) } pub async fn setup() -> Result<(TestContext, Configuration), Box> { INIT.call_once(|| { tracing_subscriber::fmt::fmt() .with_env_filter(EnvFilter::from("sshca=trace")) .with_test_writer() .init(); }); let machine_ids = gen_machine_ids()?; let (host_key, host_key_pub) = gen_ca_key()?; let config = gen_config(machine_ids.path(), host_key.path()); let ctx = TestContext { machine_ids, host_key, host_key_pub, }; Ok((ctx, config)) } #[allow(dead_code)] pub struct TestContext { machine_ids: NamedTempFile, host_key: NamedTempFile, host_key_pub: PublicKey, } impl TestContext { pub fn host_ca_fingerprint(&self) -> Fingerprint { self.host_key_pub.fingerprint(Default::default()) } }