feat: added hmac validated proxy route
This commit is contained in:
parent
ff2570e961
commit
89f5b200a8
5 changed files with 39 additions and 2 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -4864,7 +4864,9 @@ version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"apb",
|
"apb",
|
||||||
"axum",
|
"axum",
|
||||||
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"hmac",
|
||||||
"httpsign",
|
"httpsign",
|
||||||
"jrd",
|
"jrd",
|
||||||
"mastodon-async-entities",
|
"mastodon-async-entities",
|
||||||
|
@ -4874,6 +4876,7 @@ dependencies = [
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"sha256",
|
"sha256",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
|
|
|
@ -68,6 +68,9 @@ pub struct SecurityConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub allow_public_debugger: bool,
|
pub allow_public_debugger: bool,
|
||||||
|
|
||||||
|
#[serde_inline_default("changeme".to_string())]
|
||||||
|
pub proxy_secret: String,
|
||||||
|
|
||||||
#[serde_inline_default(true)]
|
#[serde_inline_default(true)]
|
||||||
pub show_reply_ids: bool,
|
pub show_reply_ids: bool,
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,10 @@ readme = "README.md"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
sha256 = "1.5"
|
sha2 = "0.10"
|
||||||
|
sha256 = "1.5" # TODO ughhh
|
||||||
|
hmac = "0.12"
|
||||||
|
base64 = "0.22"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use apb::{LD, ActorMut, BaseMut, ObjectMut, PublicKeyMut};
|
use apb::{LD, ActorMut, BaseMut, ObjectMut, PublicKeyMut};
|
||||||
use axum::{extract::{Path, Query, State}, http::HeaderMap, response::{IntoResponse, Redirect, Response}, Form};
|
use axum::{extract::{Path, Query, State}, http::HeaderMap, response::{IntoResponse, Redirect, Response}, Form};
|
||||||
|
use hmac::{Hmac, Mac};
|
||||||
use reqwest::Method;
|
use reqwest::Method;
|
||||||
|
use base64::{engine::general_purpose::URL_SAFE, Engine as _};
|
||||||
use upub::{traits::Fetcher, Context};
|
use upub::{traits::Fetcher, Context};
|
||||||
|
|
||||||
use crate::{builders::JsonLD, AuthIdentity, Identity};
|
use crate::{builders::JsonLD, ApiError, AuthIdentity, Identity};
|
||||||
|
|
||||||
|
|
||||||
pub async fn view(
|
pub async fn view(
|
||||||
|
@ -74,6 +76,31 @@ pub async fn proxy_form(
|
||||||
proxy(ctx, query, auth).await
|
proxy(ctx, query, auth).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn proxy_hmac(
|
||||||
|
State(ctx): State<Context>,
|
||||||
|
AuthIdentity(auth): AuthIdentity,
|
||||||
|
Path(hmac): Path<String>,
|
||||||
|
Path(uri): Path<String>,
|
||||||
|
) -> crate::ApiResult<impl IntoResponse> {
|
||||||
|
let bytes = URL_SAFE.decode(hmac).map_err(|_| ApiError::bad_request())?;
|
||||||
|
let uri =
|
||||||
|
std::str::from_utf8(
|
||||||
|
&URL_SAFE.decode(uri).map_err(|_| ApiError::bad_request())?
|
||||||
|
)
|
||||||
|
.map_err(|_| ApiError::bad_request())?
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
type HmacSha256 = Hmac<sha2::Sha256>;
|
||||||
|
let mut mac = HmacSha256::new_from_slice(ctx.cfg().security.proxy_secret.as_bytes())
|
||||||
|
.map_err(|_| ApiError::internal_server_error())?;
|
||||||
|
|
||||||
|
mac.update(uri.as_bytes());
|
||||||
|
mac.verify_slice(&bytes)
|
||||||
|
.map_err(|_| ApiError::forbidden())?;
|
||||||
|
|
||||||
|
proxy(ctx, uri, auth).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn proxy(ctx: Context, query: String, auth: Identity) -> crate::ApiResult<impl IntoResponse> {
|
async fn proxy(ctx: Context, query: String, auth: Identity) -> crate::ApiResult<impl IntoResponse> {
|
||||||
// only local users can request fetches
|
// only local users can request fetches
|
||||||
if !ctx.cfg().security.allow_public_debugger && !auth.is_local() {
|
if !ctx.cfg().security.allow_public_debugger && !auth.is_local() {
|
||||||
|
|
|
@ -25,6 +25,7 @@ impl ActivityPubRouter for Router<upub::Context> {
|
||||||
.route("/proxy", post(ap::application::proxy_form))
|
.route("/proxy", post(ap::application::proxy_form))
|
||||||
.route("/proxy", get(ap::application::proxy_get))
|
.route("/proxy", get(ap::application::proxy_get))
|
||||||
.route("/proxy/:uri", get(ap::application::proxy_path))
|
.route("/proxy/:uri", get(ap::application::proxy_path))
|
||||||
|
.route("/proxy/:hmac/:uri", get(ap::application::proxy_hmac))
|
||||||
.route("/inbox", post(ap::inbox::post))
|
.route("/inbox", post(ap::inbox::post))
|
||||||
.route("/inbox", get(ap::inbox::get))
|
.route("/inbox", get(ap::inbox::get))
|
||||||
.route("/inbox/page", get(ap::inbox::page))
|
.route("/inbox/page", get(ap::inbox::page))
|
||||||
|
|
Loading…
Reference in a new issue