Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-03-17 17:38:59 -04:00
parent 7f22f0e3a6
commit 2fad03597a
3 changed files with 96 additions and 10 deletions

View file

@ -2,7 +2,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::Parser; use clap::{Parser, Subcommand};
/// Commandline arguments /// Commandline arguments
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -11,6 +11,43 @@ pub struct Args {
#[arg(short, long)] #[arg(short, long)]
/// Optional argument to the path of a conduwuit config TOML file /// Optional argument to the path of a conduwuit config TOML file
pub config: Option<PathBuf>, pub config: Option<PathBuf>,
#[clap(subcommand)]
/// Optional subcommand to export the homeserver signing key and exit
pub signing_key: Option<SigningKey>,
}
#[derive(Debug, Subcommand)]
pub enum SigningKey {
/// Filesystem path to export the homeserver signing key to.
/// The output will be: `ed25519 <version> <keypair base64 encoded>` which
/// is Synapse's format
ExportPath {
path: PathBuf,
},
/// Filesystem path for conduwuit to attempt to read and import the
/// homeserver signing key. The expected format is Synapse's format:
/// `ed25519 <version> <keypair base64 encoded>`
ImportPath {
path: PathBuf,
#[arg(long)]
/// Optional argument to import the key but don't overwrite our signing
/// key, and instead add it to `old_verify_keys`. This field tells other
/// servers that this is our old public key that can still be used to
/// sign old events.
///
/// See https://spec.matrix.org/v1.9/server-server-api/#get_matrixkeyv2server for more details.
add_to_old_public_keys: bool,
#[arg(long)]
/// Timestamp (`expired_ts`) in seconds since UNIX epoch that the old
/// homeserver signing key stopped being used.
///
/// See https://spec.matrix.org/v1.9/server-server-api/#get_matrixkeyv2server for more details.
timestamp: u64,
},
} }
/// Parse commandline arguments into structured data /// Parse commandline arguments into structured data

View file

@ -211,9 +211,10 @@ lasttimelinecount_cache: {lasttimelinecount_cache}\n"
.map(|key| (version, key)) .map(|key| (version, key))
}) })
.and_then(|(version, key)| { .and_then(|(version, key)| {
debug!("Keypair bytes: {:?}", key);
let keypair = Ed25519KeyPair::from_der(key, version) let keypair = Ed25519KeyPair::from_der(key, version)
.map_err(|_| Error::bad_database("Private or public keys are invalid.")); .map_err(|_| Error::bad_database("Private or public keys are invalid."));
debug!("Private and public key bytes: {keypair:?}"); debug!("Private and public key: {keypair:?}");
keypair keypair
}) })
} }

View file

@ -15,8 +15,12 @@ use axum::{
use axum_server::{bind, bind_rustls, tls_rustls::RustlsConfig, Handle as ServerHandle}; use axum_server::{bind, bind_rustls, tls_rustls::RustlsConfig, Handle as ServerHandle};
#[cfg(feature = "axum_dual_protocol")] #[cfg(feature = "axum_dual_protocol")]
use axum_server_dual_protocol::ServerExt; use axum_server_dual_protocol::ServerExt;
use conduit::api::{client_server, server_server}; use base64::{engine::general_purpose, Engine as _};
pub use conduit::*; // Re-export everything from the library crate pub use conduit::*; // Re-export everything from the library crate
use conduit::{
api::{client_server, server_server},
clap::{Args, SigningKey},
};
use either::Either::{Left, Right}; use either::Either::{Left, Right};
use figment::{ use figment::{
providers::{Env, Format, Toml}, providers::{Env, Format, Toml},
@ -28,12 +32,15 @@ use http::{
}; };
#[cfg(unix)] #[cfg(unix)]
use hyperlocal::SocketIncoming; use hyperlocal::SocketIncoming;
use ruma::api::{ use ruma::{
client::{ api::{
error::{Error as RumaError, ErrorBody, ErrorKind}, client::{
uiaa::UiaaResponse, error::{Error as RumaError, ErrorBody, ErrorKind},
uiaa::UiaaResponse,
},
IncomingRequest,
}, },
IncomingRequest, serde::Base64,
}; };
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
use tikv_jemallocator::Jemalloc; use tikv_jemallocator::Jemalloc;
@ -73,7 +80,7 @@ async fn main() {
} else if args.config.is_some() { } else if args.config.is_some() {
Figment::new() Figment::new()
.merge( .merge(
Toml::file(args.config.expect( Toml::file(args.config.as_ref().expect(
"conduwuit config commandline argument was specified, but appears to be invalid. This should be \ "conduwuit config commandline argument was specified, but appears to be invalid. This should be \
set to the path of a valid TOML file.", set to the path of a valid TOML file.",
)) ))
@ -169,8 +176,16 @@ async fn main() {
let config = &services().globals.config; let config = &services().globals.config;
/* ad-hoc config validation/checks */ /* homeserver signing keypair subcommand stuff */
if let Some(subcommands) = &args.signing_key {
if signing_key_operations(subcommands).await.is_ok() {
return;
}
}
debug!("Ed25519KeyPair: {:?}", services().globals.keypair());
/* ad-hoc config validation/checks */
if config.unix_socket_path.is_some() && !cfg!(unix) { if config.unix_socket_path.is_some() && !cfg!(unix) {
error!( error!(
"UNIX socket support is only available on *nix platforms. Please remove \"unix_socket_path\" from your \ "UNIX socket support is only available on *nix platforms. Please remove \"unix_socket_path\" from your \
@ -912,3 +927,36 @@ fn maximize_fd_limit() -> Result<(), nix::errno::Errno> {
Ok(()) Ok(())
} }
/// Homeserver signing key commands/operations
async fn signing_key_operations(subcommands: &SigningKey) -> Result<()> {
match subcommands {
SigningKey::ExportPath {
path,
} => {
let mut file = tokio::fs::File::create(path).await?;
let mut content = String::new();
content.push_str("ed25519 ");
let version = services().globals.keypair().version();
content.push_str(version);
content.push(' ');
let keypair = services().globals.keypair();
debug!("Ed25519KeyPair: {:?}", keypair);
//let key_base64 = Base64::new(key);
Ok(())
},
SigningKey::ImportPath {
path,
add_to_old_public_keys,
timestamp,
} => {
unimplemented!()
},
}
}