]> Untitled Git - lemmy.git/commitdiff
Rewrite federation settings
authorFelix Ableitner <me@nutomic.com>
Wed, 18 Mar 2020 21:09:00 +0000 (22:09 +0100)
committerFelix Ableitner <me@nutomic.com>
Wed, 18 Mar 2020 21:09:00 +0000 (22:09 +0100)
docker/federation-test/docker-compose.yml
server/config/defaults.hjson
server/src/api/community.rs
server/src/api/post.rs
server/src/apub/mod.rs
server/src/apub/puller.rs
server/src/routes/federation.rs
server/src/routes/nodeinfo.rs
server/src/routes/webfinger.rs
server/src/settings.rs

index 63dbf27d3e1d2cf85030e4c7a52664a47bde5809..de539237b17dfd5e74e17a7b84704c8ae2919bec 100644 (file)
@@ -10,8 +10,9 @@ services:
       - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
       - LEMMY_JWT_SECRET=changeme
       - LEMMY_FRONT_END_DIR=/app/dist
-      - LEMMY_FEDERATION_ENABLED=true
-      - LEMMY_FEDERATED_INSTANCE=lemmy_beta:8541
+      - LEMMY_FEDERATION__ENABLED=true
+      - LEMMY_FEDERATION__FOLLOWED_INSTANCES=lemmy_beta:8541
+      - LEMMY_FEDERATION__TLS_ENABLED=false
       - LEMMY_PORT=8540
       - RUST_BACKTRACE=1
     restart: always
@@ -36,8 +37,9 @@ services:
       - LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
       - LEMMY_JWT_SECRET=changeme
       - LEMMY_FRONT_END_DIR=/app/dist
-      - LEMMY_FEDERATION_ENABLED=true
-      - LEMMY_FEDERATED_INSTANCE=lemmy_alpha:8540
+      - LEMMY_FEDERATION__ENABLED=true
+      - LEMMY_FEDERATION__FOLLOWED_INSTANCES=lemmy_alpha:8540
+      - LEMMY_FEDERATION__TLS_ENABLED=false
       - LEMMY_PORT=8541
       - RUST_BACKTRACE=1
     restart: always
index 7eda46ec4472f4d7db2fd972f030c886031a353a..e048ced89048aae063d79ea05bd5fc3bd4cf7ce4 100644 (file)
   jwt_secret: "changeme"
   # The dir for the front end
   front_end_dir: "../ui/dist"
-  # whether to enable activitypub federation. this feature is in alpha, do not enable in production.
-  federation_enabled: false
-  // another instance to federate with. this should be a list, but it seems like lists cant be set from environment
-  // https://github.com/mehcode/config-rs/issues/117
-  federated_instance: null
   # rate limits for various user actions, by user ip
   rate_limit: {
     # maximum number of messages created in interval
     # interval length for registration limit
     register_per_second: 3600
   }
+  # settings related to activitypub federation
+  federation: {
+    # whether to enable activitypub federation. this feature is in alpha, do not enable in production.
+    enabled: false
+    # comma seperated list of instances to follow
+    followed_instances: ""
+    # whether tls is required for activitypub. only disable this for debugging, never for producion.
+    tls_enabled: true
+  }
 #  # email sending configuration
 #  email: {
 #    # hostname of the smtp server
index a07b15d720e3d9939348b15573fd33052bcd2003..dac8733b2aeebd6142c60724fd9c43955e3264e3 100644 (file)
@@ -121,7 +121,7 @@ impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
     let data: &GetCommunity = &self.data;
 
     if data.name.is_some()
