From 52b51501d5e892e146a28873bf1c43069b73b8fb Mon Sep 17 00:00:00 2001 From: silverpill Date: Thu, 18 Nov 2021 00:22:41 +0000 Subject: [PATCH] Add config parameter that specifies instance actor's private key --- README.md | 6 ++++++ config.yaml.example | 1 + src/bin/mitractl.rs | 15 +++++++++++++++ src/config.rs | 28 +++++++++++++++++++++++++--- src/lib.rs | 2 +- 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 700ca28..f94b3e4 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,12 @@ GET /api/v1/statuses/{status_id}/signature ## CLI commands +Generate RSA private key: + +``` +mitractl generate-rsa-key +``` + Generate invite code: ``` diff --git a/config.yaml.example b/config.yaml.example index 59fbb20..9018866 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -10,6 +10,7 @@ instance_title: myserver instance_short_description: my fedi instance # Long description can contain markdown syntax instance_description: my fedi instance +instance_rsa_key: null registrations_open: false # Login message must contain instance URL login_message: 'Sign this message to log in to https://myserver.net. Do not sign this message on other sites!' diff --git a/src/bin/mitractl.rs b/src/bin/mitractl.rs index 5116a76..ad2d304 100644 --- a/src/bin/mitractl.rs +++ b/src/bin/mitractl.rs @@ -12,6 +12,7 @@ use mitra::models::users::queries::{ create_invite_code, get_invite_codes, }; +use mitra::utils::crypto::{generate_private_key, serialize_private_key}; /// Admin CLI tool #[derive(Clap)] @@ -22,6 +23,7 @@ struct Opts { #[derive(Clap)] enum SubCommand { + GenerateRsaKey(GenerateRsaKey), GenerateEthereumAddress(GenerateEthereumAddress), GenerateInviteCode(GenerateInviteCode), @@ -30,6 +32,18 @@ enum SubCommand { DeletePost(DeletePost), } +/// Generate RSA private key +#[derive(Clap)] +struct GenerateRsaKey; + +impl GenerateRsaKey { + fn execute(&self) -> () { + let private_key = generate_private_key().unwrap(); + let private_key_str = serialize_private_key(private_key).unwrap(); + println!("{}", private_key_str); + } +} + /// Generate ethereum address #[derive(Clap)] struct GenerateEthereumAddress; @@ -61,6 +75,7 @@ async fn main() { let opts: Opts = Opts::parse(); match opts.subcmd { + SubCommand::GenerateRsaKey(cmd) => cmd.execute(), SubCommand::GenerateEthereumAddress(_) => { let (private_key, address) = generate_ethereum_address(); println!( diff --git a/src/config.rs b/src/config.rs index cfeebfc..7904255 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,12 @@ use std::path::PathBuf; use std::str::FromStr; +use rsa::RsaPrivateKey; use serde::{de, Deserialize, Deserializer}; use url::Url; use crate::errors::ConversionError; +use crate::utils::crypto::deserialize_private_key; #[derive(Clone, Debug)] pub enum Environment { @@ -86,6 +88,7 @@ pub struct Config { pub instance_title: String, pub instance_short_description: String, pub instance_description: String, + instance_rsa_key: String, #[serde(default)] pub registrations_open: bool, // default is false @@ -114,8 +117,15 @@ impl Config { Ok(url) } + fn try_instance_rsa_key(&self) -> Result { + deserialize_private_key(&self.instance_rsa_key) + } + pub fn instance(&self) -> Instance { - Instance { _url: self.try_instance_url().unwrap() } + Instance { + _url: self.try_instance_url().unwrap(), + actor_key: self.try_instance_rsa_key().unwrap(), + } } pub fn instance_url(&self) -> String { @@ -129,6 +139,8 @@ impl Config { pub struct Instance { _url: Url, + // Instance actor + pub actor_key: RsaPrivateKey, } impl Instance { @@ -162,18 +174,24 @@ pub fn parse_config() -> Config { }; }; config.try_instance_url().expect("invalid instance URI"); + config.try_instance_rsa_key().expect("invalid RSA private key"); config } #[cfg(test)] mod tests { + use rand::rngs::OsRng; use super::*; #[test] fn test_instance_url_https_dns() { let instance_url = Url::parse("https://example.com/").unwrap(); - let instance = Instance { _url: instance_url }; + let instance_rsa_key = RsaPrivateKey::new(&mut OsRng, 512).unwrap(); + let instance = Instance { + _url: instance_url, + actor_key: instance_rsa_key, + }; assert_eq!(instance.url(), "https://example.com"); assert_eq!(instance.host(), "example.com"); @@ -182,7 +200,11 @@ mod tests { #[test] fn test_instance_url_http_ipv4() { let instance_url = Url::parse("http://1.2.3.4:3777/").unwrap(); - let instance = Instance { _url: instance_url }; + let instance_rsa_key = RsaPrivateKey::new(&mut OsRng, 512).unwrap(); + let instance = Instance { + _url: instance_url, + actor_key: instance_rsa_key, + }; assert_eq!(instance.url(), "http://1.2.3.4:3777"); assert_eq!(instance.host(), "1.2.3.4"); diff --git a/src/lib.rs b/src/lib.rs index eccad3a..d7bd517 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,5 +11,5 @@ pub mod mastodon_api; pub mod models; pub mod nodeinfo; pub mod scheduler; -mod utils; +pub mod utils; pub mod webfinger;