Skip to content

Commit 42f4501

Browse files
committed
blop
1 parent 94b575a commit 42f4501

File tree

19 files changed

+209
-28
lines changed

19 files changed

+209
-28
lines changed

quickwit/Cargo.lock

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

quickwit/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ tikv-jemalloc-ctl = "0.5"
240240
tikv-jemallocator = "0.5"
241241
time = { version = "0.3", features = ["std", "formatting", "macros"] }
242242
tokio = { version = "1.40", features = ["full"] }
243+
tokio-inherit-task-local = "0.2"
243244
tokio-metrics = { version = "0.3.1", features = ["rt"] }
244245
tokio-stream = { version = "0.1", features = ["sync"] }
245246
tokio-util = { version = "0.7", features = ["full"] }

quickwit/quickwit-authorize/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ tower = { workspace = true}
1313
biscuit-auth = { workspace = true, optional=true }
1414
futures = { workspace = true }
1515
http = { workspace = true }
16+
tokio-inherit-task-local = { workspace = true }
1617
serde = { workspace = true }
1718
thiserror = { workspace = true }
1819
tonic = { workspace = true }

quickwit/quickwit-authorize/src/authorization_layer.rs renamed to quickwit/quickwit-authorize/src/enterprise/authorization_layer.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
// Copyright (C) 2024 Quickwit, Inc.
2+
//
3+
// Quickwit is offered under the AGPL v3.0 and as commercial software.
4+
// For commercial licensing, contact us at [email protected].
5+
//
6+
// AGPL:
7+
// This program is free software: you can redistribute it and/or modify
8+
// it under the terms of the GNU Affero General Public License as
9+
// published by the Free Software Foundation, either version 3 of the
10+
// License, or (at your option) any later version.
11+
//
12+
// This program is distributed in the hope that it will be useful,
13+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
// GNU Affero General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU Affero General Public License
18+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
120
use std::fmt;
221
use std::task::{Context, Poll};
322

@@ -7,6 +26,7 @@ use tower::{Layer, Service};
726

827
use crate::AuthorizationError;
928

29+
#[derive(Clone, Copy, Debug)]
1030
pub struct AuthorizationLayer;
1131

1232
impl<S: Clone> Layer<S> for AuthorizationLayer {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright (C) 2024 Quickwit, Inc.
2+
//
3+
// Quickwit is offered under the AGPL v3.0 and as commercial software.
4+
// For commercial licensing, contact us at [email protected].
5+
//
6+
// AGPL:
7+
// This program is free software: you can redistribute it and/or modify
8+
// it under the terms of the GNU Affero General Public License as
9+
// published by the Free Software Foundation, either version 3 of the
10+
// License, or (at your option) any later version.
11+
//
12+
// This program is distributed in the hope that it will be useful,
13+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
// GNU Affero General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU Affero General Public License
18+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
20+
use std::task::{Context, Poll};
21+
22+
use futures::future::Either;
23+
use http::Request;
24+
use tokio::task::futures::TaskLocalFuture;
25+
use tokio_inherit_task_local::TaskLocalInheritableTable;
26+
use tower::{Layer, Service};
27+
28+
use super::AuthorizationToken;
29+
30+
#[derive(Clone, Copy, Debug)]
31+
pub struct AuthorizationTokenExtractionLayer;
32+
33+
impl<S: Clone> Layer<S> for AuthorizationTokenExtractionLayer {
34+
type Service = AuthorizationTokenExtractionService<S>;
35+
36+
fn layer(&self, service: S) -> Self::Service {
37+
AuthorizationTokenExtractionService { service }
38+
}
39+
}
40+
41+
#[derive(Clone)]
42+
pub struct AuthorizationTokenExtractionService<S> {
43+
service: S,
44+
}
45+
46+
fn get_authorization_token_opt(headers: &http::HeaderMap) -> Option<AuthorizationToken> {
47+
let authorization_header_value = headers.get("Authorization")?;
48+
let authorization_header_str = authorization_header_value.to_str().ok()?;
49+
crate::get_auth_token_from_str(authorization_header_str).ok()
50+
}
51+
52+
impl<B, S> Service<Request<B>> for AuthorizationTokenExtractionService<S>
53+
where S: Service<Request<B>>
54+
{
55+
type Response = S::Response;
56+
type Error = S::Error;
57+
type Future = Either<S::Future, TaskLocalFuture<TaskLocalInheritableTable, S::Future>>;
58+
59+
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
60+
self.service.poll_ready(cx)
61+
}
62+
63+
fn call(&mut self, request: Request<B>) -> Self::Future {
64+
let authorization_token_opt = get_authorization_token_opt(request.headers());
65+
let fut = self.service.call(request);
66+
if let Some(authorization_token) = authorization_token_opt {
67+
Either::Right(crate::execute_with_authorization(authorization_token, fut))
68+
} else {
69+
Either::Left(fut)
70+
}
71+
}
72+
}

