split csp into array; integrate error; cleanup type

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-14 05:11:58 +00:00
parent e4dc4a1ba5
commit 5ec49b3f62
3 changed files with 27 additions and 18 deletions

View file

@ -53,6 +53,8 @@ pub enum Error {
Path(#[from] axum::extract::rejection::PathRejection), Path(#[from] axum::extract::rejection::PathRejection),
#[error("{0}")] #[error("{0}")]
Http(#[from] http::Error), Http(#[from] http::Error),
#[error("{0}")]
HttpHeader(#[from] http::header::InvalidHeaderValue),
// ruma // ruma
#[error("{0}")] #[error("{0}")]

View file

@ -1,11 +1,11 @@
use std::{any::Any, io, sync::Arc, time::Duration}; use std::{any::Any, sync::Arc, time::Duration};
use axum::{ use axum::{
extract::{DefaultBodyLimit, MatchedPath}, extract::{DefaultBodyLimit, MatchedPath},
Router, Router,
}; };
use axum_client_ip::SecureClientIpSource; use axum_client_ip::SecureClientIpSource;
use conduit::Server; use conduit::{Result, Server};
use http::{ use http::{
header::{self, HeaderName}, header::{self, HeaderName},
HeaderValue, Method, StatusCode, HeaderValue, Method, StatusCode,
@ -22,11 +22,19 @@ use tracing::Level;
use crate::{request, router}; use crate::{request, router};
const CONDUWUIT_CSP: &str = "sandbox; default-src 'none'; font-src 'none'; script-src 'none'; frame-ancestors 'none'; \ const CONDUWUIT_CSP: &[&str] = &[
form-action 'none'; base-uri 'none';"; "sandbox",
const CONDUWUIT_PERMISSIONS_POLICY: &str = "interest-cohort=(),browsing-topics=()"; "default-src 'none'",
"font-src 'none'",
"script-src 'none'",
"frame-ancestors 'none'",
"form-action 'none'",
"base-uri 'none'",
];
pub(crate) fn build(server: &Arc<Server>) -> io::Result<Router> { const CONDUWUIT_PERMISSIONS_POLICY: &[&str] = &["interest-cohort=()", "browsing-topics=()"];
pub(crate) fn build(server: &Arc<Server>) -> Result<Router> {
let layers = ServiceBuilder::new(); let layers = ServiceBuilder::new();
#[cfg(feature = "sentry_telemetry")] #[cfg(feature = "sentry_telemetry")]
@ -65,11 +73,11 @@ pub(crate) fn build(server: &Arc<Server>) -> io::Result<Router> {
)) ))
.layer(SetResponseHeaderLayer::if_not_present( .layer(SetResponseHeaderLayer::if_not_present(
HeaderName::from_static("permissions-policy"), HeaderName::from_static("permissions-policy"),
HeaderValue::from_static(CONDUWUIT_PERMISSIONS_POLICY), HeaderValue::from_str(&CONDUWUIT_PERMISSIONS_POLICY.join(","))?,
)) ))
.layer(SetResponseHeaderLayer::if_not_present( .layer(SetResponseHeaderLayer::if_not_present(
header::CONTENT_SECURITY_POLICY, header::CONTENT_SECURITY_POLICY,
HeaderValue::from_static(CONDUWUIT_CSP), HeaderValue::from_str(&CONDUWUIT_CSP.join("; "))?,
)) ))
.layer(cors_layer(server)) .layer(cors_layer(server))
.layer(body_limit_layer(server)) .layer(body_limit_layer(server))

View file

@ -1,6 +1,9 @@
use std::sync::{atomic::Ordering, Arc}; use std::sync::{atomic::Ordering, Arc};
use axum::{extract::State, response::IntoResponse}; use axum::{
extract::State,
response::{IntoResponse, Response},
};
use conduit::{debug, debug_error, debug_warn, defer, error, trace, Error, Result, Server}; use conduit::{debug, debug_error, debug_warn, defer, error, trace, Error, Result, Server};
use http::{Method, StatusCode, Uri}; use http::{Method, StatusCode, Uri};
use ruma::api::client::error::{Error as RumaError, ErrorBody, ErrorKind}; use ruma::api::client::error::{Error as RumaError, ErrorBody, ErrorKind};
@ -8,7 +11,7 @@ use ruma::api::client::error::{Error as RumaError, ErrorBody, ErrorKind};
#[tracing::instrument(skip_all, level = "debug")] #[tracing::instrument(skip_all, level = "debug")]
pub(crate) async fn spawn( pub(crate) async fn spawn(
State(server): State<Arc<Server>>, req: http::Request<axum::body::Body>, next: axum::middleware::Next, State(server): State<Arc<Server>>, req: http::Request<axum::body::Body>, next: axum::middleware::Next,
) -> Result<axum::response::Response, StatusCode> { ) -> Result<Response, StatusCode> {
if !server.running() { if !server.running() {
debug_warn!("unavailable pending shutdown"); debug_warn!("unavailable pending shutdown");
return Err(StatusCode::SERVICE_UNAVAILABLE); return Err(StatusCode::SERVICE_UNAVAILABLE);
@ -30,7 +33,7 @@ pub(crate) async fn spawn(
#[tracing::instrument(skip_all, name = "handle")] #[tracing::instrument(skip_all, name = "handle")]
pub(crate) async fn handle( pub(crate) async fn handle(
State(server): State<Arc<Server>>, req: http::Request<axum::body::Body>, next: axum::middleware::Next, State(server): State<Arc<Server>>, req: http::Request<axum::body::Body>, next: axum::middleware::Next,
) -> Result<axum::response::Response, StatusCode> { ) -> Result<Response, StatusCode> {
if !server.running() { if !server.running() {
debug_warn!( debug_warn!(
method = %req.method(), method = %req.method(),
@ -57,9 +60,7 @@ pub(crate) async fn handle(
handle_result(&method, &uri, result) handle_result(&method, &uri, result)
} }
fn handle_result( fn handle_result(method: &Method, uri: &Uri, result: Response) -> Result<Response, StatusCode> {
method: &Method, uri: &Uri, result: axum::response::Response,
) -> Result<axum::response::Response, StatusCode> {
handle_result_log(method, uri, &result); handle_result_log(method, uri, &result);
match result.status() { match result.status() {
StatusCode::METHOD_NOT_ALLOWED => handle_result_405(method, uri, &result), StatusCode::METHOD_NOT_ALLOWED => handle_result_405(method, uri, &result),
@ -67,9 +68,7 @@ fn handle_result(
} }
} }
fn handle_result_405( fn handle_result_405(_method: &Method, _uri: &Uri, result: &Response) -> Result<Response, StatusCode> {
_method: &Method, _uri: &Uri, result: &axum::response::Response,
) -> Result<axum::response::Response, StatusCode> {
let error = Error::RumaError(RumaError { let error = Error::RumaError(RumaError {
status_code: result.status(), status_code: result.status(),
body: ErrorBody::Standard { body: ErrorBody::Standard {
@ -81,7 +80,7 @@ fn handle_result_405(
Ok(error.into_response()) Ok(error.into_response())
} }
fn handle_result_log(method: &Method, uri: &Uri, result: &axum::response::Response) { fn handle_result_log(method: &Method, uri: &Uri, result: &Response) {
let status = result.status(); let status = result.status();
let reason = status.canonical_reason().unwrap_or("Unknown Reason"); let reason = status.canonical_reason().unwrap_or("Unknown Reason");
let code = status.as_u16(); let code = status.as_u16();