-      && Settings::get().federation_enabled
+      && Settings::get().federation.enabled
       && data.name.as_ref().unwrap().contains('@')
     {
       return get_remote_community(data.name.as_ref().unwrap());
@@ -344,7 +344,7 @@ impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
     let data: &ListCommunities = &self.data;
 
     let local_only = data.local_only.unwrap_or(false);
-    if Settings::get().federation_enabled && !local_only {
+    if Settings::get().federation.enabled && !local_only {
       return Ok(ListCommunitiesResponse {
         communities: get_all_communities()?,
       });
index 1602626be862a09ad5ad4ae6cd6397bde8c541b9..651d5769ef5b924c319abd881e79c6ba3eb83924 100644 (file)
@@ -221,7 +221,7 @@ impl Perform<GetPostsResponse> for Oper<GetPosts> {
   fn perform(&self, conn: &PgConnection) -> Result<GetPostsResponse, Error> {
     let data: &GetPosts = &self.data;
 
-    if Settings::get().federation_enabled {
+    if Settings::get().federation.enabled {
       // TODO: intercept here (but the type is wrong)
       //get_remote_community_posts(get_posts.community_id.unwrap())
     }
index b7202d57f7ce195adfcc315ba8e27e236c7571ab..97eb21565d6a57cc672c78a558f7a42b76a4f5db 100644 (file)
@@ -38,5 +38,9 @@ fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
 }
 
 pub fn get_apub_protocol_string() -> &'static str {
-  "http"
+  if Settings::get().federation.tls_enabled {
+    "https"
+  } else {
+    "http"
+  }
 }
index e7b5d6d7df69eba18d1491e13b1b6a96c119e94b..e318a68ec41805cc87c925da7604d95adaf3abe3 100644 (file)
@@ -2,6 +2,7 @@ extern crate reqwest;
 
 use crate::api::community::{GetCommunityResponse, ListCommunitiesResponse};
 use crate::api::post::GetPostsResponse;
+use crate::apub::get_apub_protocol_string;
 use crate::db::community_view::CommunityView;
 use crate::db::post_view::PostView;
 use crate::naive_now;
@@ -16,10 +17,15 @@ use log::warn;
 use serde::Deserialize;
 
 fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
-  let well_known: NodeInfoWellKnown =
-    reqwest::get(&format!("http://{}/.well-known/nodeinfo", domain))?.json()?;
-  Ok(reqwest::get(&well_known.links.href)?.json()?)
+  let well_known_uri = format!(
+    "{}://{}/.well-known/nodeinfo",
+    get_apub_protocol_string(),
+    domain
+  );
+  let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
+  Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
 }
+
 fn fetch_communities_from_instance(domain: &str) -> Result<Vec<CommunityView>, Error> {
   let node_info = fetch_node_info(domain)?;
   if node_info.software.name != "lemmy" {
@@ -54,6 +60,9 @@ fn fetch_remote_object<Response>(uri: &str) -> Result<Response, Error>
 where
   Response: for<'de> Deserialize<'de>,
 {
+  if Settings::get().federation.tls_enabled && !uri.starts_with("https") {
+    return Err(format_err!("Activitypub uri is insecure: {}", uri));
+  }
   // TODO: should cache responses here when we are in production
   // TODO: this function should return a future
   // TODO: in production mode, fail if protocol is not https
@@ -179,11 +188,12 @@ pub fn get_remote_community(identifier: &str) -> Result<GetCommunityResponse, fa
   })
 }
 
-pub fn get_following_instances() -> Vec<String> {
-  match Settings::get().federated_instance.clone() {
-    Some(f) => vec![f, Settings::get().hostname.clone()],
-    None => vec![Settings::get().hostname.clone()],
-  }
+pub fn get_following_instances() -> Vec<&'static str> {
+  Settings::get()
+    .federation
+    .followed_instances
+    .split(',')
+    .collect()
 }
 
 pub fn get_all_communities() -> Result<Vec<CommunityView>, Error> {
index fbe8d795a3849c793ec781f0ab9fc01ee0b652f0..06a88e2b653311caa3df2c9948e73f65cc61db11 100644 (file)
@@ -9,7 +9,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
 use diesel::PgConnection;
 
 pub fn config(cfg: &mut web::ServiceConfig) {
-  if Settings::get().federation_enabled {
+  if Settings::get().federation.enabled {
     println!("federation enabled, host is {}", Settings::get().hostname);
     cfg
       .route(
index 901db9d31ccb3ec9f999bdb0946b4d2a14c46814..abfae1eda0ae6f5d143548f0f5f052519e7a4968 100644 (file)
@@ -40,7 +40,7 @@ async fn node_info(
       Ok(site_view) => site_view,
       Err(_) => return Err(format_err!("not_found")),
     };
-    let protocols = if Settings::get().federation_enabled {
+    let protocols = if Settings::get().federation.enabled {
       vec!["activitypub".to_string()]
     } else {
       vec![]
index a078b487e9dfebcfa94c0590d42bf4e26fe7dee9..33e3a48e62555ac4499358a2a87d0070beadb98d 100644 (file)
@@ -15,7 +15,7 @@ pub struct Params {
 }
 
 pub fn config(cfg: &mut web::ServiceConfig) {
-  if Settings::get().federation_enabled {
+  if Settings::get().federation.enabled {
     cfg.route(
       ".well-known/webfinger",
       web::get().to(get_webfinger_response),
index 3d32f3f38d63d6d4dc611db902a925be930a77cb..3928f74e1ef189886fbdde3451e1d669c5fcd766 100644 (file)
@@ -17,8 +17,7 @@ pub struct Settings {
   pub front_end_dir: String,
   pub rate_limit: RateLimitConfig,
   pub email: Option<EmailConfig>,
-  pub federation_enabled: bool,
-  pub federated_instance: Option<String>,
+  pub federation: Federation,
 }
 
 #[derive(Debug, Deserialize)]
@@ -50,6 +49,13 @@ pub struct Database {
   pub pool_size: u32,
 }
 
+#[derive(Debug, Deserialize)]
+pub struct Federation {
+  pub enabled: bool,
+  pub followed_instances: String,
+  pub tls_enabled: bool,
+}
+
 lazy_static! {
   static ref SETTINGS: Settings = {
     match Settings::init() {