diff --git a/quickwit/Cargo.lock b/quickwit/Cargo.lock index f1851bba250..5a90536790e 100644 --- a/quickwit/Cargo.lock +++ b/quickwit/Cargo.lock @@ -6559,6 +6559,7 @@ dependencies = [ "mockall", "once_cell", "ouroboros", + "quickwit-auth", "quickwit-common", "quickwit-config", "quickwit-doc-mapper", diff --git a/quickwit/Cargo.toml b/quickwit/Cargo.toml index 082748687a8..12bdd18eae4 100644 --- a/quickwit/Cargo.toml +++ b/quickwit/Cargo.toml @@ -36,7 +36,6 @@ members = [ "quickwit-serve", "quickwit-storage", "quickwit-telemetry", - "quickwit-telemetry", ] # The following list excludes `quickwit-metastore-utils` and `quickwit-lambda` diff --git a/quickwit/quickwit-auth/Cargo.toml b/quickwit/quickwit-auth/Cargo.toml new file mode 100644 index 00000000000..ea2013777c5 --- /dev/null +++ b/quickwit/quickwit-auth/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "quickwit-auth" +version.workspace = true +edition.workspace = true +homepage.workspace = true +documentation.workspace = true +repository.workspace = true +authors.workspace = true +license.workspace = true + +[dependencies] +biscuit-auth = { workspace = true, optional=true } +http = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +tonic = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } + +[features] +enterprise = ["biscuit-auth"] diff --git a/quickwit/quickwit-auth/src/community.rs b/quickwit/quickwit-auth/src/community.rs new file mode 100644 index 00000000000..7be01328fde --- /dev/null +++ b/quickwit/quickwit-auth/src/community.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2024 Quickwit, Inc. +// +// Quickwit is offered under the AGPL v3.0 and as commercial software. +// For commercial licensing, contact us at hello@quickwit.io. +// +// AGPL: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use std::future::Future; + +use crate::AuthorizationError; + +pub type AuthorizationToken = (); + +pub trait Authorization { + fn attenuate( + &self, + _auth_token: AuthorizationToken, + ) -> Result { + Ok(()) + } +} + +impl Authorization for T {} + +pub trait StreamAuthorization { + fn attenuate( + _auth_token: AuthorizationToken, + ) -> std::result::Result { + Ok(()) + } +} + +impl StreamAuthorization for T {} + +pub fn get_auth_token( + _req_metadata: &tonic::metadata::MetadataMap, +) -> Result { + Ok(()) +} + +pub fn set_auth_token( + _auth_token: &AuthorizationToken, + _req_metadata: &mut tonic::metadata::MetadataMap, +) { +} + +pub fn authorize( + _req: &R, + _auth_token: &AuthorizationToken, +) -> Result<(), AuthorizationError> { + Ok(()) +} + +pub fn build_tonic_stream_request_with_auth_token( + req: R, +) -> Result, AuthorizationError> { + Ok(tonic::Request::new(req)) +} + +pub fn build_tonic_request_with_auth_token( + req: R, +) -> Result, AuthorizationError> { + Ok(tonic::Request::new(req)) +} + +pub fn authorize_stream( + _auth_token: &AuthorizationToken, +) -> Result<(), AuthorizationError> { + Ok(()) +} + +pub fn execute_with_authorization(_: AuthorizationToken, f: F) -> impl Future +where F: Future { + f +} diff --git a/quickwit/quickwit-auth/src/enterprise.rs b/quickwit/quickwit-auth/src/enterprise.rs new file mode 100644 index 00000000000..fd81ab73e49 --- /dev/null +++ b/quickwit/quickwit-auth/src/enterprise.rs @@ -0,0 +1,262 @@ +// The Quickwit Enterprise Edition (EE) license +// Copyright (c) 2024-present Quickwit Inc. +// +// With regard to the Quickwit Software: +// +// This software and associated documentation files (the "Software") may only be +// used in production, if you (and any entity that you represent) hold a valid +// Quickwit Enterprise license corresponding to your usage. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// For all third party components incorporated into the Quickwit Software, those +// components are licensed under the original license provided by the owner of the +// applicable component. + +use std::future::Future; +use std::str::FromStr; +use std::sync::{Arc, OnceLock}; + +use biscuit_auth::macros::authorizer; +use biscuit_auth::{Authorizer, Biscuit, RootKeyProvider}; + +use crate::AuthorizationError; + +pub struct AuthorizationToken(Biscuit); + +impl AuthorizationToken { + pub fn into_biscuit(self) -> Biscuit { + self.0 + } +} + +impl From for AuthorizationToken { + fn from(biscuit: Biscuit) -> Self { + AuthorizationToken(biscuit) + } +} + +impl std::fmt::Display for AuthorizationToken { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl std::fmt::Debug for AuthorizationToken { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "AuthorizationToken({})", &self.0) + } +} + +static ROOT_KEY_PROVIDER: OnceLock> = OnceLock::new(); + +pub fn set_root_key_provider(key_provider: Arc) { + if ROOT_KEY_PROVIDER.set(key_provider).is_err() { + tracing::error!("root key provider was already initialized"); + } +} + +fn get_root_key_provider() -> Arc { + ROOT_KEY_PROVIDER + .get() + .expect("root key provider should have been initialized beforehand") + .clone() +} + +impl FromStr for AuthorizationToken { + type Err = AuthorizationError; + + fn from_str(token_base64: &str) -> Result { + let root_key_provider = get_root_key_provider(); + let biscuit = Biscuit::from_base64(token_base64, root_key_provider)?; + Ok(AuthorizationToken(biscuit)) + } +} + +tokio::task_local! { + pub static AUTHORIZATION_TOKEN: AuthorizationToken; +} + +const AUTHORIZATION_VALUE_PREFIX: &str = "Bearer "; + +fn default_operation_authorizer( + auth_token: &AuthorizationToken, +) -> Result { + let request_type = std::any::type_name::(); + let operation: &str = request_type.strip_suffix("Request").unwrap(); + let mut authorizer: Authorizer = authorizer!( + r#" + operation({operation}); + + // We generate the actual user role, by doing an union of the rights granted via roles. + user_right($operation) <- role($role), right($role, $operation); + user_right($operation, $resource) <- role($role), right($role, $operation, $resource); + user_right($operation) <- role("root"), operation($operation); + user_right($operation, $resource) <- role("root"), operation($operation), resource($resource); + + // Finally we check that we have access to index1 and index2. + check all operation($operation), right($operation); + + allow if true; + "# + ); + authorizer.set_time(); + authorizer.add_token(&auth_token.0)?; + Ok(authorizer) +} + +pub trait Authorization { + fn attenuate( + &self, + auth_token: AuthorizationToken, + ) -> Result { + Ok(auth_token) + } + + fn authorizer( + &self, + auth_token: &AuthorizationToken, + ) -> Result { + default_operation_authorizer::(auth_token) + } +} + +pub trait StreamAuthorization { + fn attenuate( + auth_token: AuthorizationToken, + ) -> std::result::Result { + Ok(auth_token) + } + fn authorizer( + auth_token: &AuthorizationToken, + ) -> std::result::Result { + default_operation_authorizer::(&auth_token) + } +} + +impl From for AuthorizationError { + fn from(_token_error: biscuit_auth::error::Token) -> AuthorizationError { + AuthorizationError::InvalidToken + } +} + +pub fn get_auth_token( + req_metadata: &tonic::metadata::MetadataMap, +) -> Result { + let authorization_header_value: &str = req_metadata + .get(http::header::AUTHORIZATION.as_str()) + .ok_or(AuthorizationError::AuthorizationTokenMissing)? + .to_str() + .map_err(|_| AuthorizationError::InvalidToken)?; + let authorization_token_str: &str = authorization_header_value + .strip_prefix(AUTHORIZATION_VALUE_PREFIX) + .ok_or(AuthorizationError::InvalidToken)?; + let biscuit: Biscuit = Biscuit::from_base64(authorization_token_str, get_root_key_provider())?; + Ok(AuthorizationToken(biscuit)) +} + +pub fn set_auth_token( + auth_token: &AuthorizationToken, + req_metadata: &mut tonic::metadata::MetadataMap, +) { + let authorization_header_value = format!("{AUTHORIZATION_VALUE_PREFIX}{auth_token}"); + req_metadata.insert( + http::header::AUTHORIZATION.as_str(), + authorization_header_value.parse().unwrap(), + ); +} + +pub fn authorize( + req: &R, + auth_token: &AuthorizationToken, +) -> Result<(), AuthorizationError> { + let mut authorizer = req.authorizer(auth_token)?; + authorizer.add_token(&auth_token.0)?; + authorizer.authorize()?; + Ok(()) +} + +pub fn build_tonic_stream_request_with_auth_token( + req: R, +) -> Result, AuthorizationError> { + AUTHORIZATION_TOKEN + .try_with(|token| { + let mut request = tonic::Request::new(req); + set_auth_token(token, request.metadata_mut()); + Ok(request) + }) + .unwrap_or(Err(AuthorizationError::AuthorizationTokenMissing)) +} + +pub fn build_tonic_request_with_auth_token( + req: R, +) -> Result, AuthorizationError> { + AUTHORIZATION_TOKEN + .try_with(|token| { + let mut request = tonic::Request::new(req); + set_auth_token(token, request.metadata_mut()); + Ok(request) + }) + .unwrap_or(Err(AuthorizationError::AuthorizationTokenMissing)) +} + +pub fn authorize_stream( + auth_token: &AuthorizationToken, +) -> Result<(), AuthorizationError> { + let mut authorizer = R::authorizer(auth_token)?; + authorizer.add_token(&auth_token.0)?; + authorizer.authorize()?; + Ok(()) +} + +pub fn execute_with_authorization( + token: AuthorizationToken, + f: F, +) -> impl Future +where + F: Future, +{ + AUTHORIZATION_TOKEN.scope(token, f) +} + +#[cfg(test)] +mod tests { + use super::*; + + // #[test] + // fn test_auth_token() { + // let mut req_metadata = tonic::metadata::MetadataMap::new(); + // let token = + // let auth_token = "test_token".to_string(); + // set_auth_token(&auth_token, &mut req_metadata); + // let auth_token_retrieved = get_auth_token(&req_metadata).unwrap(); + // assert_eq!(auth_token_retrieved, auth_token); + // } + + #[test] + fn test_auth_token_missing() { + let req_metadata = tonic::metadata::MetadataMap::new(); + let missing_error = get_auth_token(&req_metadata).unwrap_err(); + assert!(matches!( + missing_error, + AuthorizationError::AuthorizationTokenMissing + )); + } + + #[test] + fn test_auth_token_invalid() { + let mut req_metadata = tonic::metadata::MetadataMap::new(); + req_metadata.insert( + http::header::AUTHORIZATION.as_str(), + "some_token".parse().unwrap(), + ); + let missing_error = get_auth_token(&req_metadata).unwrap_err(); + assert!(matches!(missing_error, AuthorizationError::InvalidToken)); + } +} diff --git a/quickwit/quickwit-auth/src/lib.rs b/quickwit/quickwit-auth/src/lib.rs new file mode 100644 index 00000000000..cccaf68989a --- /dev/null +++ b/quickwit/quickwit-auth/src/lib.rs @@ -0,0 +1,56 @@ +// Copyright (C) 2024 Quickwit, Inc. +// +// Quickwit is offered under the AGPL v3.0 and as commercial software. +// For commercial licensing, contact us at hello@quickwit.io. +// +// AGPL: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use serde::{Deserialize, Serialize}; + +#[cfg(not(feature = "enterprise"))] +#[path = "community.rs"] +mod implementation; + +#[cfg(feature = "enterprise")] +#[path = "enterprise.rs"] +mod implementation; + +pub use implementation::*; + +#[derive(thiserror::Error, Debug, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)] +pub enum AuthorizationError { + #[error("authorization token missing")] + AuthorizationTokenMissing, + #[error("invalid token")] + InvalidToken, + #[error("permission denied")] + PermissionDenied, +} + +impl From for tonic::Status { + fn from(authorization_error: AuthorizationError) -> tonic::Status { + match authorization_error { + AuthorizationError::AuthorizationTokenMissing => { + tonic::Status::unauthenticated("Authorization token missing") + } + AuthorizationError::InvalidToken => { + tonic::Status::unauthenticated("Invalid authorization token") + } + AuthorizationError::PermissionDenied => { + tonic::Status::permission_denied("Permission denied") + } + } + } +} diff --git a/quickwit/quickwit-cli/Cargo.toml b/quickwit/quickwit-cli/Cargo.toml index 6542536aca1..64bf88dabda 100644 --- a/quickwit/quickwit-cli/Cargo.toml +++ b/quickwit/quickwit-cli/Cargo.toml @@ -79,7 +79,7 @@ quickwit-metastore = { workspace = true, features = ["testsuite"] } quickwit-storage = { workspace = true, features = ["testsuite"] } [features] -enterprise = ["quickwit-config/enterprise"] +enterprise = ["quickwit-config/enterprise", "quickwit-ingest/enterprise", "quickwit-proto/enterprise"] jemalloc = ["dep:tikv-jemalloc-ctl", "dep:tikv-jemallocator"] ci-test = [] pprof = ["quickwit-serve/pprof"] diff --git a/quickwit/quickwit-codegen/example/Cargo.toml b/quickwit/quickwit-codegen/example/Cargo.toml index 69617d20d8f..f678d0cadc2 100644 --- a/quickwit/quickwit-codegen/example/Cargo.toml +++ b/quickwit/quickwit-codegen/example/Cargo.toml @@ -41,3 +41,4 @@ quickwit-codegen = { workspace = true } [features] testsuite = ["mockall"] +enterprise = [ "quickwit-auth/enterprise" ] diff --git a/quickwit/quickwit-codegen/example/src/authorization.rs b/quickwit/quickwit-codegen/example/src/authorization.rs index fa4e0bf0f3d..b58c6bea026 100644 --- a/quickwit/quickwit-codegen/example/src/authorization.rs +++ b/quickwit/quickwit-codegen/example/src/authorization.rs @@ -1,26 +1,46 @@ -use quickwit_auth::Authorization; -use quickwit_auth::AuthorizationError; -use quickwit_auth::AuthorizationToken; -use quickwit_auth::StreamAuthorization; +// The Quickwit Enterprise Edition (EE) license +// Copyright (c) 2024-present Quickwit Inc. +// +// With regard to the Quickwit Software: +// +// This software and associated documentation files (the "Software") may only be +// used in production, if you (and any entity that you represent) hold a valid +// Quickwit Enterprise license corresponding to your usage. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -use crate::GoodbyeRequest; -use crate::HelloRequest; -use crate::PingRequest; +use quickwit_auth::{Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization}; + +use crate::{GoodbyeRequest, HelloRequest, PingRequest}; impl Authorization for HelloRequest { - fn attenuate(&self, auth_token: quickwit_auth::AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: quickwit_auth::AuthorizationToken, + ) -> Result { Ok(auth_token) } } impl Authorization for GoodbyeRequest { - fn attenuate(&self, auth_token: quickwit_auth::AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: quickwit_auth::AuthorizationToken, + ) -> Result { Ok(auth_token) } } impl StreamAuthorization for PingRequest { - fn attenuate(auth_token: quickwit_auth::AuthorizationToken) -> Result { + fn attenuate( + auth_token: quickwit_auth::AuthorizationToken, + ) -> Result { Ok(auth_token) } } diff --git a/quickwit/quickwit-codegen/example/src/codegen/hello.rs b/quickwit/quickwit-codegen/example/src/codegen/hello.rs index 38dee0dc214..83b8cb40bb0 100644 --- a/quickwit/quickwit-codegen/example/src/codegen/hello.rs +++ b/quickwit/quickwit-codegen/example/src/codegen/hello.rs @@ -723,9 +723,10 @@ where T::Future: Send, { async fn hello(&self, request: HelloRequest) -> crate::HelloResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .hello(request) + .hello(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -737,9 +738,10 @@ where &self, request: GoodbyeRequest, ) -> crate::HelloResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .goodbye(request) + .goodbye(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -751,9 +753,12 @@ where &self, request: quickwit_common::ServiceStream, ) -> crate::HelloResult> { + let tonic_request = quickwit_auth::build_tonic_stream_request_with_auth_token( + request, + )?; self.inner .clone() - .ping(request) + .ping(tonic_request) .await .map(|response| { let streaming: tonic::Streaming<_> = response.into_inner(); @@ -806,13 +811,9 @@ impl hello_grpc_server::HelloGrpc for HelloGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.hello(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.hello(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -822,13 +823,9 @@ impl hello_grpc_server::HelloGrpc for HelloGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.goodbye(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.goodbye(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -844,8 +841,7 @@ impl hello_grpc_server::HelloGrpc for HelloGrpcServerAdapter { quickwit_common::ServiceStream::from(streaming) }; quickwit_auth::authorize_stream::(&auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.ping(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.ping(req)) .await .map(|stream| tonic::Response::new( stream.map_err(crate::error::grpc_error_to_grpc_status), diff --git a/quickwit/quickwit-codegen/example/src/error.rs b/quickwit/quickwit-codegen/example/src/error.rs index ab35bf53dd9..9d3a9dbde19 100644 --- a/quickwit/quickwit-codegen/example/src/error.rs +++ b/quickwit/quickwit-codegen/example/src/error.rs @@ -20,6 +20,7 @@ use std::fmt; use quickwit_actors::AskError; +use quickwit_auth::AuthorizationError; use quickwit_proto::error::GrpcServiceError; pub use quickwit_proto::error::{grpc_error_to_grpc_status, grpc_status_to_service_error}; use quickwit_proto::{ServiceError, ServiceErrorCode}; @@ -38,6 +39,8 @@ pub enum HelloError { TooManyRequests, #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] AuthorizationError), } impl ServiceError for HelloError { @@ -48,6 +51,7 @@ impl ServiceError for HelloError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(_) => ServiceErrorCode::Unauthorized, } } } diff --git a/quickwit/quickwit-codegen/example/src/lib.rs b/quickwit/quickwit-codegen/example/src/lib.rs index 6ff2bd41fac..7e4da88ed55 100644 --- a/quickwit/quickwit-codegen/example/src/lib.rs +++ b/quickwit/quickwit-codegen/example/src/lib.rs @@ -19,9 +19,11 @@ mod error; +#[cfg(feature = "enterprise")] +mod authorization; + #[path = "codegen/hello.rs"] mod hello; -mod authorization; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; diff --git a/quickwit/quickwit-codegen/src/codegen.rs b/quickwit/quickwit-codegen/src/codegen.rs index 198ab048b14..26d284e54ba 100644 --- a/quickwit/quickwit-codegen/src/codegen.rs +++ b/quickwit/quickwit-codegen/src/codegen.rs @@ -1167,14 +1167,29 @@ fn generate_grpc_client_adapter_methods(context: &CodegenContext) -> TokenStream } else { quote! { |response| response.into_inner() } }; - let method = quote! { - async fn #method_name(&self, request: #request_type) -> #result_type<#response_type> { - self.inner + let method = if syn_method.client_streaming { + quote! { + async fn #method_name(&self, request: #request_type) -> #result_type<#response_type> { + let tonic_request = quickwit_auth::build_tonic_stream_request_with_auth_token(request)?; + self.inner .clone() - .#method_name(request) + .#method_name(tonic_request) .await .map(#into_response_type) .map_err(|status| crate::error::grpc_status_to_service_error(status, #rpc_name)) + } + } + } else { + quote! { + async fn #method_name(&self, request: #request_type) -> #result_type<#response_type> { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; + self.inner + .clone() + .#method_name(tonic_request) + .await + .map(#into_response_type) + .map_err(|status| crate::error::grpc_status_to_service_error(status, #rpc_name)) + } } }; stream.extend(method); @@ -1232,10 +1247,7 @@ fn generate_grpc_server_adapter_methods(context: &CodegenContext) -> TokenStream } } else { quote! { - { - let req = request.into_inner(); - req - } + request.into_inner() } }; let response_type = if syn_method.server_streaming { @@ -1276,7 +1288,7 @@ fn generate_grpc_server_adapter_methods(context: &CodegenContext) -> TokenStream let auth_token = quickwit_auth::get_auth_token(request.metadata())?; let req = #method_arg; #authorize_block; - quickwit_auth::AUTHORIZATION_TOKEN.scope(auth_token, self.inner.0.#method_name(req)).await + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.#method_name(req)).await .map(#into_response_type) .map_err(crate::error::grpc_error_to_grpc_status) } @@ -1286,8 +1298,6 @@ fn generate_grpc_server_adapter_methods(context: &CodegenContext) -> TokenStream stream } - - /// A [`ServiceGenerator`] wrapper that appends a suffix to the name of the wrapped service. It is /// used to add a `Grpc` suffix to the service, client, and server generated by tonic. struct WithSuffixServiceGenerator { diff --git a/quickwit/quickwit-ingest/Cargo.toml b/quickwit/quickwit-ingest/Cargo.toml index 3577addff50..2fdb7195555 100644 --- a/quickwit/quickwit-ingest/Cargo.toml +++ b/quickwit/quickwit-ingest/Cargo.toml @@ -63,3 +63,4 @@ quickwit-codegen = { workspace = true } failpoints = ["fail/failpoints"] no-failpoints = [] testsuite = ["mockall"] +enterprise = ["quickwit-auth/enterprise"] diff --git a/quickwit/quickwit-ingest/src/authorize.rs b/quickwit/quickwit-ingest/src/authorize.rs index c739f2adb1a..8b1b9287ce0 100644 --- a/quickwit/quickwit-ingest/src/authorize.rs +++ b/quickwit/quickwit-ingest/src/authorize.rs @@ -1,25 +1,47 @@ -use quickwit_auth::Authorization; -use quickwit_auth::AuthorizationError; -use quickwit_auth::AuthorizationToken; +// The Quickwit Enterprise Edition (EE) license +// Copyright (c) 2024-present Quickwit Inc. +// +// With regard to the Quickwit Software: +// +// This software and associated documentation files (the "Software") may only be +// used in production, if you (and any entity that you represent) hold a valid +// Quickwit Enterprise license corresponding to your usage. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. -use crate::FetchRequest; -use crate::IngestRequest; -use crate::TailRequest; +use quickwit_auth::{Authorization, AuthorizationError, AuthorizationToken}; + +use crate::{FetchRequest, IngestRequest, TailRequest}; impl Authorization for TailRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: AuthorizationToken, + ) -> Result { Ok(auth_token) } } impl Authorization for IngestRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: AuthorizationToken, + ) -> Result { Ok(auth_token) } } impl Authorization for FetchRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: AuthorizationToken, + ) -> Result { Ok(auth_token) } } diff --git a/quickwit/quickwit-ingest/src/codegen/ingest_service.rs b/quickwit/quickwit-ingest/src/codegen/ingest_service.rs index 8aeec3f2e86..49e20a534be 100644 --- a/quickwit/quickwit-ingest/src/codegen/ingest_service.rs +++ b/quickwit/quickwit-ingest/src/codegen/ingest_service.rs @@ -819,9 +819,10 @@ where T::Future: Send, { async fn ingest(&self, request: IngestRequest) -> crate::Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .ingest(request) + .ingest(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -830,9 +831,10 @@ where )) } async fn fetch(&self, request: FetchRequest) -> crate::Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .fetch(request) + .fetch(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -841,9 +843,10 @@ where )) } async fn tail(&self, request: TailRequest) -> crate::Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .tail(request) + .tail(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -873,13 +876,9 @@ impl ingest_service_grpc_server::IngestServiceGrpc for IngestServiceGrpcServerAd request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.ingest(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.ingest(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -889,13 +888,9 @@ impl ingest_service_grpc_server::IngestServiceGrpc for IngestServiceGrpcServerAd request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.fetch(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.fetch(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -905,13 +900,9 @@ impl ingest_service_grpc_server::IngestServiceGrpc for IngestServiceGrpcServerAd request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.tail(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.tail(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-ingest/src/error.rs b/quickwit/quickwit-ingest/src/error.rs index ab2c282db36..0b99ba27c95 100644 --- a/quickwit/quickwit-ingest/src/error.rs +++ b/quickwit/quickwit-ingest/src/error.rs @@ -21,6 +21,7 @@ use std::io; use mrecordlog::error::*; use quickwit_actors::AskError; +use quickwit_auth::AuthorizationError; use quickwit_common::rate_limited_error; use quickwit_common::tower::BufferError; pub(crate) use quickwit_proto::error::{grpc_error_to_grpc_status, grpc_status_to_service_error}; @@ -48,6 +49,8 @@ pub enum IngestServiceError { RateLimited(RateLimitingCause), #[error("ingest service is unavailable ({0})")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] AuthorizationError), } impl From> for IngestServiceError { @@ -93,6 +96,9 @@ impl From for IngestServiceError { IngestV2Error::TooManyRequests(rate_limiting_cause) => { IngestServiceError::RateLimited(rate_limiting_cause) } + IngestV2Error::Unauthorized(authorization_error) => { + IngestServiceError::Unauthorized(authorization_error) + } } } } @@ -134,6 +140,9 @@ impl From for IngestServiceError { IngestFailureReason::CircuitBreaker => { IngestServiceError::RateLimited(RateLimitingCause::CircuitBreaker) } + IngestFailureReason::Unauthorized => { + IngestServiceError::Unauthorized(AuthorizationError::PermissionDenied) + } } } } @@ -161,6 +170,7 @@ impl ServiceError for IngestServiceError { } Self::RateLimited(_) => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(_) => ServiceErrorCode::Unauthorized, } } } @@ -204,6 +214,9 @@ impl From for tonic::Status { IngestServiceError::IoError { .. } => tonic::Code::Internal, IngestServiceError::RateLimited(_) => tonic::Code::ResourceExhausted, IngestServiceError::Unavailable(_) => tonic::Code::Unavailable, + IngestServiceError::Unauthorized(authorized_error) => { + return (*authorized_error).into(); + } }; let message = error.to_string(); tonic::Status::new(code, message) diff --git a/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs b/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs index 8fc6a75b9f4..a5ae312faef 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs @@ -44,6 +44,7 @@ pub(crate) struct IngestResultMetrics { pub load_shedding: IntCounter, pub shard_not_found: IntCounter, pub unavailable: IntCounter, + pub unauthorized: IntCounter, } impl Default for IngestResultMetrics { @@ -72,6 +73,7 @@ impl Default for IngestResultMetrics { load_shedding: ingest_result_total_vec.with_label_values(["load_shedding"]), unavailable: ingest_result_total_vec.with_label_values(["unavailable"]), shard_not_found: ingest_result_total_vec.with_label_values(["shard_not_found"]), + unauthorized: ingest_result_total_vec.with_label_values(["unauthorized"]), } } } diff --git a/quickwit/quickwit-ingest/src/ingest_v2/router.rs b/quickwit/quickwit-ingest/src/ingest_v2/router.rs index d20d5c2e74c..0f18bf53d6b 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/router.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/router.rs @@ -542,6 +542,7 @@ fn update_ingest_metrics(ingest_result: &IngestV2Result, num_s ingest_results_metrics.router_load_shedding.inc() } IngestFailureReason::LoadShedding => ingest_results_metrics.load_shedding.inc(), + IngestFailureReason::Unauthorized => ingest_results_metrics.unauthorized.inc(), } } } @@ -588,6 +589,9 @@ fn update_ingest_metrics(ingest_result: &IngestV2Result, num_s IngestV2Error::Internal(_) => { ingest_results_metrics.internal.inc_by(num_subrequests); } + IngestV2Error::Unauthorized(_) => { + ingest_results_metrics.unauthorized.inc_by(num_subrequests); + } }, } } diff --git a/quickwit/quickwit-ingest/src/ingest_v2/workbench.rs b/quickwit/quickwit-ingest/src/ingest_v2/workbench.rs index 7dab68c5485..8717b959373 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/workbench.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/workbench.rs @@ -224,6 +224,12 @@ impl IngestWorkbench { self.record_too_many_requests(subrequest_id, rate_limiting_cause); } } + IngestV2Error::Unauthorized(_) => { + for subrequest_id in persist_summary.subrequest_ids { + let failure = SubworkbenchFailure::Persist(PersistFailureReason::Unauthorized); + self.record_failure(subrequest_id, failure); + } + } } } diff --git a/quickwit/quickwit-ingest/src/lib.rs b/quickwit/quickwit-ingest/src/lib.rs index 3bed1dd7833..33e23055ccd 100644 --- a/quickwit/quickwit-ingest/src/lib.rs +++ b/quickwit/quickwit-ingest/src/lib.rs @@ -19,6 +19,9 @@ #![deny(clippy::disallowed_methods)] +#[cfg(feature = "enterprise")] +mod authorize; + mod doc_batch; pub mod error; mod ingest_api_service; @@ -31,7 +34,6 @@ mod mrecordlog_async; mod notifications; mod position; mod queue; -mod authorize; use std::collections::HashMap; use std::path::{Path, PathBuf}; diff --git a/quickwit/quickwit-license/src/lib.rs b/quickwit/quickwit-license/src/lib.rs index 8cd89f3dad3..4c38b3adc9b 100644 --- a/quickwit/quickwit-license/src/lib.rs +++ b/quickwit/quickwit-license/src/lib.rs @@ -15,10 +15,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -// For all third party components incorporated into the Quickwit Software, those -// components are licensed under the original license provided by the owner of the -// applicable component. - use std::str::FromStr; use std::sync::OnceLock; use std::time::SystemTime; diff --git a/quickwit/quickwit-metastore/Cargo.toml b/quickwit/quickwit-metastore/Cargo.toml index a2ff2470cbc..4e4c7ec98aa 100644 --- a/quickwit/quickwit-metastore/Cargo.toml +++ b/quickwit/quickwit-metastore/Cargo.toml @@ -39,6 +39,7 @@ tracing = { workspace = true } ulid = { workspace = true, features = ["serde"] } utoipa = { workspace = true } +quickwit-auth = { workspace = true } quickwit-common = { workspace = true } quickwit-config = { workspace = true } quickwit-doc-mapper = { workspace = true } diff --git a/quickwit/quickwit-metastore/src/error.rs b/quickwit/quickwit-metastore/src/error.rs index 3e02d2cbed4..43c7f4b6ec9 100644 --- a/quickwit/quickwit-metastore/src/error.rs +++ b/quickwit/quickwit-metastore/src/error.rs @@ -39,4 +39,8 @@ pub enum MetastoreResolverError { /// error, incompatible version, internal error in a third party, etc. #[error("failed to connect to metastore: `{0}`")] Initialization(#[from] MetastoreError), + + /// The requested operation is not authorized. + #[error("unauthorized: `{0}`")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } diff --git a/quickwit/quickwit-proto/Cargo.toml b/quickwit/quickwit-proto/Cargo.toml index 088235e9c28..a5e90f751ae 100644 --- a/quickwit/quickwit-proto/Cargo.toml +++ b/quickwit/quickwit-proto/Cargo.toml @@ -54,3 +54,4 @@ quickwit-codegen = { workspace = true } [features] postgres = ["sea-query", "sqlx"] testsuite = ["mockall", "futures"] +enterprise = [ "quickwit-auth/enterprise"] diff --git a/quickwit/quickwit-proto/protos/quickwit/ingester.proto b/quickwit/quickwit-proto/protos/quickwit/ingester.proto index 8874176b941..2e9e8c75e9a 100644 --- a/quickwit/quickwit-proto/protos/quickwit/ingester.proto +++ b/quickwit/quickwit-proto/protos/quickwit/ingester.proto @@ -106,6 +106,7 @@ enum PersistFailureReason { PERSIST_FAILURE_REASON_SHARD_RATE_LIMITED = 3; PERSIST_FAILURE_REASON_WAL_FULL = 4; PERSIST_FAILURE_REASON_TIMEOUT = 5; + PERSIST_FAILURE_REASON_UNAUTHORIZED = 6; } message PersistFailure { diff --git a/quickwit/quickwit-proto/protos/quickwit/router.proto b/quickwit/quickwit-proto/protos/quickwit/router.proto index 8db31d7bf15..9f13db2c4b8 100644 --- a/quickwit/quickwit-proto/protos/quickwit/router.proto +++ b/quickwit/quickwit-proto/protos/quickwit/router.proto @@ -73,6 +73,7 @@ enum IngestFailureReason { INGEST_FAILURE_REASON_ROUTER_LOAD_SHEDDING = 8; INGEST_FAILURE_REASON_LOAD_SHEDDING = 9; INGEST_FAILURE_REASON_CIRCUIT_BREAKER = 10; + INGEST_FAILURE_REASON_UNAUTHORIZED = 11; } message IngestFailure { diff --git a/quickwit/quickwit-proto/src/authorization.rs b/quickwit/quickwit-proto/src/authorization.rs index 6316aaac9e8..0ad4fb8ec36 100644 --- a/quickwit/quickwit-proto/src/authorization.rs +++ b/quickwit/quickwit-proto/src/authorization.rs @@ -1,326 +1,167 @@ -use std::time::Duration; -use std::time::SystemTime; +use std::time::{Duration, SystemTime}; use biscuit_auth::builder_ext::BuilderExt; -use quickwit_auth::Authorization; -use quickwit_auth::AuthorizationError; -use quickwit_auth::AuthorizationToken; -use quickwit_auth::StreamAuthorization; +use biscuit_auth::macros::*; +use quickwit_auth::{Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization}; + use crate::cluster::FetchClusterStateRequest; -use crate::control_plane::AdviseResetShardsRequest; -use crate::control_plane::GetOrCreateOpenShardsRequest; +use crate::control_plane::{AdviseResetShardsRequest, GetOrCreateOpenShardsRequest}; use crate::developer::GetDebugInfoRequest; use crate::indexing::ApplyIndexingPlanRequest; -use crate::ingest::ingester::CloseShardsRequest; -use crate::ingest::ingester::DecommissionRequest; -use crate::ingest::ingester::InitShardsRequest; -use crate::ingest::ingester::OpenFetchStreamRequest; -use crate::ingest::ingester::OpenObservationStreamRequest; -use crate::ingest::ingester::PersistRequest; -use crate::ingest::ingester::RetainShardsRequest; -use crate::ingest::ingester::SynReplicationMessage; -use crate::ingest::ingester::TruncateShardsRequest; +use crate::ingest::ingester::{ + CloseShardsRequest, DecommissionRequest, InitShardsRequest, OpenFetchStreamRequest, + OpenObservationStreamRequest, PersistRequest, RetainShardsRequest, SynReplicationMessage, + TruncateShardsRequest, +}; use crate::ingest::router::IngestRequestV2; -use crate::metastore::DeleteQuery; -use crate::metastore::GetIndexTemplateRequest; -use crate::metastore::IndexMetadataRequest; -use crate::metastore::LastDeleteOpstampRequest; -use crate::metastore::ListDeleteTasksRequest; -use crate::metastore::ListIndexTemplatesRequest; -use crate::metastore::ListIndexesMetadataRequest; -use crate::metastore::ListShardsRequest; -use crate::metastore::ListSplitsRequest; -use crate::metastore::ListStaleSplitsRequest; -use crate::metastore::OpenShardsRequest; -use crate::metastore::PruneShardsRequest; -use crate::metastore::PublishSplitsRequest; -use crate::metastore::StageSplitsRequest; -use crate::metastore::UpdateSplitsDeleteOpstampRequest; -use biscuit_auth::macros::*; +use crate::metastore::{ + DeleteQuery, GetIndexTemplateRequest, IndexMetadataRequest, LastDeleteOpstampRequest, + ListDeleteTasksRequest, ListIndexTemplatesRequest, ListIndexesMetadataRequest, + ListShardsRequest, ListSplitsRequest, ListStaleSplitsRequest, OpenShardsRequest, + PruneShardsRequest, PublishSplitsRequest, StageSplitsRequest, UpdateSplitsDeleteOpstampRequest, +}; impl Authorization for crate::metastore::AcquireShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::AddSourceRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - - impl Authorization for crate::metastore::CreateIndexRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { + fn attenuate( + &self, + auth_token: AuthorizationToken, + ) -> Result { let mut builder = block!(r#"check if operation("create_index");"#); builder.check_expiration_date(SystemTime::now() + Duration::from_secs(60)); - let new_auth_token = auth_token.append(builder)?; - Ok(new_auth_token) + let biscuit = auth_token.into_biscuit(); + let new_auth_token = biscuit.append(builder)?; + Ok(AuthorizationToken::from(new_auth_token)) } } impl Authorization for crate::metastore::CreateIndexTemplateRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::DeleteIndexRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::DeleteIndexTemplatesRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::DeleteShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::DeleteSourceRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::DeleteSplitsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::FindIndexTemplateMatchesRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::IndexesMetadataRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::ToggleSourceRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::MarkSplitsForDeletionRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::ResetSourceCheckpointRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for crate::metastore::UpdateIndexRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for OpenObservationStreamRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for InitShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for OpenShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for FetchClusterStateRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for GetIndexTemplateRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for ListIndexTemplatesRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for PruneShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for ListShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for ListStaleSplitsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for ListDeleteTasksRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for UpdateSplitsDeleteOpstampRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for LastDeleteOpstampRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for DeleteQuery { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for GetOrCreateOpenShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for AdviseResetShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for GetDebugInfoRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for StageSplitsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for ListSplitsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for PublishSplitsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for ListIndexesMetadataRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for TruncateShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for CloseShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for RetainShardsRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for ApplyIndexingPlanRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for PersistRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for IndexMetadataRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl StreamAuthorization for SynReplicationMessage { - fn attenuate(auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for IngestRequestV2 { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } impl Authorization for OpenFetchStreamRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } - impl Authorization for DecommissionRequest { - fn attenuate(&self, auth_token: AuthorizationToken) -> Result { - Ok(auth_token) - } } diff --git a/quickwit/quickwit-proto/src/cluster/mod.rs b/quickwit/quickwit-proto/src/cluster/mod.rs index 48ee9dc0554..7f0a25ecf7a 100644 --- a/quickwit/quickwit-proto/src/cluster/mod.rs +++ b/quickwit/quickwit-proto/src/cluster/mod.rs @@ -39,6 +39,8 @@ pub enum ClusterError { TooManyRequests, #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } impl ServiceError for ClusterError { @@ -51,6 +53,7 @@ impl ServiceError for ClusterError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.cluster.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.cluster.rs index 2b54c972f75..07ec4928ec1 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.cluster.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.cluster.rs @@ -510,9 +510,10 @@ where &self, request: FetchClusterStateRequest, ) -> crate::cluster::ClusterResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .fetch_cluster_state(request) + .fetch_cluster_state(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -543,13 +544,12 @@ for ClusterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.fetch_cluster_state(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.fetch_cluster_state(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.control_plane.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.control_plane.rs index 5de613c9a05..780edd4b9ae 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.control_plane.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.control_plane.rs @@ -1633,9 +1633,10 @@ where ) -> crate::control_plane::ControlPlaneResult< super::metastore::CreateIndexResponse, > { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .create_index(request) + .create_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1649,9 +1650,10 @@ where ) -> crate::control_plane::ControlPlaneResult< super::metastore::IndexMetadataResponse, > { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .update_index(request) + .update_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1663,9 +1665,10 @@ where &self, request: super::metastore::DeleteIndexRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_index(request) + .delete_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1677,9 +1680,10 @@ where &self, request: super::metastore::AddSourceRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .add_source(request) + .add_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1691,9 +1695,10 @@ where &self, request: super::metastore::ToggleSourceRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .toggle_source(request) + .toggle_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1705,9 +1710,10 @@ where &self, request: super::metastore::DeleteSourceRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_source(request) + .delete_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1719,9 +1725,10 @@ where &self, request: GetOrCreateOpenShardsRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .get_or_create_open_shards(request) + .get_or_create_open_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1733,9 +1740,10 @@ where &self, request: AdviseResetShardsRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .advise_reset_shards(request) + .advise_reset_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1747,9 +1755,10 @@ where &self, request: super::metastore::PruneShardsRequest, ) -> crate::control_plane::ControlPlaneResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .prune_shards(request) + .prune_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -1780,13 +1789,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.create_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.create_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1799,13 +1807,12 @@ for ControlPlaneServiceGrpcServerAdapter { tonic::Status, > { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.update_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.update_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1815,13 +1822,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1831,13 +1837,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.add_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.add_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1847,13 +1852,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.toggle_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.toggle_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1863,13 +1867,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1879,13 +1882,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.get_or_create_open_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.get_or_create_open_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1895,13 +1897,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.advise_reset_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.advise_reset_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -1911,13 +1912,12 @@ for ControlPlaneServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.prune_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.prune_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.developer.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.developer.rs index cbe28bd2eb2..ec25565eef2 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.developer.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.developer.rs @@ -446,9 +446,10 @@ where &self, request: GetDebugInfoRequest, ) -> crate::developer::DeveloperResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .get_debug_info(request) + .get_debug_info(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -479,13 +480,12 @@ for DeveloperServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.get_debug_info(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.get_debug_info(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.indexing.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.indexing.rs index 42514ba5003..a6b7a2a0aee 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.indexing.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.indexing.rs @@ -459,9 +459,10 @@ where &self, request: ApplyIndexingPlanRequest, ) -> crate::indexing::IndexingResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .apply_indexing_plan(request) + .apply_indexing_plan(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -492,13 +493,12 @@ for IndexingServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.apply_indexing_plan(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.apply_indexing_plan(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.ingester.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.ingester.rs index e18cc626151..c5a230b7d09 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.ingester.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.ingester.rs @@ -441,6 +441,7 @@ pub enum PersistFailureReason { ShardRateLimited = 3, WalFull = 4, Timeout = 5, + Unauthorized = 6, } impl PersistFailureReason { /// String value of the enum field names used in the ProtoBuf definition. @@ -459,6 +460,7 @@ impl PersistFailureReason { } PersistFailureReason::WalFull => "PERSIST_FAILURE_REASON_WAL_FULL", PersistFailureReason::Timeout => "PERSIST_FAILURE_REASON_TIMEOUT", + PersistFailureReason::Unauthorized => "PERSIST_FAILURE_REASON_UNAUTHORIZED", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -470,6 +472,7 @@ impl PersistFailureReason { "PERSIST_FAILURE_REASON_SHARD_RATE_LIMITED" => Some(Self::ShardRateLimited), "PERSIST_FAILURE_REASON_WAL_FULL" => Some(Self::WalFull), "PERSIST_FAILURE_REASON_TIMEOUT" => Some(Self::Timeout), + "PERSIST_FAILURE_REASON_UNAUTHORIZED" => Some(Self::Unauthorized), _ => None, } } @@ -2041,9 +2044,10 @@ where &self, request: PersistRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .persist(request) + .persist(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2055,9 +2059,12 @@ where &self, request: quickwit_common::ServiceStream, ) -> crate::ingest::IngestV2Result> { + let tonic_request = quickwit_auth::build_tonic_stream_request_with_auth_token( + request, + )?; self.inner .clone() - .open_replication_stream(request) + .open_replication_stream(tonic_request) .await .map(|response| { let streaming: tonic::Streaming<_> = response.into_inner(); @@ -2077,9 +2084,10 @@ where &self, request: OpenFetchStreamRequest, ) -> crate::ingest::IngestV2Result> { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .open_fetch_stream(request) + .open_fetch_stream(tonic_request) .await .map(|response| { let streaming: tonic::Streaming<_> = response.into_inner(); @@ -2099,9 +2107,10 @@ where &self, request: OpenObservationStreamRequest, ) -> crate::ingest::IngestV2Result> { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .open_observation_stream(request) + .open_observation_stream(tonic_request) .await .map(|response| { let streaming: tonic::Streaming<_> = response.into_inner(); @@ -2121,9 +2130,10 @@ where &self, request: InitShardsRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .init_shards(request) + .init_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2135,9 +2145,10 @@ where &self, request: RetainShardsRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .retain_shards(request) + .retain_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2149,9 +2160,10 @@ where &self, request: TruncateShardsRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .truncate_shards(request) + .truncate_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2163,9 +2175,10 @@ where &self, request: CloseShardsRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .close_shards(request) + .close_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2177,9 +2190,10 @@ where &self, request: DecommissionRequest, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .decommission(request) + .decommission(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -2210,13 +2224,9 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.persist(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.persist(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -2234,8 +2244,10 @@ for IngesterServiceGrpcServerAdapter { quickwit_common::ServiceStream::from(streaming) }; quickwit_auth::authorize_stream::(&auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.open_replication_stream(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.open_replication_stream(req), + ) .await .map(|stream| tonic::Response::new( stream.map_err(crate::error::grpc_error_to_grpc_status), @@ -2250,13 +2262,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.open_fetch_stream(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.open_fetch_stream(req), + ) .await .map(|stream| tonic::Response::new( stream.map_err(crate::error::grpc_error_to_grpc_status), @@ -2271,13 +2282,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.open_observation_stream(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.open_observation_stream(req), + ) .await .map(|stream| tonic::Response::new( stream.map_err(crate::error::grpc_error_to_grpc_status), @@ -2289,13 +2299,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.init_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.init_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -2305,13 +2314,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.retain_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.retain_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -2321,13 +2329,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.truncate_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.truncate_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -2337,13 +2344,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.close_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.close_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -2353,13 +2359,12 @@ for IngesterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.decommission(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.decommission(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.router.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.router.rs index 16a078d360a..405e9abe6f3 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.router.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.ingest.router.rs @@ -81,6 +81,7 @@ pub enum IngestFailureReason { RouterLoadShedding = 8, LoadShedding = 9, CircuitBreaker = 10, + Unauthorized = 11, } impl IngestFailureReason { /// String value of the enum field names used in the ProtoBuf definition. @@ -110,6 +111,7 @@ impl IngestFailureReason { IngestFailureReason::CircuitBreaker => { "INGEST_FAILURE_REASON_CIRCUIT_BREAKER" } + IngestFailureReason::Unauthorized => "INGEST_FAILURE_REASON_UNAUTHORIZED", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -128,6 +130,7 @@ impl IngestFailureReason { } "INGEST_FAILURE_REASON_LOAD_SHEDDING" => Some(Self::LoadShedding), "INGEST_FAILURE_REASON_CIRCUIT_BREAKER" => Some(Self::CircuitBreaker), + "INGEST_FAILURE_REASON_UNAUTHORIZED" => Some(Self::Unauthorized), _ => None, } } @@ -569,9 +572,10 @@ where &self, request: IngestRequestV2, ) -> crate::ingest::IngestV2Result { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .ingest(request) + .ingest(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -602,13 +606,9 @@ for IngestRouterServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.ingest(req)) + quickwit_auth::execute_with_authorization(auth_token, self.inner.0.ingest(req)) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.metastore.rs b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.metastore.rs index 1ca889eaf00..b923d5261f7 100644 --- a/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.metastore.rs +++ b/quickwit/quickwit-proto/src/codegen/quickwit/quickwit.metastore.rs @@ -4866,9 +4866,10 @@ where &self, request: CreateIndexRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .create_index(request) + .create_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4880,9 +4881,10 @@ where &self, request: UpdateIndexRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .update_index(request) + .update_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4894,9 +4896,10 @@ where &self, request: IndexMetadataRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .index_metadata(request) + .index_metadata(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4908,9 +4911,10 @@ where &self, request: IndexesMetadataRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .indexes_metadata(request) + .indexes_metadata(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4922,9 +4926,10 @@ where &self, request: ListIndexesMetadataRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_indexes_metadata(request) + .list_indexes_metadata(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4936,9 +4941,10 @@ where &self, request: DeleteIndexRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_index(request) + .delete_index(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4950,9 +4956,10 @@ where &self, request: ListSplitsRequest, ) -> crate::metastore::MetastoreResult> { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_splits(request) + .list_splits(tonic_request) .await .map(|response| { let streaming: tonic::Streaming<_> = response.into_inner(); @@ -4972,9 +4979,10 @@ where &self, request: StageSplitsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .stage_splits(request) + .stage_splits(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -4986,9 +4994,10 @@ where &self, request: PublishSplitsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .publish_splits(request) + .publish_splits(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5000,9 +5009,10 @@ where &self, request: MarkSplitsForDeletionRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .mark_splits_for_deletion(request) + .mark_splits_for_deletion(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5014,9 +5024,10 @@ where &self, request: DeleteSplitsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_splits(request) + .delete_splits(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5028,9 +5039,10 @@ where &self, request: AddSourceRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .add_source(request) + .add_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5042,9 +5054,10 @@ where &self, request: ToggleSourceRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .toggle_source(request) + .toggle_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5056,9 +5069,10 @@ where &self, request: DeleteSourceRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_source(request) + .delete_source(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5070,9 +5084,10 @@ where &self, request: ResetSourceCheckpointRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .reset_source_checkpoint(request) + .reset_source_checkpoint(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5084,9 +5099,10 @@ where &self, request: LastDeleteOpstampRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .last_delete_opstamp(request) + .last_delete_opstamp(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5098,9 +5114,10 @@ where &self, request: DeleteQuery, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .create_delete_task(request) + .create_delete_task(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5112,9 +5129,10 @@ where &self, request: UpdateSplitsDeleteOpstampRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .update_splits_delete_opstamp(request) + .update_splits_delete_opstamp(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5126,9 +5144,10 @@ where &self, request: ListDeleteTasksRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_delete_tasks(request) + .list_delete_tasks(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5140,9 +5159,10 @@ where &self, request: ListStaleSplitsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_stale_splits(request) + .list_stale_splits(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5154,9 +5174,10 @@ where &self, request: OpenShardsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .open_shards(request) + .open_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5168,9 +5189,10 @@ where &self, request: AcquireShardsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .acquire_shards(request) + .acquire_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5182,9 +5204,10 @@ where &self, request: DeleteShardsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_shards(request) + .delete_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5196,9 +5219,10 @@ where &self, request: PruneShardsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .prune_shards(request) + .prune_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5210,9 +5234,10 @@ where &self, request: ListShardsRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_shards(request) + .list_shards(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5224,9 +5249,10 @@ where &self, request: CreateIndexTemplateRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .create_index_template(request) + .create_index_template(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5238,9 +5264,10 @@ where &self, request: GetIndexTemplateRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .get_index_template(request) + .get_index_template(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5252,9 +5279,10 @@ where &self, request: FindIndexTemplateMatchesRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .find_index_template_matches(request) + .find_index_template_matches(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5266,9 +5294,10 @@ where &self, request: ListIndexTemplatesRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .list_index_templates(request) + .list_index_templates(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5280,9 +5309,10 @@ where &self, request: DeleteIndexTemplatesRequest, ) -> crate::metastore::MetastoreResult { + let tonic_request = quickwit_auth::build_tonic_request_with_auth_token(request)?; self.inner .clone() - .delete_index_templates(request) + .delete_index_templates(tonic_request) .await .map(|response| response.into_inner()) .map_err(|status| crate::error::grpc_status_to_service_error( @@ -5328,13 +5358,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.create_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.create_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5344,13 +5373,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.update_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.update_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5360,13 +5388,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.index_metadata(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.index_metadata(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5376,13 +5403,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.indexes_metadata(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.indexes_metadata(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5392,13 +5418,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_indexes_metadata(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_indexes_metadata(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5408,13 +5433,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_index(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_index(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5427,13 +5451,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_splits(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_splits(req), + ) .await .map(|stream| tonic::Response::new( stream.map_err(crate::error::grpc_error_to_grpc_status), @@ -5445,13 +5468,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.stage_splits(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.stage_splits(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5461,13 +5483,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.publish_splits(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.publish_splits(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5477,13 +5498,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.mark_splits_for_deletion(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.mark_splits_for_deletion(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5493,13 +5513,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_splits(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_splits(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5509,13 +5528,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.add_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.add_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5525,13 +5543,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.toggle_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.toggle_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5541,13 +5558,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_source(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_source(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5557,13 +5573,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.reset_source_checkpoint(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.reset_source_checkpoint(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5573,13 +5588,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.last_delete_opstamp(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.last_delete_opstamp(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5589,13 +5603,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.create_delete_task(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.create_delete_task(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5605,13 +5618,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.update_splits_delete_opstamp(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.update_splits_delete_opstamp(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5621,13 +5633,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_delete_tasks(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_delete_tasks(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5637,13 +5648,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_stale_splits(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_stale_splits(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5653,13 +5663,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.open_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.open_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5669,13 +5678,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.acquire_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.acquire_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5685,13 +5693,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5701,13 +5708,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.prune_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.prune_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5717,13 +5723,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_shards(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_shards(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5733,13 +5738,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.create_index_template(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.create_index_template(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5749,13 +5753,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.get_index_template(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.get_index_template(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5765,13 +5768,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.find_index_template_matches(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.find_index_template_matches(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5781,13 +5783,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.list_index_templates(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.list_index_templates(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) @@ -5797,13 +5798,12 @@ for MetastoreServiceGrpcServerAdapter { request: tonic::Request, ) -> Result, tonic::Status> { let auth_token = quickwit_auth::get_auth_token(request.metadata())?; - let req = { - let req = request.into_inner(); - req - }; + let req = request.into_inner(); quickwit_auth::authorize(&req, &auth_token)?; - quickwit_auth::AUTHORIZATION_TOKEN - .scope(auth_token, self.inner.0.delete_index_templates(req)) + quickwit_auth::execute_with_authorization( + auth_token, + self.inner.0.delete_index_templates(req), + ) .await .map(tonic::Response::new) .map_err(crate::error::grpc_error_to_grpc_status) diff --git a/quickwit/quickwit-proto/src/control_plane/mod.rs b/quickwit/quickwit-proto/src/control_plane/mod.rs index 8184851845e..34306229a2a 100644 --- a/quickwit/quickwit-proto/src/control_plane/mod.rs +++ b/quickwit/quickwit-proto/src/control_plane/mod.rs @@ -42,6 +42,8 @@ pub enum ControlPlaneError { TooManyRequests, #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } impl From for ControlPlaneError { @@ -70,6 +72,7 @@ impl ServiceError for ControlPlaneError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } @@ -109,6 +112,7 @@ impl From for MetastoreError { ControlPlaneError::Timeout(message) => MetastoreError::Timeout(message), ControlPlaneError::TooManyRequests => MetastoreError::TooManyRequests, ControlPlaneError::Unavailable(message) => MetastoreError::Unavailable(message), + ControlPlaneError::Unauthorized(authorization_error) => authorization_error.into(), } } } diff --git a/quickwit/quickwit-proto/src/developer/mod.rs b/quickwit/quickwit-proto/src/developer/mod.rs index 2ed98190b17..90595b6d60a 100644 --- a/quickwit/quickwit-proto/src/developer/mod.rs +++ b/quickwit/quickwit-proto/src/developer/mod.rs @@ -38,6 +38,8 @@ pub enum DeveloperError { TooManyRequests, #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } impl ServiceError for DeveloperError { @@ -48,6 +50,7 @@ impl ServiceError for DeveloperError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } diff --git a/quickwit/quickwit-proto/src/error.rs b/quickwit/quickwit-proto/src/error.rs index 8fb11caac6e..828e33efe0a 100644 --- a/quickwit/quickwit-proto/src/error.rs +++ b/quickwit/quickwit-proto/src/error.rs @@ -23,6 +23,7 @@ use std::fmt::Debug; use anyhow::Context; use quickwit_actors::AskError; +use quickwit_auth::AuthorizationError; use serde::de::DeserializeOwned; use serde::Serialize; use tonic::metadata::BinaryMetadataValue; @@ -47,6 +48,13 @@ pub enum ServiceErrorCode { TooManyRequests, Unauthenticated, Unavailable, + Unauthorized, +} + +impl From for ServiceErrorCode { + fn from(_: AuthorizationError) -> Self { + ServiceErrorCode::Unauthorized + } } impl ServiceErrorCode { @@ -61,6 +69,7 @@ impl ServiceErrorCode { Self::TooManyRequests => tonic::Code::ResourceExhausted, Self::Unauthenticated => tonic::Code::Unauthenticated, Self::Unavailable => tonic::Code::Unavailable, + Self::Unauthorized => tonic::Code::PermissionDenied, } } @@ -75,6 +84,7 @@ impl ServiceErrorCode { Self::TooManyRequests => http::StatusCode::TOO_MANY_REQUESTS, Self::Unauthenticated => http::StatusCode::UNAUTHORIZED, Self::Unavailable => http::StatusCode::SERVICE_UNAVAILABLE, + Self::Unauthorized => http::StatusCode::UNAUTHORIZED, } } } diff --git a/quickwit/quickwit-proto/src/indexing/mod.rs b/quickwit/quickwit-proto/src/indexing/mod.rs index b621f447ef1..449d7f9efae 100644 --- a/quickwit/quickwit-proto/src/indexing/mod.rs +++ b/quickwit/quickwit-proto/src/indexing/mod.rs @@ -51,7 +51,10 @@ pub enum IndexingError { TooManyRequests, #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } + impl From for IndexingError { fn from(_timeout_exceeded: TimeoutExceeded) -> Self { Self::Timeout("tower layer timeout".to_string()) @@ -69,6 +72,7 @@ impl ServiceError for IndexingError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } diff --git a/quickwit/quickwit-proto/src/ingest/mod.rs b/quickwit/quickwit-proto/src/ingest/mod.rs index 48a410cd5ba..3722c5fbd87 100644 --- a/quickwit/quickwit-proto/src/ingest/mod.rs +++ b/quickwit/quickwit-proto/src/ingest/mod.rs @@ -65,6 +65,8 @@ pub enum IngestV2Error { TooManyRequests(RateLimitingCause), #[error("service unavailable: {0}")] Unavailable(String), + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } impl From for IngestV2Error { @@ -90,6 +92,7 @@ impl ServiceError for IngestV2Error { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests(_) => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } @@ -318,6 +321,7 @@ impl From for IngestFailureReason { PersistFailureReason::WalFull => IngestFailureReason::WalFull, PersistFailureReason::ShardRateLimited => IngestFailureReason::ShardRateLimited, PersistFailureReason::Timeout => IngestFailureReason::Timeout, + PersistFailureReason::Unauthorized => IngestFailureReason::Unauthorized, } } } diff --git a/quickwit/quickwit-proto/src/lib.rs b/quickwit/quickwit-proto/src/lib.rs index 14d1969c573..3e0f44a3003 100644 --- a/quickwit/quickwit-proto/src/lib.rs +++ b/quickwit/quickwit-proto/src/lib.rs @@ -30,9 +30,11 @@ use tonic::Status; use tracing::Span; use tracing_opentelemetry::OpenTelemetrySpanExt; +#[cfg(feature = "enterprise")] +mod authorization; + pub mod cluster; pub mod control_plane; -mod authorization; pub use {bytes, tonic}; pub mod developer; pub mod error; diff --git a/quickwit/quickwit-proto/src/metastore/mod.rs b/quickwit/quickwit-proto/src/metastore/mod.rs index 4782dac03c2..530f5ec0c79 100644 --- a/quickwit/quickwit-proto/src/metastore/mod.rs +++ b/quickwit/quickwit-proto/src/metastore/mod.rs @@ -155,6 +155,9 @@ pub enum MetastoreError { #[error("service unavailable: {0}")] Unavailable(String), + + #[error("unauthorized: {0}")] + Unauthorized(#[from] quickwit_auth::AuthorizationError), } impl MetastoreError { @@ -169,7 +172,8 @@ impl MetastoreError { | MetastoreError::JsonDeserializeError { .. } | MetastoreError::JsonSerializeError { .. } | MetastoreError::NotFound(_) - | MetastoreError::TooManyRequests => true, + | MetastoreError::TooManyRequests + | MetastoreError::Unauthorized(_) => true, MetastoreError::Connection { .. } | MetastoreError::Db { .. } | MetastoreError::Internal { .. } @@ -242,6 +246,7 @@ impl ServiceError for MetastoreError { Self::Timeout(_) => ServiceErrorCode::Timeout, Self::TooManyRequests => ServiceErrorCode::TooManyRequests, Self::Unavailable(_) => ServiceErrorCode::Unavailable, + Self::Unauthorized(authorization_error) => (*authorization_error).into(), } } } diff --git a/quickwit/quickwit-serve/src/elasticsearch_api/model/bulk_query_params.rs b/quickwit/quickwit-serve/src/elasticsearch_api/model/bulk_query_params.rs index e9b415c8248..fbba0f739a6 100644 --- a/quickwit/quickwit-serve/src/elasticsearch_api/model/bulk_query_params.rs +++ b/quickwit/quickwit-serve/src/elasticsearch_api/model/bulk_query_params.rs @@ -114,7 +114,7 @@ mod tests { serde_qs::from_str::("refresh=wait") .unwrap_err() .to_string(), - "unknown variant `wait`, expected one of `false`, `true`, `wait_for`" + "unknown variant `wait`, expected one of `false`, ``, `true`, `wait_for`" ); } } diff --git a/quickwit/scripts/.ee.license_header.txt b/quickwit/scripts/.ee.license_header.txt index 9a1485ca763..2978b3cab09 100644 --- a/quickwit/scripts/.ee.license_header.txt +++ b/quickwit/scripts/.ee.license_header.txt @@ -1,5 +1,5 @@ // The Quickwit Enterprise Edition (EE) license -// Copyright (c) {\d+}-present Quickwit Inc. +// Copyright (c) 2024-present Quickwit Inc. // // With regard to the Quickwit Software: // @@ -14,7 +14,3 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. - -// For all third party components incorporated into the Quickwit Software, those -// components are licensed under the original license provided by the owner of the -// applicable component. diff --git a/quickwit/scripts/check_license_headers.sh b/quickwit/scripts/check_license_headers.sh index 6684b2023ba..9ff9861192b 100755 --- a/quickwit/scripts/check_license_headers.sh +++ b/quickwit/scripts/check_license_headers.sh @@ -15,7 +15,7 @@ do # echo "Checking $file"; diff <(sed 's/{\\d+}/2024/' "${SCRIPT_DIR}/.agpl.license_header.txt") <(head -n 18 $file) > /dev/null HAS_AGPL_LICENSE=$? - diff <(sed 's/{\\d+}/2024/' "${SCRIPT_DIR}/.ee.license_header.txt") <(head -n 20 $file) > /dev/null + diff <(sed 's/{\\d+}/2024/' "${SCRIPT_DIR}/.ee.license_header.txt") <(head -n 16 $file) > /dev/null HAS_EE_LICENSE=$? HAS_LICENSE_HEADER=$(( $HAS_AGPL_LICENSE ^ $HAS_EE_LICENSE )) if [ $HAS_LICENSE_HEADER -ne 1 ]; then