quickwit/quickwit-authorize/src/enterprise.rs renamed to quickwit/quickwit-authorize/src/enterprise/mod.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@
1919
// components are licensed under the original license provided by the owner of the
2020
// applicable component.
2121

22+
mod authorization_layer;
23+
mod authorization_token_extraction_layer;
24+
2225
use std::future::Future;
2326
use std::str::FromStr;
2427
use std::sync::{Arc, OnceLock};
2528

29+
pub use authorization_layer::AuthorizationLayer;
30+
pub use authorization_token_extraction_layer::AuthorizationTokenExtractionLayer;
2631
use biscuit_auth::macros::authorizer;
2732
use biscuit_auth::{Authorizer, Biscuit, RootKeyProvider};
33+
use tokio::task::futures::TaskLocalFuture;
34+
use tokio_inherit_task_local::TaskLocalInheritableTable;
2835

2936
use crate::AuthorizationError;
3037

@@ -79,7 +86,7 @@ impl FromStr for AuthorizationToken {
7986
}
8087
}
8188

82-
tokio::task_local! {
89+
tokio_inherit_task_local::inheritable_task_local! {
8390
pub static AUTHORIZATION_TOKEN: AuthorizationToken;
8491
}
8592

@@ -146,6 +153,16 @@ impl From<biscuit_auth::error::Token> for AuthorizationError {
146153
}
147154
}
148155

