Don't sign GET requests in private mode
This commit is contained in:
parent
924f5181b6
commit
ac1027ac2a
3 changed files with 44 additions and 38 deletions
|
@ -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,32 +53,29 @@ 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!(
|
"private mode: not sending activity to {}",
|
||||||
"development mode: not sending activity to {}",
|
inbox_url,
|
||||||
inbox_url,
|
);
|
||||||
);
|
} else {
|
||||||
},
|
// Default timeout is 30s
|
||||||
Environment::Production => {
|
let response = request.send().await?;
|
||||||
// Default timeout is 30s
|
let response_status = response.status();
|
||||||
let response = request.send().await?;
|
let response_text = response.text().await?;
|
||||||
let response_status = response.status();
|
log::info!(
|
||||||
let response_text = response.text().await?;
|
"remote server response: {}",
|
||||||
log::info!(
|
response_text,
|
||||||
"remote server response: {}",
|
);
|
||||||
response_text,
|
if response_status.is_client_error() || response_status.is_server_error() {
|
||||||
);
|
return Err(DelivererError::HttpError(response_status));
|
||||||
if response_status.is_client_error() || response_status.is_server_error() {
|
};
|
||||||
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,
|
||||||
|
|
|
@ -45,19 +45,23 @@ async fn send_request(
|
||||||
request_builder = request_builder.query(query_params);
|
request_builder = request_builder.query(query_params);
|
||||||
};
|
};
|
||||||
|
|
||||||
let headers = create_http_signature(
|
if !instance.is_private {
|
||||||
Method::GET,
|
// Only public instance can send signed request
|
||||||
url,
|
let headers = create_http_signature(
|
||||||
"",
|
Method::GET,
|
||||||
&instance.actor_key,
|
url,
|
||||||
&instance.actor_key_id(),
|
"",
|
||||||
)?;
|
&instance.actor_key,
|
||||||
|
&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?;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in a new issue