Regrets Dot Pee Enn Gee (#2804)

Upgrade Axum

Co-authored-by: James Hodgkinson <james@terminaloutcomes.com>
This commit is contained in:
Firstyear 2024-05-30 12:50:45 +10:00 committed by GitHub
parent f669f5a0e8
commit 1e7b94b7cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 546 additions and 378 deletions

638
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -89,18 +89,16 @@ serde_with = "3.7.0"
argon2 = { version = "0.5.3", features = ["alloc"] } argon2 = { version = "0.5.3", features = ["alloc"] }
async-recursion = "1.1.0" async-recursion = "1.1.0"
async-trait = "^0.1.78" async-trait = "^0.1.78"
axum = { version = "0.6.20", features = [ axum = { version = "0.7.5", features = [
"form", "form",
"headers",
"http2",
"json", "json",
"macros", "macros",
"multipart", "multipart",
"original-uri", "original-uri",
"query", "query",
"tokio",
"tracing", "tracing",
] } ] }
axum-csp = { version = "0.0.5" }
base32 = "^0.4.0" base32 = "^0.4.0"
base64 = "^0.21.7" base64 = "^0.21.7"
base64urlsafedata = "0.5.0" base64urlsafedata = "0.5.0"
@ -129,9 +127,10 @@ gloo = "^0.8.1"
gloo-utils = "0.2.0" gloo-utils = "0.2.0"
hashbrown = { version = "0.14.3", features = ["serde", "inline-more", "ahash"] } hashbrown = { version = "0.14.3", features = ["serde", "inline-more", "ahash"] }
hex = "^0.4.3" hex = "^0.4.3"
http = "0.2.12" http = "1.1.0"
hyper = { version = "0.14.28", features = ["full"] } hyper = { version = "1.3.1", features = ["server", "client"] }
hyper-tls = "0.5.0" hyper-util = { version = "0.1.5", features = ["server", "tokio"] }
hyper-tls = "0.6.0"
idlset = "^0.2.4" idlset = "^0.2.4"
image = { version = "0.24.9", default-features = false, features = [ image = { version = "0.24.9", default-features = false, features = [
"gif", "gif",
@ -181,7 +180,7 @@ quote = "1"
rand = "^0.8.5" rand = "^0.8.5"
rand_chacha = "0.3.1" rand_chacha = "0.3.1"
regex = "1.10.3" regex = "1.10.3"
reqwest = { version = "0.11.26", default-features = false, features = [ reqwest = { version = "0.12.4", default-features = false, features = [
"cookies", "cookies",
"json", "json",
"gzip", "gzip",
@ -224,7 +223,7 @@ tracing-forest = "^0.1.6"
url = "^2.5.0" url = "^2.5.0"
urlencoding = "2.1.3" urlencoding = "2.1.3"
utoipa = "4.2.0" utoipa = "4.2.0"
utoipa-swagger-ui = "4.0.0" utoipa-swagger-ui = "6.0.0"
uuid = "^1.8.0" uuid = "^1.8.0"
wasm-bindgen = "^0.2.92" wasm-bindgen = "^0.2.92"

View file

@ -24,6 +24,8 @@ reqwest = { workspace = true, default-features = false, features = [
] } ] }
kanidm_proto = { workspace = true } kanidm_proto = { workspace = true }
kanidm_lib_file_permissions = { workspace = true } kanidm_lib_file_permissions = { workspace = true }
http = { workspace = true }
hyper = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
time = { workspace = true, features = ["serde", "std"] } time = { workspace = true, features = ["serde", "std"] }
@ -39,4 +41,4 @@ toml = { workspace = true }
uuid = { workspace = true, features = ["serde", "v4"] } uuid = { workspace = true, features = ["serde", "v4"] }
url = { workspace = true, features = ["serde"] } url = { workspace = true, features = ["serde"] }
webauthn-rs-proto = { workspace = true, features = ["wasm"] } webauthn-rs-proto = { workspace = true, features = ["wasm"] }
hyper = { workspace = true } # hyper = { workspace = true }

View file

@ -2032,9 +2032,9 @@ impl KanidmClient {
#[tokio::test] #[tokio::test]
async fn test_no_client_version_check_on_502() { async fn test_no_client_version_check_on_502() {
let res = reqwest::Response::from( let res = reqwest::Response::from(
hyper::Response::builder() http::Response::builder()
.status(StatusCode::GATEWAY_TIMEOUT) .status(StatusCode::GATEWAY_TIMEOUT)
.body(hyper::Body::empty()) .body("")
.unwrap(), .unwrap(),
); );
let client = KanidmClientBuilder::new() let client = KanidmClientBuilder::new()
@ -2045,9 +2045,9 @@ async fn test_no_client_version_check_on_502() {
client.expect_version(&res).await; client.expect_version(&res).await;
let res = reqwest::Response::from( let res = reqwest::Response::from(
hyper::Response::builder() http::Response::builder()
.status(StatusCode::BAD_GATEWAY) .status(StatusCode::BAD_GATEWAY)
.body(hyper::Body::empty()) .body("")
.unwrap(), .unwrap(),
); );
let client = KanidmClientBuilder::new() let client = KanidmClientBuilder::new()

View file

@ -19,10 +19,9 @@ doctest = false
async-trait = { workspace = true } async-trait = { workspace = true }
axum = { workspace = true } axum = { workspace = true }
axum-auth = "0.4.1" axum-auth = "0.4.1"
axum-csp = { workspace = true } axum-extra = { version = "0.9.3", features = ["cookie"] }
axum-extra = { version = "0.7.7", features = ["cookie"] } axum-macros = "0.4.1"
axum-macros = "0.3.8" axum-server = { version = "0.6.0", features = ["tls-openssl"] }
axum-server = { version = "0.5.1", features = ["tls-openssl"] }
bytes = { workspace = true } bytes = { workspace = true }
chrono = { workspace = true } chrono = { workspace = true }
compact_jwt = { workspace = true } compact_jwt = { workspace = true }
@ -33,6 +32,7 @@ futures-util = { workspace = true }
hashbrown = { workspace = true } hashbrown = { workspace = true }
http = { workspace = true } http = { workspace = true }
hyper = { workspace = true } hyper = { workspace = true }
hyper-util = { workspace = true }
kanidm_proto = { workspace = true } kanidm_proto = { workspace = true }
kanidm_utils_users = { workspace = true } kanidm_utils_users = { workspace = true }
kanidmd_lib = { workspace = true } kanidmd_lib = { workspace = true }
@ -53,7 +53,7 @@ tokio-openssl = { workspace = true }
tokio-util = { workspace = true, features = ["codec"] } tokio-util = { workspace = true, features = ["codec"] }
toml = { workspace = true } toml = { workspace = true }
tower = { version = "0.4.13", features = ["tokio-stream", "tracing"] } tower = { version = "0.4.13", features = ["tokio-stream", "tracing"] }
tower-http = { version = "0.4.4", features = [ tower-http = { version = "0.5.2", features = [
"compression-gzip", "compression-gzip",
"fs", "fs",
"tokio", "tokio",

View file

@ -5,12 +5,12 @@ use axum::{
http::{ http::{
header::HeaderName, header::AUTHORIZATION as AUTHORISATION, request::Parts, StatusCode, header::HeaderName, header::AUTHORIZATION as AUTHORISATION, request::Parts, StatusCode,
}, },
serve::IncomingStream,
RequestPartsExt, RequestPartsExt,
}; };
use axum_extra::extract::cookie::CookieJar; use axum_extra::extract::cookie::CookieJar;
use hyper::server::conn::AddrStream;
use kanidm_proto::constants::X_FORWARDED_FOR; use kanidm_proto::constants::X_FORWARDED_FOR;
use kanidm_proto::internal::COOKIE_BEARER_TOKEN; use kanidm_proto::internal::COOKIE_BEARER_TOKEN;
use kanidmd_lib::prelude::{ClientAuthInfo, ClientCertInfo, Source}; use kanidmd_lib::prelude::{ClientAuthInfo, ClientCertInfo, Source};
@ -192,8 +192,17 @@ impl Connected<ClientConnInfo> for ClientConnInfo {
} }
} }
impl<'a> Connected<&'a AddrStream> for ClientConnInfo { impl Connected<SocketAddr> for ClientConnInfo {
fn connect_info(target: &'a AddrStream) -> Self { fn connect_info(addr: SocketAddr) -> Self {
ClientConnInfo {
addr,
client_cert: None,
}
}
}
impl Connected<IncomingStream<'_>> for ClientConnInfo {
fn connect_info(target: IncomingStream<'_>) -> Self {
ClientConnInfo { ClientConnInfo {
addr: target.remote_addr(), addr: target.remote_addr(),
client_cert: None, client_cert: None,

View file

@ -1,16 +1,16 @@
use axum::{ use axum::{
headers::{CacheControl, HeaderMapExt}, body::Body,
http::{header, HeaderValue, Request}, http::{header, HeaderValue, Request},
middleware::Next, middleware::Next,
response::Response, response::Response,
}; };
/// Adds `no-cache max-age=0` to the response headers. /// Adds `no-cache max-age=0` to the response headers.
pub async fn dont_cache_me<B>(request: Request<B>, next: Next<B>) -> Response { pub async fn dont_cache_me(request: Request<Body>, next: Next) -> Response {
let mut response = next.run(request).await; let mut response = next.run(request).await;
response.headers_mut().insert( response.headers_mut().insert(
header::CACHE_CONTROL, header::CACHE_CONTROL,
HeaderValue::from_static("no-store no-cache max-age=0"), HeaderValue::from_static("no-store, no-cache, max-age=0"),
); );
response response
.headers_mut() .headers_mut()
@ -20,13 +20,12 @@ pub async fn dont_cache_me<B>(request: Request<B>, next: Next<B>) -> Response {
} }
/// Adds a cache control header of 300 seconds to the response headers. /// Adds a cache control header of 300 seconds to the response headers.
pub async fn cache_me<B>(request: Request<B>, next: Next<B>) -> Response { pub async fn cache_me(request: Request<Body>, next: Next) -> Response {
let mut response = next.run(request).await; let mut response = next.run(request).await;
let cache_header = CacheControl::new() response.headers_mut().insert(
.with_max_age(std::time::Duration::from_secs(300)) header::CACHE_CONTROL,
.with_private(); HeaderValue::from_static("private, max-age=300"),
);
response.headers_mut().typed_insert(cache_header);
response response
.headers_mut() .headers_mut()
.insert(header::PRAGMA, HeaderValue::from_static("no-cache")); .insert(header::PRAGMA, HeaderValue::from_static("no-cache"));

View file

@ -20,6 +20,7 @@
//! //!
use tower_http::compression::CompressionLayer; use tower_http::compression::CompressionLayer;
// TODO: this should skip compression on responses smaller than ~256 bytes because gzip can make them bigger. // TODO: this should skip compression on responses smaller than ~256 bytes because gzip can make them bigger.
/// This builds a compression layer with the following configuration: /// This builds a compression layer with the following configuration:
/// ///

View file

@ -1,10 +1,13 @@
use axum::http::{header, HeaderValue, Request}; use axum::{
use axum::middleware::Next; body::Body,
use axum::response::Response; http::{header, HeaderValue, Request},
middleware::Next,
response::Response,
};
const HSTS_HEADER: &str = "max-age=86400"; const HSTS_HEADER: &str = "max-age=86400";
pub async fn strict_transport_security_layer<B>(request: Request<B>, next: Next<B>) -> Response { pub async fn strict_transport_security_layer(request: Request<Body>, next: Next) -> Response {
// wait for the middleware to come back // wait for the middleware to come back
let mut response = next.run(request).await; let mut response = next.run(request).await;

View file

@ -1,4 +1,5 @@
use axum::{ use axum::{
body::Body,
http::{HeaderValue, Request}, http::{HeaderValue, Request},
middleware::Next, middleware::Next,
response::Response, response::Response,
@ -15,7 +16,7 @@ pub(crate) mod security_headers;
const KANIDM_VERSION: &str = env!("CARGO_PKG_VERSION"); const KANIDM_VERSION: &str = env!("CARGO_PKG_VERSION");
/// Injects a header into the response with "X-KANIDM-VERSION" matching the version of the package. /// Injects a header into the response with "X-KANIDM-VERSION" matching the version of the package.
pub async fn version_middleware<B>(request: Request<B>, next: Next<B>) -> Response { pub async fn version_middleware(request: Request<Body>, next: Next) -> Response {
let mut response = next.run(request).await; let mut response = next.run(request).await;
response response
.headers_mut() .headers_mut()
@ -26,7 +27,7 @@ pub async fn version_middleware<B>(request: Request<B>, next: Next<B>) -> Respon
#[cfg(any(test, debug_assertions))] #[cfg(any(test, debug_assertions))]
/// This is a debug middleware to ensure that /v1/ endpoints only return JSON /// This is a debug middleware to ensure that /v1/ endpoints only return JSON
#[instrument(level = "trace", name = "are_we_json_yet", skip_all)] #[instrument(level = "trace", name = "are_we_json_yet", skip_all)]
pub async fn are_we_json_yet<B>(request: Request<B>, next: Next<B>) -> Response { pub async fn are_we_json_yet(request: Request<Body>, next: Next) -> Response {
let uri = request.uri().path().to_string(); let uri = request.uri().path().to_string();
let response = next.run(request).await; let response = next.run(request).await;
@ -54,7 +55,7 @@ pub struct KOpId {
/// This runs at the start of the request, adding an extension with `KOpId` which has useful things inside it. /// This runs at the start of the request, adding an extension with `KOpId` which has useful things inside it.
#[instrument(level = "trace", name = "kopid_middleware", skip_all)] #[instrument(level = "trace", name = "kopid_middleware", skip_all)]
pub async fn kopid_middleware<B>(mut request: Request<B>, next: Next<B>) -> Response { pub async fn kopid_middleware(mut request: Request<Body>, next: Next) -> Response {
// generate the event ID // generate the event ID
let eventid = sketching::tracing_forest::id(); let eventid = sketching::tracing_forest::id();

View file

@ -1,19 +1,20 @@
use axum::extract::State; use axum::{
use axum::http::header; body::Body,
use axum::http::HeaderValue; extract::State,
use axum::http::Request; http::{header, HeaderValue, Request},
use axum::middleware::Next; middleware::Next,
use axum::response::Response; response::Response,
};
use crate::https::ServerState; use crate::https::ServerState;
const PERMISSIONS_POLICY_VALUE: &str = "fullscreen=(), geolocation=()"; const PERMISSIONS_POLICY_VALUE: &str = "fullscreen=(), geolocation=()";
const X_CONTENT_TYPE_OPTIONS_VALUE: &str = "nosniff"; const X_CONTENT_TYPE_OPTIONS_VALUE: &str = "nosniff";
pub async fn security_headers_layer<B>( pub async fn security_headers_layer(
State(state): State<ServerState>, State(state): State<ServerState>,
request: Request<B>, request: Request<Body>,
next: Next<B>, next: Next,
) -> Response { ) -> Response {
// wait for the middleware to come back // wait for the middleware to come back
let mut response = next.run(request).await; let mut response = next.run(request).await;

View file

@ -16,47 +16,48 @@ mod v1_scim;
use self::extractors::ClientConnInfo; use self::extractors::ClientConnInfo;
use self::javascript::*; use self::javascript::*;
use self::v1::SessionId;
use crate::actors::{QueryServerReadV1, QueryServerWriteV1}; use crate::actors::{QueryServerReadV1, QueryServerWriteV1};
use crate::config::{Configuration, ServerRole, TlsConfiguration}; use crate::config::{Configuration, ServerRole, TlsConfiguration};
use axum::extract::connect_info::IntoMakeServiceWithConnectInfo; use crate::CoreAction;
use axum::http::{HeaderMap, HeaderValue};
use axum::middleware::{from_fn, from_fn_with_state}; use axum::{
use axum::response::Redirect; body::Body,
use axum::routing::*; extract::connect_info::IntoMakeServiceWithConnectInfo,
use axum::Router; http::{HeaderMap, HeaderValue, Request},
use axum_csp::{CspDirectiveType, CspValue}; middleware::{from_fn, from_fn_with_state},
response::Redirect,
routing::*,
Router,
};
use axum_extra::extract::cookie::CookieJar; use axum_extra::extract::cookie::CookieJar;
use compact_jwt::{JwsCompact, JwsHs256Signer, JwsVerifier}; use compact_jwt::{JwsCompact, JwsHs256Signer, JwsVerifier};
use futures::pin_mut;
use hashbrown::HashMap; use hashbrown::HashMap;
use hyper::server::accept::Accept; use hyper::body::Incoming;
use hyper::server::conn::{AddrStream, Http}; use hyper_util::rt::{TokioExecutor, TokioIo};
use kanidm_proto::constants::KSESSIONID; use kanidm_proto::{constants::KSESSIONID, internal::COOKIE_AUTH_SESSION_ID};
use kanidm_proto::internal::COOKIE_AUTH_SESSION_ID; use kanidmd_lib::{idm::ClientCertInfo, status::StatusActor};
use kanidmd_lib::idm::ClientCertInfo;
use kanidmd_lib::status::StatusActor;
use openssl::nid; use openssl::nid;
use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod, SslSessionCacheMode, SslVerifyMode}; use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod, SslSessionCacheMode, SslVerifyMode};
use openssl::x509::X509; use openssl::x509::X509;
use sketching::*;
use tokio_openssl::SslStream;
use futures_util::future::poll_fn; use sketching::*;
use tokio::net::TcpListener; use tokio::{
net::{TcpListener, TcpStream},
sync::broadcast,
};
use tokio_openssl::SslStream;
use tower::Service;
use tower_http::{services::ServeDir, trace::TraceLayer};
use uuid::Uuid;
use std::fs; use std::fs;
use std::io::{ErrorKind, Read}; use std::io::{ErrorKind, Read};
use std::path::PathBuf; use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc;
use std::{net::SocketAddr, str::FromStr}; use std::{net::SocketAddr, str::FromStr};
use tokio::sync::broadcast;
use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer;
use uuid::Uuid;
use crate::CoreAction;
use self::v1::SessionId;
#[derive(Clone)] #[derive(Clone)]
pub struct ServerState { pub struct ServerState {
@ -213,34 +214,28 @@ pub async fn create_https_server(
.into_iter() .into_iter()
.map(|f| f.hash) .map(|f| f.hash)
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let mut js_directives: Vec<CspValue> = js_directives
.into_iter()
.map(|value| CspValue::Sha384 { value })
.collect();
js_directives.extend(vec![CspValue::UnsafeEval, CspValue::SelfSite]);
let csp_header = axum_csp::CspSetBuilder::new() let js_checksums: String = js_directives
// default-src 'self'; .iter()
.add(CspDirectiveType::DefaultSrc, vec![CspValue::SelfSite]) .map(|value| format!(" 'sha384-{}'", value))
// form-action https: 'self'; .collect();
.add(
CspDirectiveType::FormAction, let csp_header = format!(
vec![CspValue::SelfSite, CspValue::SchemeHttps], concat!(
) "base-uri 'self' https:; ",
// base-uri 'self'; "default-src 'self'; ",
.add( "form-action 'self' https:;",
CspDirectiveType::BaseUri, "frame-ancestors 'none'; ",
vec![CspValue::SelfSite, CspValue::SchemeHttps], "img-src 'self' data:; ",
) "worker-src 'none'; ",
// worker-src 'none'; "script-src 'self' 'unsafe-eval'{};"
.add(CspDirectiveType::WorkerSource, vec![CspValue::None]) ),
// frame-ancestors 'none' js_checksums
.add(CspDirectiveType::FrameAncestors, vec![CspValue::None]) );
.add(CspDirectiveType::ScriptSource, js_directives)
.add( let csp_header = HeaderValue::from_str(&csp_header).map_err(|err| {
CspDirectiveType::ImgSrc, error!(?err, "Unable to generate content security policy");
vec![CspValue::SelfSite, CspValue::SchemeData], })?;
);
let trust_x_forward_for = config.trust_x_forward_for; let trust_x_forward_for = config.trust_x_forward_for;
@ -251,7 +246,7 @@ pub async fn create_https_server(
jws_signer, jws_signer,
js_files, js_files,
trust_x_forward_for, trust_x_forward_for,
csp_header: csp_header.finish(), csp_header,
domain: config.domain.clone(), domain: config.domain.clone(),
secure_cookies: config.integration_test_config.is_none(), secure_cookies: config.integration_test_config.is_none(),
}; };
@ -537,23 +532,13 @@ async fn server_loop(
} }
let tls_acceptor = tls_builder.build(); let tls_acceptor = tls_builder.build();
pin_mut!(listener);
let protocol = Arc::new(Http::new());
let mut listener =
hyper::server::conn::AddrIncoming::from_listener(listener).map_err(|err| {
std::io::Error::new(
ErrorKind::Other,
format!("Failed to create listener: {:?}", err),
)
})?;
loop { loop {
if let Some(Ok(stream)) = poll_fn(|cx| Pin::new(&mut listener).poll_accept(cx)).await { if let Ok((stream, addr)) = listener.accept().await {
let tls_acceptor = tls_acceptor.clone(); let tls_acceptor = tls_acceptor.clone();
let app = app.clone(); let app = app.clone();
tokio::spawn(handle_conn(tls_acceptor, stream, app, addr));
// let svc = tower::MakeService::make_service(&mut app, &stream);
// tokio::spawn(handle_conn(tls_acceptor, stream, svc, protocol.clone()));
tokio::spawn(handle_conn(tls_acceptor, stream, app, protocol.clone()));
} }
} }
} }
@ -561,18 +546,15 @@ async fn server_loop(
/// This handles an individual connection. /// This handles an individual connection.
pub(crate) async fn handle_conn( pub(crate) async fn handle_conn(
acceptor: SslAcceptor, acceptor: SslAcceptor,
stream: AddrStream, stream: TcpStream,
// svc: ResponseFuture<Router, ClientConnInfo>,
mut app: IntoMakeServiceWithConnectInfo<Router, ClientConnInfo>, mut app: IntoMakeServiceWithConnectInfo<Router, ClientConnInfo>,
protocol: Arc<Http>, addr: SocketAddr,
) -> Result<(), std::io::Error> { ) -> Result<(), std::io::Error> {
let ssl = Ssl::new(acceptor.context()).map_err(|e| { let ssl = Ssl::new(acceptor.context()).map_err(|e| {
error!("Failed to create TLS context: {:?}", e); error!("Failed to create TLS context: {:?}", e);
std::io::Error::from(ErrorKind::ConnectionAborted) std::io::Error::from(ErrorKind::ConnectionAborted)
})?; })?;
let addr = stream.remote_addr();
let mut tls_stream = SslStream::new(ssl, stream).map_err(|e| { let mut tls_stream = SslStream::new(ssl, stream).map_err(|e| {
error!("Failed to create TLS stream: {:?}", e); error!("Failed to create TLS stream: {:?}", e);
std::io::Error::from(ErrorKind::ConnectionAborted) std::io::Error::from(ErrorKind::ConnectionAborted)
@ -611,15 +593,33 @@ pub(crate) async fn handle_conn(
debug!(?client_conn_info); debug!(?client_conn_info);
let svc = tower::MakeService::make_service(&mut app, client_conn_info); let svc = tower::MakeService::<ClientConnInfo, hyper::Request<Body>>::make_service(
&mut app,
client_conn_info,
);
let svc = svc.await.map_err(|e| { let svc = svc.await.map_err(|e| {
error!("Failed to build HTTP response: {:?}", e); error!("Failed to build HTTP response: {:?}", e);
std::io::Error::from(ErrorKind::Other) std::io::Error::from(ErrorKind::Other)
})?; })?;
protocol // Hyper has its own `AsyncRead` and `AsyncWrite` traits and doesn't use tokio.
.serve_connection(tls_stream, svc) // `TokioIo` converts between them.
let stream = TokioIo::new(tls_stream);
// Hyper also has its own `Service` trait and doesn't use tower. We can use
// `hyper::service::service_fn` to create a hyper `Service` that calls our app through
// `tower::Service::call`.
let hyper_service = hyper::service::service_fn(move |request: Request<Incoming>| {
// We have to clone `tower_service` because hyper's `Service` uses `&self` whereas
// tower's `Service` requires `&mut self`.
//
// We don't need to call `poll_ready` since `Router` is always ready.
svc.clone().call(request)
});
hyper_util::server::conn::auto::Builder::new(TokioExecutor::new())
.serve_connection_with_upgrades(stream, hyper_service)
.await .await
.map_err(|e| { .map_err(|e| {
debug!("Failed to complete connection: {:?}", e); debug!("Failed to complete connection: {:?}", e);

View file

@ -2,19 +2,21 @@ use super::errors::WebError;
use super::middleware::KOpId; use super::middleware::KOpId;
use super::ServerState; use super::ServerState;
use crate::https::extractors::VerifiedClientInformation; use crate::https::extractors::VerifiedClientInformation;
use axum::extract::{Path, Query, State}; use axum::{
use axum::http::header::{ body::Body,
ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE, LOCATION, extract::{Path, Query, State},
WWW_AUTHENTICATE, http::header::{
ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE, LOCATION,
WWW_AUTHENTICATE,
},
http::{HeaderValue, StatusCode},
middleware::from_fn,
response::{IntoResponse, Response},
routing::{get, post},
Extension, Form, Json, Router,
}; };
use axum::http::{HeaderValue, StatusCode};
use axum::middleware::from_fn;
use axum::response::{IntoResponse, Response};
use axum::routing::{get, post};
use axum::{Extension, Form, Json, Router};
use axum_macros::debug_handler; use axum_macros::debug_handler;
use compact_jwt::{JwkKeySet, OidcToken}; use compact_jwt::{JwkKeySet, OidcToken};
use hyper::Body;
use kanidm_proto::constants::uri::{ use kanidm_proto::constants::uri::{
OAUTH2_AUTHORISE, OAUTH2_AUTHORISE_PERMIT, OAUTH2_AUTHORISE_REJECT, OAUTH2_AUTHORISE, OAUTH2_AUTHORISE_PERMIT, OAUTH2_AUTHORISE_REJECT,
}; };

View file

@ -2846,7 +2846,7 @@ fn auth_session_state_management(
bearer_cookie.set_path("/"); bearer_cookie.set_path("/");
jar = jar jar = jar
.add(bearer_cookie) .add(bearer_cookie)
.remove(Cookie::named(COOKIE_AUTH_SESSION_ID)); .remove(Cookie::from(COOKIE_AUTH_SESSION_ID));
Ok(ProtoAuthState::Success(token_str)) Ok(ProtoAuthState::Success(token_str))
} }
} }

View file

@ -11,7 +11,6 @@ use axum::extract::{Path, State};
use axum::response::Html; use axum::response::Html;
use axum::routing::{get, post}; use axum::routing::{get, post};
use axum::{Extension, Json, Router}; use axum::{Extension, Json, Router};
use axum_auth::AuthBearer;
use kanidm_proto::scim_v1::{ScimSyncRequest, ScimSyncState}; use kanidm_proto::scim_v1::{ScimSyncRequest, ScimSyncState};
use kanidm_proto::v1::Entry as ProtoEntry; use kanidm_proto::v1::Entry as ProtoEntry;
use kanidmd_lib::prelude::*; use kanidmd_lib::prelude::*;
@ -247,10 +246,8 @@ async fn scim_sync_get(
State(state): State<ServerState>, State(state): State<ServerState>,
Extension(kopid): Extension<KOpId>, Extension(kopid): Extension<KOpId>,
VerifiedClientInformation(client_auth_info): VerifiedClientInformation, VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
AuthBearer(bearer): AuthBearer,
) -> Result<Json<ScimSyncState>, WebError> { ) -> Result<Json<ScimSyncState>, WebError> {
// Given the token, what is it's connected sync state? // Given the token, what is it's connected sync state?
trace!(?bearer);
state state
.qe_r_ref .qe_r_ref
.handle_scim_sync_status(client_auth_info, kopid.eventid) .handle_scim_sync_status(client_auth_info, kopid.eventid)