156+
pub fn get_auth_token_from_str(
157+
authorization_header_value: &str,
158+
) -> Result<AuthorizationToken, AuthorizationError> {
159+
let authorization_token_str: &str = authorization_header_value
160+
.strip_prefix(AUTHORIZATION_VALUE_PREFIX)
161+
.ok_or(AuthorizationError::InvalidToken)?;
162+
let biscuit: Biscuit = Biscuit::from_base64(authorization_token_str, get_root_key_provider())?;
163+
Ok(AuthorizationToken(biscuit))
164+
}
165+
149166
pub fn get_auth_token(
150167
req_metadata: &tonic::metadata::MetadataMap,
151168
) -> Result<AuthorizationToken, AuthorizationError> {
@@ -154,11 +171,7 @@ pub fn get_auth_token(
154171
.ok_or(AuthorizationError::AuthorizationTokenMissing)?
155172
.to_str()
156173
.map_err(|_| AuthorizationError::InvalidToken)?;
157-
let authorization_token_str: &str = authorization_header_value
158-
.strip_prefix(AUTHORIZATION_VALUE_PREFIX)
159-
.ok_or(AuthorizationError::InvalidToken)?;
160-
let biscuit: Biscuit = Biscuit::from_base64(authorization_token_str, get_root_key_provider())?;
161-
Ok(AuthorizationToken(biscuit))
174+
get_auth_token_from_str(authorization_header_value)
162175
}
163176

164177
pub fn set_auth_token(
@@ -224,7 +237,7 @@ pub fn authorize_request<R: Authorization>(req: &R) -> Result<(), AuthorizationE
224237
pub fn execute_with_authorization<F, O>(
225238
token: AuthorizationToken,
226239
f: F,
227-
) -> impl Future<Output = O>
240+
) -> TaskLocalFuture<TaskLocalInheritableTable, F>
228241
where
229242
F: Future<Output = O>,
230243
{

quickwit/quickwit-authorize/src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@
1717
// You should have received a copy of the GNU Affero General Public License
1818
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1919

20-
mod authorization_layer;
21-
2220
#[cfg(not(feature = "enterprise"))]
23-
#[path = "community.rs"]
21+
#[path = "community/mod.rs"]
2422
mod implementation;
2523

2624
#[cfg(feature = "enterprise")]
27-
#[path = "enterprise.rs"]
25+
#[path = "enterprise/mod.rs"]
2826
mod implementation;
2927

3028
pub use implementation::*;

quickwit/quickwit-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ quickwit-metastore = { workspace = true, features = ["testsuite"] }
7979
quickwit-storage = { workspace = true, features = ["testsuite"] }
8080

8181
[features]
82-
enterprise = ["quickwit-config/enterprise", "quickwit-ingest/enterprise", "quickwit-proto/enterprise"]
82+
enterprise = ["quickwit-config/enterprise", "quickwit-ingest/enterprise", "quickwit-proto/enterprise", "quickwit-serve/enterprise"]
8383
jemalloc = ["dep:tikv-jemalloc-ctl", "dep:tikv-jemallocator"]
8484
ci-test = []
8585
pprof = ["quickwit-serve/pprof"]

quickwit/quickwit-codegen/example/src/authorization.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1616
// SOFTWARE.
1717

18-
use quickwit_authorize::{Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization};
18+
use quickwit_authorize::{
19+
Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization,
20+
};
1921

2022
use crate::{GoodbyeRequest, HelloRequest, PingRequest};
2123

@@ -38,9 +40,7 @@ impl Authorization for GoodbyeRequest {
3840
}
3941

4042
impl StreamAuthorization for PingRequest {
41-
fn attenuate(
42-
auth_token: AuthorizationToken,
43-
) -> Result<AuthorizationToken, AuthorizationError> {
43+
fn attenuate(auth_token: AuthorizationToken) -> Result<AuthorizationToken, AuthorizationError> {
4444
Ok(auth_token)
4545
}
4646
}

quickwit/quickwit-common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ thiserror = { workspace = true }
3939
tokio = { workspace = true }
4040
tokio-metrics = { workspace = true }
4141
tokio-stream = { workspace = true }
42+
tokio-inherit-task-local = { workspace = true }
4243
tonic = { workspace = true }
4344
tower = { workspace = true }
4445
tracing = { workspace = true }

quickwit/quickwit-common/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ pub fn num_cpus() -> usize {
213213
}
214214
}
215215

216+
pub fn spawn_inherit_task_local<F>(future: F) -> tokio::task::JoinHandle<F::Output>
217+
where
218+
F: Future + Send + 'static,
219+
F::Output: Send + 'static,
220+
{
221+
use tokio_inherit_task_local::FutureInheritTaskLocal;
222+
tokio::task::spawn(future.inherit_task_local())
223+
}
224+
216225
// The following are helpers to build named tasks.
217226
//
218227
// Named tasks require the tokio feature `tracing` to be enabled.

quickwit/quickwit-common/src/tower/one_task_per_call_layer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ where
7777
fn call(&mut self, request: Request) -> Self::Future {
7878
let request_name: &'static str = Request::rpc_name();
7979
let future = self.service.call(request);
80-
let join_handle = tokio::spawn(future);
80+
let join_handle = crate::spawn_inherit_task_local(future);
8181
UnwrapOrElseFuture {
8282
request_name,
8383
join_handle,

quickwit/quickwit-ingest/src/authorize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1616
// SOFTWARE.
1717

18-
use quickwit_authorize::::{Authorization, AuthorizationError, AuthorizationToken};
18+
use quickwit_authorize::{Authorization, AuthorizationError, AuthorizationToken};
1919

2020
use crate::{FetchRequest, IngestRequest, TailRequest};
2121

quickwit/quickwit-proto/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ license.workspace = true
1212
[dependencies]
1313
anyhow = { workspace = true }
1414
async-trait = { workspace = true }
15+
biscuit-auth = { workspace = true, optional = true }
1516
bytes = { workspace = true }
1617
bytesize = { workspace = true }
1718
bytestring = { workspace = true }
@@ -53,4 +54,4 @@ quickwit-codegen = { workspace = true }
5354
[features]
5455
postgres = ["sea-query", "sqlx"]
5556
testsuite = ["mockall", "futures"]
56-
enterprise = [ "quickwit-authorize/enterprise"]
57+
enterprise = [ "quickwit-authorize/enterprise", "dep:biscuit-auth"]

quickwit/quickwit-proto/src/authorization.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use std::time::{Duration, SystemTime};
22

3-
use biscuit_auth::builder_ext::BuilderExt;
4-
use biscuit_auth::macros::*;
5-
use quickwit_authorize::::{Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization};
3+
pub use biscuit_auth;
4+
pub use biscuit_auth::builder_ext::BuilderExt;
5+
pub use biscuit_auth::macros::*;
6+
use quickwit_authorize::{
7+
Authorization, AuthorizationError, AuthorizationToken, StreamAuthorization,
8+
};
69

710
use crate::cluster::FetchClusterStateRequest;
811
use crate::control_plane::{AdviseResetShardsRequest, GetOrCreateOpenShardsRequest};

quickwit/quickwit-serve/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ warp = { workspace = true }
5050
zstd = { workspace = true }
5151

5252
quickwit-actors = { workspace = true }
53+
quickwit-authorize = { workspace = true, features = ["enterprise"], optional = true }
5354
quickwit-cluster = { workspace = true }
5455
quickwit-common = { workspace = true }
5556
quickwit-config = { workspace = true }
@@ -97,4 +98,5 @@ quickwit-storage = { workspace = true, features = ["testsuite"] }
9798
pprof = [
9899
"dep:pprof"
99100
]
101+
enterprise = ["dep:quickwit-authorize"]
100102
testsuite = []

0 commit comments

Comments
 (0)