Skip to content

Commit dc28ae8

Browse files
committed
feat: commit
1 parent 4281217 commit dc28ae8

File tree

10 files changed

+146
-33
lines changed

10 files changed

+146
-33
lines changed

packages/cubejs-backend-native/Cargo.lock

+36-27
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cubejs-backend-native/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ findshlibs = "0.10.2"
2929
futures = "0.3.30"
3030
http-body-util = "0.1"
3131
axum = { version = "0.7.5", features = ["default", "ws"] }
32+
tower = "0.5.2"
3233
libc = "0.2"
3334
log = "0.4.21"
3435
log-reroute = "0.1"

packages/cubejs-backend-native/src/auth.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl GatewayAuthService for NodeBridgeAuthService {
145145
req: GatewayCheckAuthRequest,
146146
token: String,
147147
) -> Result<GatewayAuthenticateResponse, CubeError> {
148-
trace!("[sql auth] Request ->");
148+
trace!("[auth] Request ->");
149149

150150
let request_id = Uuid::new_v4().to_string();
151151

@@ -163,7 +163,7 @@ impl GatewayAuthService for NodeBridgeAuthService {
163163
Some(extra),
164164
)
165165
.await?;
166-
trace!("[sql auth] Request <- {:?}", response);
166+
trace!("[auth] Request <- {:?}", response);
167167

168168
Ok(GatewayAuthenticateResponse {
169169
context: Arc::new(NativeAuthContext {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::sync::Arc;
2+
use axum::extract::State;
3+
use axum::http::{header, HeaderMap, HeaderValue, Response, StatusCode};
4+
use axum::response::IntoResponse;
5+
use crate::gateway::{ApiGatewayState, GatewayAuthContextRef, GatewayAuthService, GatewayCheckAuthRequest};
6+
use crate::gateway::http_error::HttpError;
7+
8+
#[derive(Debug, Clone)]
9+
pub struct AuthExtension {
10+
auth_context: GatewayAuthContextRef,
11+
}
12+
13+
pub async fn gateway_auth_middleware(
14+
State(state): State<ApiGatewayState>,
15+
mut req: axum::extract::Request,
16+
next: axum::middleware::Next,
17+
) -> Result<impl IntoResponse, HttpError> {
18+
let Some(token_header_value) = req.headers().get("authorization") else {
19+
return Err(HttpError::unauthorized("No authorization header".to_string()));
20+
};
21+
22+
let auth = state
23+
.injector_ref()
24+
.get_service_typed::<dyn GatewayAuthService>()
25+
.await;
26+
27+
let auth_fut = auth.authenticate(
28+
GatewayCheckAuthRequest {
29+
protocol: "http".to_string(),
30+
},
31+
token_header_value.to_str()?.to_string()
32+
);
33+
34+
let auth_response = auth_fut.await.map_err(|err| {;
35+
HttpError::unauthorized("Authentication error".to_string())
36+
})?;
37+
38+
req.extensions_mut().insert(AuthExtension { auth_context: auth_response.context });
39+
40+
let response = next.run(req).await;
41+
Ok(response)
42+
}

packages/cubejs-backend-native/src/gateway/auth_service.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct GatewayAuthenticateResponse {
1919

2020
#[derive(Debug, Serialize)]
2121
pub struct GatewayCheckAuthRequest {
22-
protocol: String,
22+
pub(crate) protocol: String,
2323
}
2424

2525
#[async_trait]

packages/cubejs-backend-native/src/gateway/handlers/stream.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
use crate::gateway::ApiGatewayState;
1+
use crate::gateway::{ApiGatewayRouterBuilder, ApiGatewayState};
22
use axum::extract::State;
33
use axum::http::StatusCode;
4-
use axum::Json;
4+
use axum::{Extension, Json};
55
use serde::Serialize;
6+
use crate::gateway::auth_middleware::AuthExtension;
67

78
#[derive(Serialize)]
89
pub struct HandlerResponse {
910
message: String,
1011
}
1112

1213
pub async fn stream_handler_v2(
13-
State(_state): State<ApiGatewayState>,
14+
State(_gateway_state): State<ApiGatewayState>,
15+
Extension(_auth): Extension<AuthExtension>,
1416
) -> (StatusCode, Json<HandlerResponse>) {
1517
(
1618
StatusCode::NOT_IMPLEMENTED,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use axum::http::header::ToStrError;
2+
use axum::response::{IntoResponse, Response};
3+
4+
pub enum HttpErrorCode {
5+
NotFound,
6+
Unauthorized,
7+
InternalServerError,
8+
}
9+
10+
pub struct HttpError {
11+
code: HttpErrorCode,
12+
message: String,
13+
}
14+
15+
impl HttpError {
16+
pub fn unauthorized(message: String) -> HttpError {
17+
Self {
18+
code: HttpErrorCode::Unauthorized,
19+
message,
20+
}
21+
}
22+
23+
pub fn status_code(&self) -> axum::http::StatusCode {
24+
match self.code {
25+
HttpErrorCode::NotFound => axum::http::StatusCode::NOT_FOUND,
26+
HttpErrorCode::InternalServerError => axum::http::StatusCode::INTERNAL_SERVER_ERROR,
27+
HttpErrorCode::Unauthorized => axum::http::StatusCode::UNAUTHORIZED,
28+
}
29+
}
30+
}
31+
32+
impl IntoResponse for HttpError {
33+
fn into_response(self) -> Response {
34+
let status_code = self.status_code();
35+
36+
(status_code, status_code.canonical_reason().unwrap_or_default())
37+
.into_response()
38+
}
39+
}
40+
41+
impl From<ToStrError> for HttpError {
42+
fn from(value: ToStrError) -> Self {
43+
HttpError {
44+
code: HttpErrorCode::InternalServerError,
45+
message: value.to_string(),
46+
}
47+
}
48+
}

packages/cubejs-backend-native/src/gateway/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ pub mod handlers;
33
pub mod router;
44
pub mod server;
55
pub mod state;
6+
pub mod auth_middleware;
7+
pub mod http_error;
68

79
pub use auth_service::{
810
GatewayAuthContext, GatewayAuthContextRef, GatewayAuthService, GatewayAuthenticateResponse,
@@ -11,3 +13,4 @@ pub use auth_service::{
1113
pub use router::ApiGatewayRouterBuilder;
1214
pub use server::{ApiGatewayServer, ApiGatewayServerImpl};
1315
pub use state::ApiGatewayState;
16+
pub use auth_middleware::{gateway_auth_middleware};

packages/cubejs-backend-native/src/gateway/router.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::gateway::handlers::stream_handler_v2;
22
use crate::gateway::ApiGatewayState;
33
use axum::routing::{get, MethodRouter};
44
use axum::Router;
5+
use tower::ServiceBuilder;
56

67
#[derive(Debug, Clone)]
78
pub struct ApiGatewayRouterBuilder {

packages/cubejs-backend-native/src/gateway/server.rs

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use cubesql::CubeError;
66
use std::sync::Arc;
77
use tokio::net::TcpListener;
88
use tokio::sync::{watch, Mutex};
9+
use tower::ServiceBuilder;
910

1011
pub trait ApiGatewayServer: ProcessingLoop {}
1112

@@ -79,6 +80,12 @@ impl ProcessingLoop for ApiGatewayServerImpl {
7980
log::trace!("Shutdown signal received");
8081
};
8182

83+
let router = router.layer(
84+
ServiceBuilder::new()
85+
.layer(crate::gateway::auth_middleware::gateway_auth_middleware)
86+
.into_inner(),
87+
);
88+
8289
axum::serve(listener, router)
8390
.with_graceful_shutdown(shutdown_signal())
8491
.await

0 commit comments

Comments
 (0)