diff --git a/Cargo.lock b/Cargo.lock index 667c1c0..0203f89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1127,20 +1127,6 @@ dependencies = [ "native-tls", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.30", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-rustls" version = "0.27.2" @@ -1151,10 +1137,10 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.12", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", ] @@ -1634,7 +1620,6 @@ dependencies = [ "getrandom 0.2.15", "http 0.2.12", "rand 0.8.5", - "reqwest 0.11.27", "serde", "serde_json", "serde_path_to_error", @@ -2202,7 +2187,6 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", - "hyper-rustls 0.24.2", "hyper-tls 0.5.0", "ipnet", "js-sys", @@ -2213,7 +2197,6 @@ dependencies = [ "once_cell", "percent-encoding 2.3.1", "pin-project-lite", - "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -2222,14 +2205,12 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.24.1", "tokio-socks", "tower-service", "url 2.5.2", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg 0.50.0", ] @@ -2249,7 +2230,7 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "hyper 1.4.1", - "hyper-rustls 0.27.2", + "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", "ipnet", @@ -2496,18 +2477,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log 0.4.22", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.12" @@ -2516,7 +2485,7 @@ checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "once_cell", "rustls-pki-types", - "rustls-webpki 0.102.6", + "rustls-webpki", "subtle", "zeroize", ] @@ -2546,16 +2515,6 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "rustls-webpki" version = "0.102.6" @@ -2609,16 +2568,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sec1" version = "0.7.3" @@ -3073,23 +3022,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.12", + "rustls", "rustls-pki-types", "tokio", ] @@ -3515,12 +3454,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "websocket" version = "0.18.0" diff --git a/apps/yourcloud/Cargo.toml b/apps/yourcloud/Cargo.toml index b8db58b..e539eac 100644 --- a/apps/yourcloud/Cargo.toml +++ b/apps/yourcloud/Cargo.toml @@ -15,11 +15,12 @@ reqwest-tracing = "0.5.0" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" serde_with = "3.7.0" -tokio = { workspace = true } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } urlencoding = "2.1.3" +openidconnect = { version = "3.5.0", default_features = false } + http_client = { workspace = true } discord_bot = { workspace = true } thiserror = { workspace = true } -openidconnect = "3.5.0" +tokio = { workspace = true } diff --git a/apps/yourcloud/examples/oidc.rs b/apps/yourcloud/examples/oidc.rs index 4911b38..0b9c41c 100644 --- a/apps/yourcloud/examples/oidc.rs +++ b/apps/yourcloud/examples/oidc.rs @@ -6,65 +6,58 @@ use color_eyre::{eyre::eyre, Result}; use openidconnect::core::{ CoreAuthenticationFlow, CoreClient, CoreProviderMetadata, CoreUserInfoClaims, }; -use openidconnect::AuthorizationCode; use openidconnect::{ AccessTokenHash, ClientId, CsrfToken, HttpResponse, IssuerUrl, Nonce, PkceCodeChallenge, RedirectUrl, Scope, }; +use openidconnect::{AuthorizationCode, PolicyUrl}; const ISSUER_URL: &str = "https://localhost:8443/oauth2/openid/yourcloud"; const CLIENT_ID: &str = "yourcloud"; const REDIRECT_URL: &str = "http://localhost:3000/oauth2/handler"; const SCOPES: [&str; 3] = ["read", "write", "email"]; -#[derive(Debug, Error)] -pub enum Error { - /// Error returned by reqwest crate. - #[error("request failed")] - Reqwest(#[source] reqwest::Error), - /// I/O error. - #[error("I/O error")] - Io(#[source] std::io::Error), - /// Other error. - #[error("Other error: {}", _0)] - Other(String), -} +use http_client::{Client, Error}; -fn http_client(request: openidconnect::HttpRequest) -> Result { - let client = reqwest::Client::builder() - // Following redirects opens the client up to SSRF vulnerabilities. - .redirect(Policy::none()) - .build() - .map_err(Error::Reqwest)?; +pub async fn async_http_client(request: openidconnect::HttpRequest) -> Result { + let builder = { + let mut builder = Client::builder(); + builder.client_builder = builder + .client_builder + .danger_accept_invalid_certs(true) // hitting localhost + .redirect(http_client::reqwest::redirect::Policy::none()); + builder + }; - let mut request_builder = client - .request(request.method, request.url.as_str()) + let mut request_builder = builder + .build()? + .build_request(request.method, request.url.as_str())? .body(request.body); for (name, value) in &request.headers { request_builder = request_builder.header(name.as_str(), value.as_bytes()); } - let mut response = client - .execute(request_builder.build().map_err(Error::Reqwest)?) - .map_err(Error::Reqwest)?; + let response = request_builder.send().await?; - let mut body = Vec::new(); - response.read_to_end(&mut body).map_err(Error::Io)?; - - { - Ok(HttpResponse { - status_code: response.status(), - headers: response.headers().to_owned(), - body, - }) - } + let status_code = response.status(); + let headers = response.headers().to_owned(); + let chunks = response.bytes().await.map_err(Error::Reqwest)?; + Ok(HttpResponse { + status_code, + headers, + body: chunks.to_vec(), + }) } -fn main() -> Result<()> { +#[tokio::main] +async fn main() -> Result<()> { // Use OpenID Connect Discovery to fetch the provider metadata. use openidconnect::{OAuth2TokenResponse, TokenResponse}; - let provider_metadata = - CoreProviderMetadata::discover(&IssuerUrl::new(ISSUER_URL.to_string())?, http_client)?; + let provider_metadata = CoreProviderMetadata::discover_async( + IssuerUrl::new(ISSUER_URL.to_string())?, + async_http_client, + ) + .await?; // Create an OpenID Connect client by specifying the client ID, client secret, authorization URL // and token URL. @@ -114,7 +107,8 @@ fn main() -> Result<()> { .exchange_code(AuthorizationCode::new(authorization_code)) // Set the PKCE code verifier. .set_pkce_verifier(pkce_verifier) - .request(http_client)?; + .request_async(async_http_client) + .await?; // Extract the ID token claims after verifying its authenticity and nonce. let id_token = token_response @@ -151,7 +145,8 @@ fn main() -> Result<()> { let userinfo: CoreUserInfoClaims = client .user_info(token_response.access_token().to_owned(), None) .map_err(|err| eyre!("No user info endpoint: {:?}", err))? - .request(http_client) + .request_async(async_http_client) + .await .map_err(|err| eyre!("Failed requesting user info: {:?}", err))?; println!("{:#?}", userinfo); diff --git a/config/kanidm/basic-setup.sh b/config/kanidm/basic-setup.sh index b7da44c..94103df 100755 --- a/config/kanidm/basic-setup.sh +++ b/config/kanidm/basic-setup.sh @@ -1,6 +1,8 @@ #!/usr/bin/env nix-shell #!nix-shell -i bash -p ripgrep oath-toolkit +set -euo pipefail + FAKE_PASSWORD="f0rTkN0x1s_cool" function kdrun { podman exec -it kanidm "$@" @@ -13,7 +15,7 @@ echo "admin password: $admin_password" echo "idm_admin password: $idm_password" # start a kanidm client in the background for an hour -podman kill kanidm-client || true +podman kill kanidm-client &>/dev/null || true sleep 0.2 podman run -itd --rm \ diff --git a/config/kanidm/run-in-podman.sh b/config/kanidm/run-in-podman.sh index 29964f9..6bdac1e 100755 --- a/config/kanidm/run-in-podman.sh +++ b/config/kanidm/run-in-podman.sh @@ -5,4 +5,4 @@ podman run -itd --rm \ -v "$PWD/chain.pem:/data/chain.pem:ro" \ -v "$PWD/key.pem:/data/key.pem:ro" \ --name kanidm \ - docker.io/kanidm/server:latest + docker.io/kanidm/server:latest &>/dev/null || true diff --git a/libs/http_client/src/lib.rs b/libs/http_client/src/lib.rs index 3fe3e71..0fe6aac 100644 --- a/libs/http_client/src/lib.rs +++ b/libs/http_client/src/lib.rs @@ -1,3 +1,4 @@ +pub use reqwest; pub use reqwest::header::{HeaderMap, HeaderValue}; pub use reqwest::{Body, ClientBuilder, Method, Response, Url}; pub use reqwest_middleware::ClientBuilder as MiddlewareClientBuilder; @@ -16,6 +17,8 @@ pub struct Client { } pub struct Builder { + pub client_builder: ClientBuilder, + // middleware_client_builder: MiddlewareClientBuilder, middleware: Option>>>, default_headers: Option, base_url: Option, @@ -33,6 +36,7 @@ impl Default for Builder { middleware.push(Arc::new(TracingMiddleware::default())); Builder { + client_builder: ClientBuilder::new(), name: None, base_url: None, default_headers: None, @@ -70,7 +74,7 @@ impl Builder { } pub fn build(mut self) -> Result { - let mut builder = reqwest::Client::builder(); + let mut builder = self.client_builder; if let Some(headers) = self.default_headers { builder = builder.default_headers(headers);