|
1 | 1 | //! S3 Authentication
|
2 | 2 |
|
3 | 3 | use std::collections::HashMap;
|
| 4 | +use std::fmt::Debug; |
4 | 5 | use std::path::{Path, PathBuf};
|
| 6 | +use std::sync::Arc; |
5 | 7 |
|
6 | 8 | use crate::errors::S3AuthError;
|
7 | 9 | use crate::ops::{ReqContext, S3Operation};
|
8 | 10 | use crate::path::S3Path;
|
9 |
| -use crate::token::database::IndexDB; |
| 11 | +use crate::token::database::{IndexDB, PassiveIndexDB}; |
10 | 12 | use crate::utils::metrics::Mesurable;
|
11 | 13 | use crate::S3Storage;
|
12 | 14 | use crate::{dto::S3AuthContext, ops::S3Handler};
|
@@ -80,30 +82,30 @@ mod authorization {
|
80 | 82 | })
|
81 | 83 | }
|
82 | 84 |
|
| 85 | + pub fn match_listops(&self, bucket: &str) -> bool { |
| 86 | + self.operations.contains(&"BucketList".to_string()) |
| 87 | + && self.bucket_matcher.is_match(bucket) |
| 88 | + } |
| 89 | + |
83 | 90 | pub fn matches(&self, operation: &S3Operation, bucket: &str, path: Option<&str>) -> bool {
|
84 | 91 | if !self.operations.contains(&operation.to_string()) {
|
85 | 92 | debug!("not match ops");
|
86 | 93 | return false;
|
87 | 94 | }
|
88 | 95 |
|
89 |
| - if !self.bucket_matcher.is_match(bucket) { |
| 96 | + if bucket != "*" && !self.bucket_matcher.is_match(bucket) { |
90 | 97 | debug!("not match bucket");
|
91 | 98 | return false;
|
92 | 99 | }
|
| 100 | + |
93 | 101 | if let Some(ref path_matcher) = self.path_matcher {
|
94 | 102 | if let Some(path) = path {
|
95 | 103 | debug!("attempt to path matching");
|
96 | 104 | let matches = path_matcher.matches(&PathBuf::from(path));
|
97 |
| - matches ^ self.path_matcher_inverted |
98 |
| - } else { |
99 |
| - // TODO |
100 |
| - // if there is no path but requested in a path required endpoint, it should not be possible |
101 |
| - // there is no such case yet this is exploitable |
102 |
| - true |
| 105 | + return matches ^ self.path_matcher_inverted; |
103 | 106 | }
|
104 |
| - } else { |
105 |
| - true |
106 |
| - } |
| 107 | + }; |
| 108 | + true |
107 | 109 | }
|
108 | 110 | }
|
109 | 111 |
|
@@ -164,14 +166,21 @@ use tracing::debug;
|
164 | 166 | /// S3 Authentication Provider
|
165 | 167 |
|
166 | 168 | #[async_trait]
|
167 |
| -pub trait S3Auth: Mesurable { |
| 169 | +pub trait S3Auth: Mesurable + Debug { |
168 | 170 | /// lookup `secret_access_key` by `access_key_id`
|
169 | 171 | async fn get_secret_access_key(
|
170 | 172 | &self,
|
171 | 173 | context: &mut S3AuthContext<'_>,
|
172 | 174 | access_key_id: &str,
|
173 | 175 | ) -> Result<String, S3AuthError>;
|
174 | 176 |
|
| 177 | + async fn get_listops_matchers( |
| 178 | + &self, |
| 179 | + _context: &S3AuthContext<'_>, |
| 180 | + ) -> Result<Arc<Vec<Permission>>, S3AuthError> { |
| 181 | + Err(S3AuthError::AuthServiceUnavailable) |
| 182 | + } |
| 183 | + |
175 | 184 | async fn authorize_query(
|
176 | 185 | &self,
|
177 | 186 | _ctx: &'_ ReqContext<'_>,
|
@@ -252,6 +261,21 @@ impl S3Auth for RwLock<ACLAuth> {
|
252 | 261 | Err(S3AuthError::NotSignedUp)
|
253 | 262 | }
|
254 | 263 |
|
| 264 | + async fn get_listops_matchers( |
| 265 | + &self, |
| 266 | + context: &S3AuthContext<'_>, |
| 267 | + ) -> Result<Arc<Vec<Permission>>, S3AuthError> { |
| 268 | + if let Some(access_id) = context.access_id { |
| 269 | + self.read() |
| 270 | + .await |
| 271 | + .indexdb |
| 272 | + .get_roles_as_permission(&access_id) |
| 273 | + .ok_or(S3AuthError::MissingToken) |
| 274 | + } else { |
| 275 | + Err(S3AuthError::MissingToken) |
| 276 | + } |
| 277 | + } |
| 278 | + |
255 | 279 | async fn authorize_public_query(&self, ctx: &'_ ReqContext<'_>) -> Result<(), S3AuthError> {
|
256 | 280 | let readed = self.read().await;
|
257 | 281 | if let S3Path::Object { bucket, key } = ctx.path {
|
@@ -318,7 +342,9 @@ impl S3Auth for RwLock<ACLAuth> {
|
318 | 342 | }
|
319 | 343 | let is_valid_origin = {
|
320 | 344 | let read_guard = self.read().await;
|
321 |
| - (token.origin == bucket) ^ read_guard.indexdb.validate_orign(bucket, &token) |
| 345 | + (bucket == "*") |
| 346 | + || (token.origin == bucket) |
| 347 | + ^ read_guard.indexdb.validate_orign(bucket, &token) |
322 | 348 | };
|
323 | 349 | if is_valid_origin {
|
324 | 350 | return Ok(());
|
|
0 commit comments