Don't sign GET requests in private mode

This commit is contained in:
silverpill 2021-11-18 14:56:52 +00:00
parent 924f5181b6
commit ac1027ac2a
3 changed files with 44 additions and 38 deletions

View file

@ -1,7 +1,7 @@
use actix_web::http::Method; use actix_web::http::Method;
use rsa::RsaPrivateKey; use rsa::RsaPrivateKey;
use crate::config::{Environment, Config}; use crate::config::{Config, Instance};
use crate::http_signatures::create::{create_http_signature, SignatureError}; use crate::http_signatures::create::{create_http_signature, SignatureError};
use crate::models::users::types::User; use crate::models::users::types::User;
use crate::utils::crypto::deserialize_private_key; use crate::utils::crypto::deserialize_private_key;
@ -29,7 +29,7 @@ pub enum DelivererError {
} }
async fn send_activity( async fn send_activity(
config: &Config, instance: &Instance,
actor_key: &RsaPrivateKey, actor_key: &RsaPrivateKey,
actor_key_id: &str, actor_key_id: &str,
activity_json: &str, activity_json: &str,
@ -53,14 +53,12 @@ async fn send_activity(
.header("Content-Type", ACTIVITY_CONTENT_TYPE) .header("Content-Type", ACTIVITY_CONTENT_TYPE)
.body(activity_json.to_owned()); .body(activity_json.to_owned());
match config.environment { if instance.is_private {
Environment::Development => {
log::info!( log::info!(
"development mode: not sending activity to {}", "private mode: not sending activity to {}",
inbox_url, inbox_url,
); );
}, } else {
Environment::Production => {
// Default timeout is 30s // Default timeout is 30s
let response = request.send().await?; let response = request.send().await?;
let response_status = response.status(); let response_status = response.status();
@ -71,14 +69,13 @@ async fn send_activity(
); );
if response_status.is_client_error() || response_status.is_server_error() { if response_status.is_client_error() || response_status.is_server_error() {
return Err(DelivererError::HttpError(response_status)); return Err(DelivererError::HttpError(response_status));
} };
},
}; };
Ok(()) Ok(())
} }
async fn deliver_activity_worker( async fn deliver_activity_worker(
config: Config, instance: Instance,
sender: User, sender: User,
activity: Activity, activity: Activity,
recipients: Vec<Actor>, recipients: Vec<Actor>,
@ -87,7 +84,7 @@ async fn deliver_activity_worker(
let actor_key_id = format!( let actor_key_id = format!(
"{}#main-key", "{}#main-key",
get_actor_url( get_actor_url(
&config.instance_url(), &instance.url(),
&sender.profile.username, &sender.profile.username,
), ),
); );
@ -100,7 +97,7 @@ async fn deliver_activity_worker(
for inbox_url in inboxes { for inbox_url in inboxes {
// TODO: retry on error // TODO: retry on error
if let Err(err) = send_activity( if let Err(err) = send_activity(
&config, &instance,
&actor_key, &actor_key,
&actor_key_id, &actor_key_id,
&activity_json, &activity_json,
@ -118,11 +115,11 @@ pub fn deliver_activity(
activity: Activity, activity: Activity,
recipients: Vec<Actor>, recipients: Vec<Actor>,
) -> () { ) -> () {
let config = config.clone(); let instance = config.instance();
let sender = sender.clone(); let sender = sender.clone();
actix_rt::spawn(async move { actix_rt::spawn(async move {
deliver_activity_worker( deliver_activity_worker(
config, instance,
sender, sender,
activity, activity,
recipients, recipients,

View file

@ -45,6 +45,8 @@ async fn send_request(
request_builder = request_builder.query(query_params); request_builder = request_builder.query(query_params);
}; };
if !instance.is_private {
// Only public instance can send signed request
let headers = create_http_signature( let headers = create_http_signature(
Method::GET, Method::GET,
url, url,
@ -52,12 +54,14 @@ async fn send_request(
&instance.actor_key, &instance.actor_key,
&instance.actor_key_id(), &instance.actor_key_id(),
)?; )?;
request_builder = request_builder
.header("Host", headers.host)
.header("Date", headers.date)
.header("Signature", headers.signature);
};
let data = request_builder let data = request_builder
.header(reqwest::header::ACCEPT, ACTIVITY_CONTENT_TYPE) .header(reqwest::header::ACCEPT, ACTIVITY_CONTENT_TYPE)
.header("Host", headers.host)
.header("Date", headers.date)
.header("Signature", headers.signature)
.send().await? .send().await?
.error_for_status()? .error_for_status()?
.text().await?; .text().await?;

View file

@ -9,7 +9,7 @@ use crate::activitypub::views::get_instance_actor_url;
use crate::errors::ConversionError; use crate::errors::ConversionError;
use crate::utils::crypto::deserialize_private_key; use crate::utils::crypto::deserialize_private_key;
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
pub enum Environment { pub enum Environment {
Development, Development,
Production, Production,
@ -126,6 +126,7 @@ impl Config {
Instance { Instance {
_url: self.try_instance_url().unwrap(), _url: self.try_instance_url().unwrap(),
actor_key: self.try_instance_rsa_key().unwrap(), actor_key: self.try_instance_rsa_key().unwrap(),
is_private: self.environment == Environment::Development,
} }
} }
@ -142,6 +143,8 @@ pub struct Instance {
_url: Url, _url: Url,
// Instance actor // Instance actor
pub actor_key: RsaPrivateKey, pub actor_key: RsaPrivateKey,
// Private instance won't send signed HTTP requests
pub is_private: bool,
} }
impl Instance { impl Instance {
@ -200,6 +203,7 @@ mod tests {
let instance = Instance { let instance = Instance {
_url: instance_url, _url: instance_url,
actor_key: instance_rsa_key, actor_key: instance_rsa_key,
is_private: true,
}; };
assert_eq!(instance.url(), "https://example.com"); assert_eq!(instance.url(), "https://example.com");
@ -213,6 +217,7 @@ mod tests {
let instance = Instance { let instance = Instance {
_url: instance_url, _url: instance_url,
actor_key: instance_rsa_key, actor_key: instance_rsa_key,
is_private: true,
}; };
assert_eq!(instance.url(), "http://1.2.3.4:3777"); assert_eq!(instance.url(), "http://1.2.3.4:3777");