From 417804e28620c9dde8847033b0e941e17540201c Mon Sep 17 00:00:00 2001 From: FlakM Date: Wed, 20 Dec 2023 08:57:28 +0100 Subject: [PATCH] chore: add hardening --- backend/Cargo.lock | 245 ++++++++++++------ backend/Cargo.toml | 12 +- backend/flake.nix | 6 +- backend/src/activities/follow.rs | 2 - backend/src/activities/mod.rs | 1 + backend/src/activities/undo_follow.rs | 64 +++++ backend/src/database.rs | 67 +++-- backend/src/http.rs | 2 +- backend/src/main.rs | 27 +- backend/src/objects/person.rs | 5 +- .../content/posts/nixos_rust/04_hardening.md | 20 ++ blog-static/flake.nix | 19 +- configuration.nix | 31 ++- flake.lock | 12 +- flake.nix | 6 +- integration.nix | 2 +- 16 files changed, 385 insertions(+), 136 deletions(-) create mode 100644 backend/src/activities/undo_follow.rs create mode 100644 blog-static/content/posts/nixos_rust/04_hardening.md diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 0908aca..893d729 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -5,8 +5,7 @@ version = 3 [[package]] name = "activitypub_federation" version = "0.5.0-beta.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0aafb8ad437a019bac2e11d47fad6131974dace1855640a09d0e71d26571c1" +source = "git+https://github.com/FlakM/activitypub-federation-rust.git#fe579f7759942c7d84622894e514d71843870e89" dependencies = [ "activitystreams-kinds", "actix-web", @@ -141,7 +140,7 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2 0.5.5", + "socket2", "tokio", "tracing", ] @@ -199,7 +198,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2 0.5.5", + "socket2", "time", "url", ] @@ -377,6 +376,53 @@ dependencies = [ "syn 2.0.41", ] +[[package]] +name = "backend" +version = "0.1.0" +dependencies = [ + "activitypub_federation", + "activitystreams-kinds", + "anyhow", + "async-trait", + "axum", + "axum-macros", + "base64 0.21.5", + "bytes", + "chrono", + "derive_builder", + "dyn-clone", + "enum_delegate", + "env_logger", + "futures", + "futures-core", + "http 0.2.11", + "http-body-util", + "http-signature-normalization", + "http-signature-normalization-reqwest", + "httpdate", + "hyper", + "itertools", + "moka", + "once_cell", + "openssl", + "pin-project-lite", + "rand", + "regex", + "reqwest", + "reqwest-middleware", + "serde", + "serde_json", + "sha2", + "sqlx", + "thiserror", + "tokio", + "tower", + "tower-http", + "tracing", + "tracing-subscriber", + "url", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -1138,11 +1184,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1253,9 +1299,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1268,7 +1314,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1464,6 +1510,15 @@ dependencies = [ "libc", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.3" @@ -1601,6 +1656,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -1718,6 +1783,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1869,52 +1940,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "quick-start" -version = "0.1.0" -dependencies = [ - "activitypub_federation", - "activitystreams-kinds", - "anyhow", - "async-trait", - "axum", - "axum-macros", - "base64 0.21.5", - "bytes", - "chrono", - "derive_builder", - "dyn-clone", - "enum_delegate", - "env_logger", - "futures", - "futures-core", - "http 0.2.11", - "http-body-util", - "http-signature-normalization", - "http-signature-normalization-reqwest", - "httpdate", - "hyper", - "itertools", - "moka", - "once_cell", - "openssl", - "pin-project-lite", - "rand", - "regex", - "reqwest", - "reqwest-middleware", - "serde", - "serde_json", - "sha2", - "sqlx", - "thiserror", - "tokio", - "tower", - "tower-http", - "tracing", - "url", -] - [[package]] name = "quote" version = "1.0.33" @@ -1980,8 +2005,17 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1992,9 +2026,15 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.2", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.2" @@ -2003,9 +2043,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "base64 0.21.5", "bytes", @@ -2249,6 +2289,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2298,16 +2347,6 @@ version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.5" @@ -2666,29 +2705,39 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" dependencies = [ "proc-macro2", "quote", "syn 2.0.41", ] +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", @@ -2706,9 +2755,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -2742,7 +2791,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -2871,6 +2920,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2960,6 +3039,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index e7f25db..2af1d18 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "quick-start" +name = "backend" version = "0.1.0" edition = "2021" @@ -12,7 +12,7 @@ url = { version = "2.5.0", features = ["serde"] } serde_json = { version = "1.0.108", features = ["preserve_order", "raw_value"] } reqwest = { version = "0.11.22", features = ["json", "stream"] } reqwest-middleware = "0.2.4" -tracing = "0.1.40" +tracing = "0.1" base64 = "0.21.5" openssl = "0.10.60" once_cell = "1.18.0" @@ -48,11 +48,17 @@ rand = "0.8.5" env_logger = "0.10.1" tower-http = { version = "0.4.0", features = ["map-request-body", "util", "trace"] } axum-macros = "0.3.8" -activitypub_federation = "0.5.0-beta.5" + +#activitypub_federation = "0.5.0-beta.5" +# take from git git@github.com:FlakM/activitypub-federation-rust.git +activitypub_federation = { git = "https://github.com/FlakM/activitypub-federation-rust.git"} + + tokio = { version = "1.35.0", features = ["full"] } sqlx = { version = "0.7", features = [ "runtime-tokio", "migrate", "sqlite", "chrono" , "json"] } +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/backend/flake.nix b/backend/flake.nix index a26d77a..63bde03 100644 --- a/backend/flake.nix +++ b/backend/flake.nix @@ -85,7 +85,7 @@ wantedBy = [ "multi-user.target" ]; serviceConfig = { Restart = "on-failure"; - ExecStart = "${server}/bin/quick-start"; + ExecStart = "${server}/bin/backend"; DynamicUser = true; TemporaryFileSystem = "/:ro"; BindPaths = "/var/lib/backend"; @@ -154,9 +154,7 @@ default = server; }; - devShell = with pkgs; mkShell { - - }; + devShell = with pkgs; mkShell { }; }); } diff --git a/backend/src/activities/follow.rs b/backend/src/activities/follow.rs index 2d56c4a..294f28b 100644 --- a/backend/src/activities/follow.rs +++ b/backend/src/activities/follow.rs @@ -46,8 +46,6 @@ impl ActivityHandler for Follow { Ok(()) } - // Ignore clippy false positive: https://github.com/rust-lang/rust-clippy/issues/6446 - #[allow(clippy::await_holding_lock)] async fn receive(self, data: &Data) -> Result<(), Self::Error> { tracing::info!("Received follow from {}", self.actor.inner()); diff --git a/backend/src/activities/mod.rs b/backend/src/activities/mod.rs index 73f5dd6..f8f5020 100644 --- a/backend/src/activities/mod.rs +++ b/backend/src/activities/mod.rs @@ -1,3 +1,4 @@ pub mod accept; pub mod create_post; pub mod follow; +pub mod undo_follow; diff --git a/backend/src/activities/undo_follow.rs b/backend/src/activities/undo_follow.rs new file mode 100644 index 0000000..9c0eb43 --- /dev/null +++ b/backend/src/activities/undo_follow.rs @@ -0,0 +1,64 @@ +use crate::{ + activities::accept::Accept, database::Database, generate_object_id, objects::person::DbUser, +}; +use activitypub_federation::traits::Actor; +use activitypub_federation::{ + config::Data, fetch::object_id::ObjectId, kinds::activity::FollowType, traits::ActivityHandler, +}; +use activitystreams_kinds::activity::UndoType; +use serde::{Deserialize, Serialize}; +use url::Url; + +use super::follow::Follow; + + +// {"@context":"https://www.w3.org/ns/activitystreams","id":"https://hachyderm.io/users/flakm#follows/3466630/undo", +// "type":"Undo","actor":"https://hachyderm.io/users/flakm", +// "object":{"id":"https://hachyderm.io/d6e9a487-9a5d-45f0-846b-bf2d90947e38","type":"Follow","actor":"https://hachyderm.io/users/flakm","object":"https://fedi.flakm.com/blog_test2"}} +#[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Unfollow { + pub(crate) actor: ObjectId, + pub(crate) object: Follow, + #[serde(rename = "type")] + kind: UndoType, + id: Url, +} + + +#[async_trait::async_trait] +impl ActivityHandler for Unfollow { + type DataType = Database; + type Error = crate::error::Error; + + fn id(&self) -> &Url { + &self.id + } + + fn actor(&self) -> &Url { + self.actor.inner() + } + + async fn verify(&self, _data: &Data) -> Result<(), Self::Error> { + Ok(()) + } + + async fn receive(self, data: &Data) -> Result<(), Self::Error> { + tracing::info!("Received unfollow from {}", self.actor.inner()); + + let local_user = data.local_user().await?; + let follower = self.actor.dereference(data).await?; + + // add to followers + data.remove_follower(&local_user, &follower).await?; + + // send back an accept + let id = generate_object_id(data.domain())?; + let accept = Accept::new(local_user.ap_id.clone(), self.object, id.clone()); + tracing::info!("Sending unfollow accept to {}", follower.ap_id); + local_user + .send(accept, vec![follower.shared_inbox_or_inbox()], data) + .await?; + Ok(()) + } +} diff --git a/backend/src/database.rs b/backend/src/database.rs index 51fef9f..84e5257 100644 --- a/backend/src/database.rs +++ b/backend/src/database.rs @@ -10,6 +10,11 @@ pub struct Database { pub pool: sqlx::SqlitePool, } +#[derive(sqlx::FromRow, Debug)] +pub struct SavedUser { + pub id: i64, +} + impl Database { pub async fn local_user(&self) -> Result { let user = self.read_user(LOCAL_USER_NAME).await?; @@ -30,21 +35,26 @@ impl Database { user.map(|u| Ok(u.into())).transpose() } - pub async fn save_user(&self, user: &DbUser) -> Result<(), Error> { + pub async fn save_user(&self, user: &DbUser) -> Result { let user_json = serde_json::to_string(user)?; let object_id = user.ap_id.inner().to_string(); - sqlx::query!( - "INSERT INTO users (name, user, object_id) VALUES (?, ?, ?)", + + //"INSERT INTO users (name, user, object_id) VALUES (?, ?, ?) returning id", + // + let id: SavedUser = sqlx::query_as!( + SavedUser, + r#"INSERT INTO users (name, user, object_id) VALUES (?, ?, ?) returning id"#, user.name, user_json, object_id ) - .execute(&self.pool) + .fetch_one(&self.pool) .await?; - Ok(()) + Ok(id) } - pub async fn find_by_object_id(&self, object_id: &str) -> Result { + pub async fn find_by_object_id(&self, object_id: &str) -> Result, Error> { + tracing::debug!("find_by_object_id: {}", object_id); let user: Option = sqlx::query_as!( SqliteUser, r#"SELECT id, name, object_id, user AS "user: sqlx::types::Json" FROM users WHERE object_id = ?"#, @@ -52,11 +62,7 @@ impl Database { ) .fetch_optional(&self.pool) .await?; - - match user { - Some(user) => Ok(user.into()), - None => Err(anyhow!("User not found").into()), - } + user.map(|u| Ok(u.into())).transpose() } pub async fn get_followers(&self, user: &DbUser) -> Result, Error> { @@ -68,16 +74,45 @@ impl Database { Ok(followers) } + pub async fn remove_follower(&self, user: &DbUser, follower: &DbUser) -> Result<(), Error> { + let follower_url = follower.ap_id.inner().to_string(); + + tracing::debug!("remove_follower: {} {}", user.name, follower_url); + + sqlx::query!( + r#"DELETE FROM followers WHERE user_id = (SELECT id FROM users WHERE name = ?) AND follower_id = (SELECT id FROM users WHERE name = ?)"#, + user.name, + follower.name + ) + .execute(&self.pool) + .await?; + Ok(()) + } + pub async fn save_follower(&self, user: &DbUser, follower: &DbUser) -> Result<(), Error> { - // todo: check if follower already exists - self.save_user(follower).await?; + if let Some(_user) = self.read_user(&follower.name).await? { + // follower user already exists, do nothing + } + else { + // save new user in the database + self.save_user(follower).await?; + }; + let follower_url = follower.ap_id.inner().to_string(); + + tracing::debug!("save_follower: {} {}", user.name, follower_url); + sqlx::query!( - r#"INSERT INTO followers (user_id, follower_url) VALUES ((SELECT id FROM users WHERE name = ?), ?)"#, + r#"INSERT INTO followers (user_id, follower_id, follower_url) VALUES ( + (SELECT id FROM users WHERE name = ?), + (SELECT id FROM users WHERE name = ?) + , ?)"#, user.name, + follower.name, follower_url - ).execute(&self.pool).await?; - + ) + .execute(&self.pool) + .await?; Ok(()) } } diff --git a/backend/src/http.rs b/backend/src/http.rs index ad75f12..7c386ab 100644 --- a/backend/src/http.rs +++ b/backend/src/http.rs @@ -38,7 +38,7 @@ pub async fn http_get_user( ) -> Result>, Error> { let db_user = data.read_user(&name).await?; let json_user = db_user - .ok_or(Error(anyhow::anyhow!("User not found")))? + .ok_or(Error(anyhow::anyhow!("User not found http_get_user")))? .into_json(&data) .await?; Ok(FederationJson(WithContext::new_default(json_user))) diff --git a/backend/src/main.rs b/backend/src/main.rs index fe1550b..16e2d3b 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -5,7 +5,6 @@ use crate::{ objects::{person::DbUser, post::DbPost}, utils::generate_object_id, }; -use ::http::HeaderMap; use activitypub_federation::config::{FederationConfig, FederationMiddleware}; use axum::response::Response; use axum::{ @@ -13,18 +12,18 @@ use axum::{ routing::{get, post}, Router, }; -use bytes::Bytes; use error::Error; use sqlx::sqlite::SqliteConnectOptions; use sqlx::SqlitePool; use std::net::ToSocketAddrs; -use tower_http::classify::ServerErrorsFailureClass; use tracing::log::info; use axum::extract::MatchedPath; use std::time::Duration; use tower_http::trace::TraceLayer; -use tracing::{info_span, Span}; +use tracing::{field, info_span, Span}; + +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; mod activities; mod database; @@ -40,7 +39,16 @@ const BIND_ADDRESS: &str = "127.0.0.1:3000"; #[tokio::main] async fn main() -> Result<(), Error> { - env_logger::builder().format_timestamp(None).init(); + tracing_subscriber::registry() + .with( + tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { + // axum logs rejections from built-in extractors with the `axum::rejection` + // target, at `TRACE` level. `axum::rejection=trace` enables showing those events + "backend=debug,tower_http=debug,axum::rejection=trace".into() + }), + ) + .with(tracing_subscriber::fmt::layer()) + .init(); let database_path = std::env::var("DATABASE_PATH").unwrap_or_else(|_| "./db.sqlite".into()); @@ -100,8 +108,10 @@ async fn main() -> Result<(), Error> { info_span!( "http_request", method = ?request.method(), + path = ?request.uri().path(), matched_path, - some_other_field = tracing::field::Empty, + latency = tracing::field::Empty, + status_code = tracing::field::Empty, ) }) .on_request(|_request: &Request<_>, _span: &Span| { @@ -109,8 +119,9 @@ async fn main() -> Result<(), Error> { // closures to attach a value to the initially empty field in the info_span // created above. }) - .on_response(|_response: &Response, _latency: Duration, _span: &Span| { - // ... + .on_response(|response: &Response, latency: Duration, span: &Span| { + span.record("latency", field::debug(&latency)); + span.record("status_code", response.status().as_u16()); tracing::info!("response"); }), ) diff --git a/backend/src/objects/person.rs b/backend/src/objects/person.rs index 17a1db2..d63b06d 100644 --- a/backend/src/objects/person.rs +++ b/backend/src/objects/person.rs @@ -1,5 +1,5 @@ use crate::{ - activities::{accept::Accept, create_post::CreatePost, follow::Follow}, + activities::{accept::Accept, create_post::CreatePost, follow::Follow, undo_follow::Unfollow}, database::Database, error::Error, utils::generate_object_id, @@ -118,6 +118,7 @@ pub enum PersonAcceptedActivities { CreateNote(CreatePost), Follow(Follow), Accept(Accept), + UndoFollow(Unfollow), } impl DbUser { @@ -207,7 +208,7 @@ impl Object for DbUser { object_id: Url, data: &Data, ) -> Result, Self::Error> { - data.find_by_object_id(object_id.as_str()).await.map(Some) + data.find_by_object_id(object_id.as_str()).await } async fn into_json(self, _data: &Data) -> Result { diff --git a/blog-static/content/posts/nixos_rust/04_hardening.md b/blog-static/content/posts/nixos_rust/04_hardening.md new file mode 100644 index 0000000..333d033 --- /dev/null +++ b/blog-static/content/posts/nixos_rust/04_hardening.md @@ -0,0 +1,20 @@ ++++ +draft = true +date = 2023-12-20T08:37:45+01:00 +title = "" +description = "A blog entry about hardening my nixos host" +slug = "" +authors = [] +tags = [] +categories = [] +externalLink = "" + +series = ["Simple personal blog"] ++++ + + +## The goals + + + + diff --git a/blog-static/flake.nix b/blog-static/flake.nix index 229d0cc..324e752 100644 --- a/blog-static/flake.nix +++ b/blog-static/flake.nix @@ -22,7 +22,8 @@ submodules = [ theme ]; }; - in { + in + { # This is a NixOS module that can be imported into a NixOS # configuration to enable the static-website service @@ -44,17 +45,17 @@ config = mkIf cfg.enable { services.nginx.virtualHosts.${cfg.domain} = { - locations."/" = { - root = "${website}"; - tryFiles = "$uri $uri/ =404"; - extraConfig = '' - add_header Cache-Control "public, max-age=3600"; - ''; - priority = 100; # set a high priority to make it the last location + locations."/" = { + root = "${website}"; + tryFiles = "$uri $uri/ =404"; + extraConfig = '' + add_header Cache-Control "public, max-age=3600"; + ''; + priority = 100; # set a high priority to make it the last location + }; }; }; }; - }; packages.default = website; diff --git a/configuration.nix b/configuration.nix index 7284415..97da210 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,4 +1,4 @@ -{ system, modulesPath, backend, static, ... }: { +{ system, pkgs, modulesPath, backend, static, ... }: { imports = [ # Adds availableKernelModules, kernelModules for instances running under QEMU (Ie Hetzner Cloud) (modulesPath + "/profiles/qemu-guest.nix") @@ -17,7 +17,16 @@ }; # Enable ssh access to the root user - services.openssh.enable = true; + services.openssh = { + enable = true; + listenAddresses = [ + { + addr = "100.96.101.15"; + port = 22; + } + ]; + }; + users.users.root.openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDh6bzSNqVZ1Ba0Uyp/EqThvDdbaAjsJ4GvYN40f/p9Wl4LcW/MQP8EYLvBTqTluAwRXqFa6fVpa0Y9Hq4kyNG62HiMoQRjujt6d3b+GU/pq7NN8+Oed9rCF6TxhtLdcvJWHTbcq9qIGs2s3eYDlMy+9koTEJ7Jnux0eGxObUaGteQUS1cOZ5k9PQg+WX5ncWa3QvqJNxx446+OzVoHgzZytvXeJMg91gKN9wAhKgfibJ4SpQYDHYcTrOILm7DLVghrcU2aFqLKVTrHSWSugfLkqeorRadHckRDr2VUzm5eXjcs4ESjrG6viKMKmlF1wxHoBrtfKzJ1nR8TGWWeH9NwXJtQ+qRzAhnQaHZyCZ6q4HvPlxxXOmgE+JuU6BCt6YPXAmNEMdMhkqYis4xSzxwWHvko79NnKY72pOIS2GgS6Xon0OxLOJ0mb66yhhZB4hUBb02CpvCMlKSLtvnS+2IcSGeSQBnwBw/wgp1uhr9ieUO/wY5K78w2kYFhR6Iet55gutbikSqDgxzTmuX3Mkjq0L/MVUIRAdmOysrR2Lxlk692IrNYTtUflQLsSfzrp6VQIKPxjfrdFhHIfbPoUdfMf+H06tfwkGONgcej56/fDjFbaHouZ357wcuwDsuMGNRCdyW7QyBXF/Wi28nPq/KSeOdCy+q9KDuOYsX9n/5Rsw== cardno:000614320136" ]; @@ -60,4 +69,22 @@ }; system.stateVersion = "23.11"; + + environment.systemPackages = with pkgs; [ + git + vim + tmux + htop + curl + jq + sqlite + tshark + ]; + + services.tailscale = { + enable = true; + openFirewall = true; + }; + + } diff --git a/flake.lock b/flake.lock index a7dd711..3949c33 100644 --- a/flake.lock +++ b/flake.lock @@ -27,12 +27,12 @@ }, "locked": { "lastModified": 1, - "narHash": "sha256-rGlEqK2S+aNGlWhMuq7nJXg8V/Re9uVaBHV37yj8L3Y=", - "path": "/nix/store/58w2chqxdjqzm1szhnsbigc1q7n9dgcd-source/backend", + "narHash": "sha256-obtaR0FNlq2s38K6rvA2vuKHd1yiGCb5aNqJvHWP9vg=", + "path": "/nix/store/199cbz8hwbc8bjrhqgprmzsjmb8s2vwi-source/backend", "type": "path" }, "original": { - "path": "/nix/store/58w2chqxdjqzm1szhnsbigc1q7n9dgcd-source/backend", + "path": "/nix/store/199cbz8hwbc8bjrhqgprmzsjmb8s2vwi-source/backend", "type": "path" } }, @@ -147,12 +147,12 @@ }, "locked": { "lastModified": 1, - "narHash": "sha256-QFo7rjJgUSiURfMfGGOCXJLDw/ZJGwtyRFR1jnHDpoE=", - "path": "/nix/store/58w2chqxdjqzm1szhnsbigc1q7n9dgcd-source/blog-static", + "narHash": "sha256-nn4Hi9ZFQKM1xl0y8ZkaCwN1CGxVRgFsBzJZS5jrJCY=", + "path": "/nix/store/199cbz8hwbc8bjrhqgprmzsjmb8s2vwi-source/blog-static", "type": "path" }, "original": { - "path": "/nix/store/58w2chqxdjqzm1szhnsbigc1q7n9dgcd-source/blog-static", + "path": "/nix/store/199cbz8hwbc8bjrhqgprmzsjmb8s2vwi-source/blog-static", "type": "path" } }, diff --git a/flake.nix b/flake.nix index eeb5f24..982118c 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,7 @@ { # Define a formatter package for the system to enable `nix fmt` formatter.${system} = pkgs.nixpkgs-fmt; - + # NixOS configuration for the 'blog' system nixosConfigurations.blog = nixpkgs.lib.nixosSystem { @@ -62,12 +62,14 @@ # It will include the packages specified in the buildInputs attribute # once the shell is entered using `nix develop` or direnv integration. devShell.${system} = pkgs.mkShell { - DATABASE_URL = "sqlite://db.sqlite"; + DATABASE_PATH = "./db.sqlite"; + DATABASE_URL = "sqlite://./db.sqlite"; buildInputs = with pkgs; [ opentofu # provisioning tool for the OpenTofu project ponysay # just for fun run `ponysay hello` hugo + sqlx-cli ]; }; diff --git a/integration.nix b/integration.nix index 5a408eb..e5e2faa 100644 --- a/integration.nix +++ b/integration.nix @@ -19,7 +19,7 @@ makeTest imports = [ sharedModule backend.nixosModules.x86_64-linux.default - static.nixosModules.x86_64-linux.default + static.nixosModules.x86_64-linux.default ]; networking.firewall = { enable = true;