From 0d1980f2d6e923262ee64b360bca34899c805596 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 8 Nov 2021 10:54:40 -0500 Subject: feat(xanthous/server): Load host secret key from disk Rather than randomly generating a new host key every time we run the server, load the host's secret key from a file on disk at startup, so that clients don't have to disable host key verification to connect every time we restart. Change-Id: I4d283bc919f4825789f686a98c174a71929087a6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3819 Tested-by: BuildkiteCI Reviewed-by: grfn --- users/grfn/xanthous/server/module.nix | 6 ++++++ users/grfn/xanthous/server/src/main.rs | 28 +++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'users') diff --git a/users/grfn/xanthous/server/module.nix b/users/grfn/xanthous/server/module.nix index 11adda955d..cbc10c014d 100644 --- a/users/grfn/xanthous/server/module.nix +++ b/users/grfn/xanthous/server/module.nix @@ -24,6 +24,11 @@ in { default = depot.users.grfn.xanthous.server.docker; description = "OCI image file to run"; }; + + ed25519SecretKeyFile = mkOption { + type = with types; uniq string; + description = "Path to the ed25519 secret key for the server"; + }; }; }; @@ -36,6 +41,7 @@ in { "${toString cfg.port}:22" "${toString cfg.metricsPort}:9000" ]; + environment.SECRET_KEY_FILE = "/etc/secrets/xanthous-server-secret-key"; }; }; } diff --git a/users/grfn/xanthous/server/src/main.rs b/users/grfn/xanthous/server/src/main.rs index 4476fe48a6..9bb31bd9b8 100644 --- a/users/grfn/xanthous/server/src/main.rs +++ b/users/grfn/xanthous/server/src/main.rs @@ -1,11 +1,12 @@ use std::net::SocketAddr; +use std::path::PathBuf; use std::pin::Pin; use std::process::Command; use std::sync::Arc; use clap::Parser; use color_eyre::eyre::Result; -use eyre::{bail, eyre}; +use eyre::{bail, Context}; use futures::future::{ready, Ready}; use futures::Future; use metrics_exporter_prometheus::PrometheusBuilder; @@ -16,6 +17,9 @@ use thrussh::{ server::{self, Auth, Session}, CryptoVec, }; +use thrussh_keys::decode_openssh; +use thrussh_keys::key::KeyPair; +use tokio::fs::File; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpListener; use tokio::select; @@ -55,17 +59,31 @@ struct Opts { #[clap(long, env = "XANTHOUS_BINARY_PATH")] xanthous_binary_path: String, + /// Path to a file containing the ed25519 secret key for the server + #[clap(long, env = "SECRET_KEY_FILE")] + secret_key_file: PathBuf, + /// Level to log at #[clap(long, env = "LOG_LEVEL", default_value = "info")] log_level: String, } impl Opts { - fn ssh_server_config(&self) -> Result { + async fn read_secret_key(&self) -> Result { + let mut file = File::open(&self.secret_key_file) + .await + .context("Reading secret key file")?; + let mut secret_key = Vec::with_capacity(464); + file.read_to_end(&mut secret_key).await?; + Ok(decode_openssh(&secret_key, None)?) + } + + async fn ssh_server_config(&self) -> Result { + let key_pair = self.read_secret_key().await?; + Ok(server::Config { server_id: "SSH-2.0-xanthous".to_owned(), - keys: vec![thrussh_keys::key::KeyPair::generate_ed25519() - .ok_or_else(|| eyre!("Could not generate ed25519 key"))?], + keys: vec![key_pair], ..Default::default() }) } @@ -301,7 +319,7 @@ async fn main() -> Result<()> { .install()?; metrics::register(); - let config = Arc::new(opts.ssh_server_config()?); + let config = Arc::new(opts.ssh_server_config().await?); info!(address = %opts.address, "Listening for new SSH connections"); let listener = TcpListener::bind(&opts.address).await?; -- cgit 1.4.1