diff --git a/.gitignore b/.gitignore index 838ce3a..8160ef9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target -.data/*.log -*.pem* \ No newline at end of file +.data/*.log \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5c40cc1..eb7f33f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3443,6 +3443,7 @@ dependencies = [ "serde", "serde_json", "signal-hook", + "ssh-key", "strip-ansi-escapes", "strum", "tokio", diff --git a/Cargo.toml b/Cargo.toml index d86cc43..6a6e09d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,4 +45,5 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter", "serde"] } [build-dependencies] anyhow = "1.0.90" +ssh-key = { version = "0.6.7", features = ["getrandom", "crypto"] } vergen-gix = { version = "1.0.2", features = ["build", "cargo"] } diff --git a/build.rs b/build.rs index 2461afa..8e9cf1b 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,44 @@ +use std::{env, path::PathBuf}; + use anyhow::Result; +use ssh_key::{rand_core, Algorithm, EcdsaCurve, LineEnding, PrivateKey}; use vergen_gix::{BuildBuilder, CargoBuilder, Emitter, GixBuilder}; +const SSH_KEY_ALGOS: &[Algorithm] = &[ + Algorithm::Rsa { hash: None }, + Algorithm::Ed25519, + Algorithm::Ecdsa { + curve: EcdsaCurve::NistP256, + }, +]; + fn main() -> Result<()> { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=Cargo.toml"); + + // Generate openSSH host keys + let mut rng = rand_core::OsRng::default(); + let keys = SSH_KEY_ALGOS + .iter() + .map(|algo| PrivateKey::random(&mut rng, algo.to_owned()).map_err(anyhow::Error::from)) + .collect::>>(); + + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + for key_res in keys { + if let Ok(ref key) = key_res { + let path = out_dir.join(format!("{}.pem", key.algorithm().as_str())); + if path.exists() { + println!("cargo:warning=Skipping existing host key: {:?}", path); + continue; + } + + key.write_openssh_file(&path, LineEnding::default())?; + } else { + println!("cargo:warning=Failed to generate host key: {:?}", key_res); + } + } + + // Emit the build information let build = BuildBuilder::all_build()?; let gix = GixBuilder::all_git()?; let cargo = CargoBuilder::all_cargo()?; diff --git a/src/main.rs b/src/main.rs index 348832b..42c81fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,8 +24,9 @@ mod ssh; mod tui; const SSH_KEYS: &[&[u8]] = &[ - include_bytes!("../rsa.pem"), - include_bytes!("../ed25519.pem"), + include_bytes!(concat!(env!("OUT_DIR"), "/ssh-rsa.pem")), + include_bytes!(concat!(env!("OUT_DIR"), "/ecdsa-sha2-nistp256.pem")), + include_bytes!(concat!(env!("OUT_DIR"), "/ssh-ed25519.pem")), ]; lazy_static! { pub(crate) static ref OPTIONS: Cli = Cli::parse(); @@ -36,6 +37,7 @@ lazy_static! { async fn main() -> Result<()> { crate::errors::init()?; crate::logging::init()?; + let _ = *OPTIONS; // force clap to run by evaluating it let config = ssh_config(); tracing::info!("Attempting to listen on {}", *SOCKET_ADDR);