From 5f71827bf24a56f61f578e491c04176502fe3868 Mon Sep 17 00:00:00 2001 From: cduvray Date: Sat, 20 Jan 2024 14:28:07 +0100 Subject: [PATCH] chore: remove tonic temporarily (waiting hyperium/tonic/#1595) --- Cargo.lock | 216 ++-------------------------------- README.md | 4 +- jwt-authorizer/Cargo.toml | 6 - jwt-authorizer/src/error.rs | 49 -------- jwt-authorizer/tests/tonic.rs | 209 -------------------------------- 5 files changed, 11 insertions(+), 473 deletions(-) delete mode 100644 jwt-authorizer/tests/tonic.rs diff --git a/Cargo.lock b/Cargo.lock index d267178..49a0239 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,28 +68,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "async-trait" version = "0.1.73" @@ -107,34 +85,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.7.1" @@ -142,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "810a80b128d70e6ed2bdf3fe8ed72c0ae56f5f5948d01c2753282dd92a84fce8" dependencies = [ "async-trait", - "axum-core 0.4.0", + "axum-core", "bytes", "futures-util", "http 1.0.0", @@ -168,23 +118,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.9", - "http-body 0.4.5", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.0" @@ -381,7 +314,7 @@ name = "demo-server" version = "0.1.0" dependencies = [ "anyhow", - "axum 0.7.1", + "axum", "headers", "josekit", "jsonwebtoken", @@ -413,12 +346,6 @@ dependencies = [ "crypto-common", ] -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -813,7 +740,7 @@ dependencies = [ "http 0.2.9", "infer", "pin-project-lite", - "rand 0.7.3", + "rand", "serde", "serde_json", "serde_qs", @@ -891,18 +818,6 @@ dependencies = [ "tokio-rustls", ] -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper 0.14.27", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - [[package]] name = "hyper-tls" version = "0.5.0" @@ -1010,15 +925,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.9" @@ -1070,7 +976,7 @@ dependencies = [ name = "jwt-authorizer" version = "0.13.0" dependencies = [ - "axum 0.7.1", + "axum", "chrono", "futures-core", "futures-util", @@ -1081,14 +987,12 @@ dependencies = [ "jsonwebtoken", "lazy_static", "pin-project", - "prost", "reqwest", "serde", "serde_json", "thiserror", "time 0.3.28", "tokio", - "tonic", "tower", "tower-http", "tower-layer", @@ -1420,29 +1324,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8473a65b88506c106c28ae905ca4a2b83a2993640467a41bb3080627ddfd2c" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56075c27b20ae524d00f247b8a4dc333e5784f889fe63099f8e626bc8d73486c" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "quote" version = "1.0.33" @@ -1460,22 +1341,11 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", "rand_hc", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand_chacha" version = "0.2.2" @@ -1483,17 +1353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -1505,22 +1365,13 @@ dependencies = [ "getrandom 0.1.16", ] -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.10", -] - [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1", + "rand_core", ] [[package]] @@ -2062,16 +1913,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.1.0" @@ -2103,17 +1944,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.8" @@ -2128,33 +1958,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tonic" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5469afaf78a11265c343a88969045c1568aa8ecc6c787dbf756e92e70f199861" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.6.20", - "base64 0.21.3", - "bytes", - "h2 0.3.21", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.4.13" @@ -2163,11 +1966,8 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", - "slab", "tokio", "tokio-util", "tower-layer", diff --git a/README.md b/README.md index d8b8f7e..73e66ea 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ JWT authorizer Layer for Axum. [![Crates.io](https://img.shields.io/crates/v/jwt-authorizer)](https://crates.io/crates/jwt-authorizer) [![Documentation](https://docs.rs/jwt-authorizer/badge.svg)](https://docs.rs/jwt-authorizer) +> **Tonic support is temporarily removed** (waiting upgrade to hyper 1 and axum 0.7 hyperium/tonic/#1584) + ## Features - JWT token verification (Bearer) @@ -19,7 +21,7 @@ JWT authorizer Layer for Axum. - into custom deserializable structs or into `RegisteredClaims` (default) - Claims checker - Tracing support (error logging) -- *tonic* support +- ~~*tonic* support~~ ## Usage diff --git a/jwt-authorizer/Cargo.toml b/jwt-authorizer/Cargo.toml index 962bdb8..a7ca0e0 100644 --- a/jwt-authorizer/Cargo.toml +++ b/jwt-authorizer/Cargo.toml @@ -28,14 +28,12 @@ tower-layer = "0.3" tower-service = "0.3" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -tonic = { version = "0.10", optional = true } time = { version = "0.3", optional = true } http-body-util = "0.1.0" [dev-dependencies] hyper = { version = "1.0.1", features = ["full"] } lazy_static = "1.4.0" -prost = "0.12" tower = { version = "0.4", features = ["util", "buffer"] } wiremock = "0.5.19" @@ -51,7 +49,3 @@ rustls-tls-webpki-roots = ["reqwest/rustls-tls-webpki-roots"] rustls-tls-native-roots = ["reqwest/rustls-tls-native-roots"] time = ["dep:time"] chrono = ["dep:chrono"] - -[[test]] -name = "tonic" -required-features = ["tonic"] diff --git a/jwt-authorizer/src/error.rs b/jwt-authorizer/src/error.rs index 58ea29d..7b32364 100644 --- a/jwt-authorizer/src/error.rs +++ b/jwt-authorizer/src/error.rs @@ -84,55 +84,6 @@ fn response_500() -> Response { res } -#[cfg(feature = "tonic")] -impl From for Response { - fn from(e: AuthError) -> Self { - match e { - AuthError::JwksRefreshError(err) => { - tracing::error!("AuthErrors::JwksRefreshError: {}", err); - tonic::Status::internal("") - } - AuthError::InvalidKey(err) => { - tracing::error!("AuthErrors::InvalidKey: {}", err); - tonic::Status::internal("") - } - AuthError::JwksSerialisationError(err) => { - tracing::error!("AuthErrors::JwksSerialisationError: {}", err); - tonic::Status::internal("") - } - AuthError::InvalidKeyAlg(err) => { - debug!("AuthErrors::InvalidKeyAlg: {:?}", err); - tonic::Status::unauthenticated("error=\"invalid_token\", error_description=\"invalid key algorithm\"") - } - AuthError::InvalidKid(err) => { - debug!("AuthErrors::InvalidKid: {}", err); - tonic::Status::unauthenticated("error=\"invalid_token\", error_description=\"invalid kid\"") - } - AuthError::InvalidToken(err) => { - debug!("AuthErrors::InvalidToken: {}", err); - tonic::Status::unauthenticated("error=\"invalid_token\"") - } - AuthError::MissingToken() => { - debug!("AuthErrors::MissingToken"); - tonic::Status::unauthenticated("") - } - AuthError::InvalidClaims() => { - debug!("AuthErrors::InvalidClaims"); - tonic::Status::unauthenticated("error=\"insufficient_scope\"") - } - AuthError::NoAuthorizer() => { - debug!("AuthErrors::NoAuthorizer"); - tonic::Status::unauthenticated("error=\"invalid_token\"") - } - AuthError::NoAuthorizerLayer() => { - debug!("AuthErrors::NoAuthorizerLayer"); - tonic::Status::unauthenticated("error=\"no_authorizer_layer\"") - } - } - .to_http() - } -} - impl From for Response { fn from(e: AuthError) -> Self { e.into_response() diff --git a/jwt-authorizer/tests/tonic.rs b/jwt-authorizer/tests/tonic.rs deleted file mode 100644 index 9523762..0000000 --- a/jwt-authorizer/tests/tonic.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::{sync::Once, task::Poll}; - -use axum::body::HttpBody; -use futures_core::future::BoxFuture; -use http::header::AUTHORIZATION; -use jwt_authorizer::{layer::AuthorizationService, IntoLayer, JwtAuthorizer, Validation}; -use serde::{Deserialize, Serialize}; -use tonic::{server::UnaryService, transport::NamedService, IntoRequest, Status}; -use tower::{buffer::Buffer, Service}; - -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; - -use crate::common::{JWT_RSA1_OK, JWT_RSA2_OK}; - -mod common; - -/// Static variable to ensure that logging is only initialized once. -pub static INITIALIZED: Once = Once::new(); - -#[derive(Debug, Deserialize, Serialize, Clone)] -struct User { - sub: String, -} - -#[derive(prost::Message)] -struct HelloMessage { - #[prost(string, tag = "1")] - message: String, -} - -#[derive(Debug, Default, Clone)] -struct SayHelloMethod {} -impl UnaryService for SayHelloMethod { - type Response = HelloMessage; - type Future = BoxFuture<'static, Result, Status>>; - - fn call(&mut self, request: tonic::Request) -> Self::Future { - Box::pin(async move { - let hi = request.into_inner(); - let reply = HelloMessage { - message: format!("Hello, {}", hi.message), - }; - Ok(tonic::Response::new(reply)) - }) - } -} - -#[derive(Debug, Default, Clone)] -struct GreeterServer { - expected_sub: String, -} - -impl Service> for GreeterServer { - type Response = http::Response; - type Error = std::convert::Infallible; - type Future = BoxFuture<'static, Result>; - - fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> std::task::Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, req: http::Request) -> Self::Future { - let token = req.extensions().get::>().unwrap(); - assert_eq!(token.claims.sub, self.expected_sub); - match req.uri().path() { - "/hello/SayHello" => Box::pin(async move { - let mut grpc = tonic::server::Grpc::new(tonic::codec::ProstCodec::default()); - Ok(grpc.unary(SayHelloMethod::default(), req).await) - }), - p => { - let p = p.to_string(); - Box::pin(async move { Ok(Status::unimplemented(p).to_http()) }) - } - } - } -} - -impl NamedService for GreeterServer { - const NAME: &'static str = "hello"; -} - -async fn app( - jwt_auth: JwtAuthorizer, - expected_sub: String, -) -> AuthorizationService>, User> { - let layer = jwt_auth.build().await.unwrap().into_layer(); - tonic::transport::Server::builder() - .layer(layer) - .layer(tower::buffer::BufferLayer::new(1)) - .add_service(GreeterServer { expected_sub }) - .into_service() -} - -fn init_test() { - INITIALIZED.call_once(|| { - tracing_subscriber::registry() - .with(tracing_subscriber::EnvFilter::new( - std::env::var("RUST_LOG").unwrap_or_else(|_| "info,jwt-authorizer=debug,tower_http=debug".into()), - )) - .with(tracing_subscriber::fmt::layer()) - .init(); - }); -} - -// The grpc client produces a http request with a tonic boxbody that the transport is meant to sent out, while the server side -// expects to receive a http request with a hyper body.. This simple wrapper converts from one to -// the other. -struct GrpcWrapper -where - S: Service> + Clone, -{ - inner: S, -} - -impl Service> for GrpcWrapper -where - S: Service> + Clone + Send + 'static, - S::Future: Send, -{ - type Response = S::Response; - type Error = S::Error; - type Future = BoxFuture<'static, Result>; - - fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> Poll> { - self.inner.poll_ready(cx) - } - - fn call(&mut self, req: http::Request) -> Self::Future { - let inner = self.inner.clone(); - // take the service that was ready - let mut inner = std::mem::replace(&mut self.inner, inner); - Box::pin(async move { - let (parts, mut body) = req.into_parts(); - let mut data = Vec::new(); - while let Some(d) = body.data().await { - let d = d.unwrap(); - data.extend_from_slice(&d) - } - inner - .call(http::Request::from_parts(parts, axum::body::Body::from(data))) - .await - }) - } -} - -async fn make_protected_request( - app: AuthorizationService, - bearer: Option<&str>, - message: &str, -) -> Result, Status> -where - S: Service< - http::Request, - Response = http::Response, - Error = tower::BoxError, - > + Send - + 'static, - S::Future: Send, -{ - let mut grpc = tonic::client::Grpc::new(GrpcWrapper { inner: app }); - - let mut request = HelloMessage { - message: message.to_string(), - } - .into_request(); - - if let Some(bearer) = bearer { - let headers = request.metadata_mut(); - headers.insert(AUTHORIZATION.as_str(), format!("Bearer {bearer}").parse().unwrap()); - } - - grpc.ready().await.unwrap(); - grpc.unary( - request, - http::uri::PathAndQuery::from_static("/hello/SayHello"), - tonic::codec::ProstCodec::default(), - ) - .await -} - -#[tokio::test] -async fn successfull_auth() { - init_test(); - let auth: JwtAuthorizer = - JwtAuthorizer::from_rsa_pem("../config/rsa-public1.pem").validation(Validation::new().aud(&["aud1"])); - let app = app(auth, "b@b.com".to_string()).await; - let r = make_protected_request(app.clone(), Some(JWT_RSA1_OK), "world").await.unwrap(); - assert_eq!(r.get_ref().message, "Hello, world"); -} - -#[tokio::test] -async fn wrong_token() { - init_test(); - let auth: JwtAuthorizer = JwtAuthorizer::from_rsa_pem("../config/rsa-public1.pem"); - let app = app(auth, "b@b.com".to_string()).await; - let status = make_protected_request(app.clone(), Some(JWT_RSA2_OK), "world") - .await - .unwrap_err(); - assert_eq!(status.code(), tonic::Code::Unauthenticated); -} - -#[tokio::test] -async fn no_token() { - init_test(); - let auth: JwtAuthorizer = JwtAuthorizer::from_rsa_pem("../config/rsa-public1.pem"); - let app = app(auth, "b@b.com".to_string()).await; - let status = make_protected_request(app.clone(), None, "world").await.unwrap_err(); - assert_eq!(status.code(), tonic::Code::Unauthenticated); -}