mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-26 05:56:50 +00:00
Signed-off-by: loverustfs <github@rustfs.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+1
-1
@@ -82,7 +82,7 @@ tokio-stream.workspace = true
|
|||||||
tokio-util.workspace = true
|
tokio-util.workspace = true
|
||||||
tonic = { workspace = true }
|
tonic = { workspace = true }
|
||||||
tower.workspace = true
|
tower.workspace = true
|
||||||
tower-http = { workspace = true, features = ["trace", "compression-full", "cors", "catch-panic", "timeout", "limit", "request-id"] }
|
tower-http = { workspace = true, features = ["trace", "compression-full", "cors", "catch-panic", "timeout", "limit", "request-id", "add-extension"] }
|
||||||
|
|
||||||
# Serialization and Data Formats
|
# Serialization and Data Formats
|
||||||
bytes = { workspace = true }
|
bytes = { workspace = true }
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ pub async fn validate_admin_request(
|
|||||||
is_owner: bool,
|
is_owner: bool,
|
||||||
deny_only: bool,
|
deny_only: bool,
|
||||||
actions: Vec<Action>,
|
actions: Vec<Action>,
|
||||||
|
remote_addr: Option<std::net::SocketAddr>,
|
||||||
) -> S3Result<()> {
|
) -> S3Result<()> {
|
||||||
let Ok(iam_store) = rustfs_iam::get() else {
|
let Ok(iam_store) = rustfs_iam::get() else {
|
||||||
return Err(s3_error!(InternalError, "iam not init"));
|
return Err(s3_error!(InternalError, "iam not init"));
|
||||||
};
|
};
|
||||||
for action in actions {
|
for action in actions {
|
||||||
match check_admin_request_auth(iam_store.clone(), headers, cred, is_owner, deny_only, action).await {
|
match check_admin_request_auth(iam_store.clone(), headers, cred, is_owner, deny_only, action, remote_addr).await {
|
||||||
Ok(_) => return Ok(()),
|
Ok(_) => return Ok(()),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
continue;
|
continue;
|
||||||
@@ -53,8 +54,9 @@ async fn check_admin_request_auth(
|
|||||||
is_owner: bool,
|
is_owner: bool,
|
||||||
deny_only: bool,
|
deny_only: bool,
|
||||||
action: Action,
|
action: Action,
|
||||||
|
remote_addr: Option<std::net::SocketAddr>,
|
||||||
) -> S3Result<()> {
|
) -> S3Result<()> {
|
||||||
let conditions = get_condition_values(headers, cred, None, None);
|
let conditions = get_condition_values(headers, cred, None, None, remote_addr);
|
||||||
|
|
||||||
if !iam_store
|
if !iam_store
|
||||||
.is_allowed(&Args {
|
.is_allowed(&Args {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ use crate::auth::check_key_valid;
|
|||||||
use crate::auth::get_condition_values;
|
use crate::auth::get_condition_values;
|
||||||
use crate::auth::get_session_token;
|
use crate::auth::get_session_token;
|
||||||
use crate::error::ApiError;
|
use crate::error::ApiError;
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
use http::{HeaderMap, HeaderValue, Uri};
|
use http::{HeaderMap, HeaderValue, Uri};
|
||||||
@@ -210,7 +211,8 @@ impl Operation for AccountInfoHandler {
|
|||||||
let claims = cred.claims.as_ref().unwrap_or(&default_claims);
|
let claims = cred.claims.as_ref().unwrap_or(&default_claims);
|
||||||
|
|
||||||
let cred_clone = cred.clone();
|
let cred_clone = cred.clone();
|
||||||
let conditions = get_condition_values(&req.headers, &cred_clone, None, None);
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
|
let conditions = get_condition_values(&req.headers, &cred_clone, None, None, remote_addr);
|
||||||
let cred_clone = Arc::new(cred_clone);
|
let cred_clone = Arc::new(cred_clone);
|
||||||
let conditions = Arc::new(conditions);
|
let conditions = Arc::new(conditions);
|
||||||
|
|
||||||
@@ -405,12 +407,14 @@ impl Operation for ServerInfoHandler {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
validate_admin_request(
|
validate_admin_request(
|
||||||
&req.headers,
|
&req.headers,
|
||||||
&cred,
|
&cred,
|
||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
remote_addr,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -451,12 +455,14 @@ impl Operation for StorageInfoHandler {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
validate_admin_request(
|
validate_admin_request(
|
||||||
&req.headers,
|
&req.headers,
|
||||||
&cred,
|
&cred,
|
||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::StorageInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::StorageInfoAdminAction)],
|
||||||
|
remote_addr,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -492,6 +498,7 @@ impl Operation for DataUsageInfoHandler {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
validate_admin_request(
|
validate_admin_request(
|
||||||
&req.headers,
|
&req.headers,
|
||||||
&cred,
|
&cred,
|
||||||
@@ -501,6 +508,7 @@ impl Operation for DataUsageInfoHandler {
|
|||||||
Action::AdminAction(AdminAction::DataUsageInfoAdminAction),
|
Action::AdminAction(AdminAction::DataUsageInfoAdminAction),
|
||||||
Action::S3Action(S3Action::ListBucketAction),
|
Action::S3Action(S3Action::ListBucketAction),
|
||||||
],
|
],
|
||||||
|
remote_addr,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation},
|
admin::{auth::validate_admin_request, router::Operation},
|
||||||
auth::{check_key_valid, get_session_token},
|
auth::{check_key_valid, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -97,6 +98,7 @@ impl Operation for ExportBucketMetadata {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ExportBucketMetadataAction)],
|
vec![Action::AdminAction(AdminAction::ExportBucketMetadataAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -389,6 +391,7 @@ impl Operation for ImportBucketMetadata {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ImportBucketMetadataAction)],
|
vec![Action::AdminAction(AdminAction::ImportBucketMetadataAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
||||||
auth::{check_key_valid, constant_time_eq, get_session_token},
|
auth::{check_key_valid, constant_time_eq, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -57,6 +58,7 @@ impl Operation for ListGroups {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ListGroupsAdminAction)],
|
vec![Action::AdminAction(AdminAction::ListGroupsAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -95,6 +97,7 @@ impl Operation for GetGroup {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::GetGroupAdminAction)],
|
vec![Action::AdminAction(AdminAction::GetGroupAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -142,6 +145,7 @@ impl Operation for SetGroupStatus {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::EnableGroupAdminAction)],
|
vec![Action::AdminAction(AdminAction::EnableGroupAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -209,6 +213,7 @@ impl Operation for UpdateGroupMembers {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::AddUserToGroupAdminAction)],
|
vec![Action::AdminAction(AdminAction::AddUserToGroupAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
use super::Operation;
|
use super::Operation;
|
||||||
use crate::admin::auth::validate_admin_request;
|
use crate::admin::auth::validate_admin_request;
|
||||||
use crate::auth::{check_key_valid, get_session_token};
|
use crate::auth::{check_key_valid, get_session_token};
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use hyper::{HeaderMap, StatusCode};
|
use hyper::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -127,6 +128,7 @@ impl Operation for CreateKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)], // TODO: Add specific KMS action
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)], // TODO: Add specific KMS action
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -205,6 +207,7 @@ impl Operation for DescribeKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -260,6 +263,7 @@ impl Operation for ListKeysHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -321,6 +325,7 @@ impl Operation for GenerateDataKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -386,6 +391,7 @@ impl Operation for KmsStatusHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -443,6 +449,7 @@ impl Operation for KmsConfigHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -487,6 +494,7 @@ impl Operation for KmsClearCacheHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
use super::Operation;
|
use super::Operation;
|
||||||
use crate::admin::auth::validate_admin_request;
|
use crate::admin::auth::validate_admin_request;
|
||||||
use crate::auth::{check_key_valid, get_session_token};
|
use crate::auth::{check_key_valid, get_session_token};
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
|
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
|
||||||
@@ -98,6 +99,7 @@ impl Operation for ConfigureKmsHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -196,6 +198,7 @@ impl Operation for StartKmsHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -329,6 +332,7 @@ impl Operation for StopKmsHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -394,6 +398,7 @@ impl Operation for GetKmsStatusHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -465,6 +470,7 @@ impl Operation for ReconfigureKmsHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
use super::Operation;
|
use super::Operation;
|
||||||
use crate::admin::auth::validate_admin_request;
|
use crate::admin::auth::validate_admin_request;
|
||||||
use crate::auth::{check_key_valid, get_session_token};
|
use crate::auth::{check_key_valid, get_session_token};
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use hyper::{HeaderMap, StatusCode};
|
use hyper::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
|
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
|
||||||
@@ -79,6 +80,7 @@ impl Operation for CreateKmsKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -212,6 +214,7 @@ impl Operation for DeleteKmsKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -360,6 +363,7 @@ impl Operation for CancelKmsKeyDeletionHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -488,6 +492,7 @@ impl Operation for ListKmsKeysHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -599,6 +604,7 @@ impl Operation for DescribeKmsKeyHandler {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
vec![Action::AdminAction(AdminAction::ServerInfoAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
||||||
auth::{check_key_valid, get_session_token},
|
auth::{check_key_valid, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -60,6 +61,7 @@ impl Operation for ListCannedPolicies {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ListUserPoliciesAdminAction)],
|
vec![Action::AdminAction(AdminAction::ListUserPoliciesAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ impl Operation for AddCannedPolicy {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::CreatePolicyAdminAction)],
|
vec![Action::AdminAction(AdminAction::CreatePolicyAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -190,6 +193,7 @@ impl Operation for InfoCannedPolicy {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::GetPolicyAdminAction)],
|
vec![Action::AdminAction(AdminAction::GetPolicyAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -247,6 +251,7 @@ impl Operation for RemoveCannedPolicy {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::DeletePolicyAdminAction)],
|
vec![Action::AdminAction(AdminAction::DeletePolicyAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -307,6 +312,7 @@ impl Operation for SetPolicyForUserOrGroup {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::AttachPolicyAdminAction)],
|
vec![Action::AdminAction(AdminAction::AttachPolicyAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use crate::{
|
|||||||
admin::{auth::validate_admin_request, router::Operation},
|
admin::{auth::validate_admin_request, router::Operation},
|
||||||
auth::{check_key_valid, get_session_token},
|
auth::{check_key_valid, get_session_token},
|
||||||
error::ApiError,
|
error::ApiError,
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ListPools {}
|
pub struct ListPools {}
|
||||||
@@ -53,6 +54,7 @@ impl Operation for ListPools {
|
|||||||
Action::AdminAction(AdminAction::ServerInfoAdminAction),
|
Action::AdminAction(AdminAction::ServerInfoAdminAction),
|
||||||
Action::AdminAction(AdminAction::DecommissionAdminAction),
|
Action::AdminAction(AdminAction::DecommissionAdminAction),
|
||||||
],
|
],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -119,6 +121,7 @@ impl Operation for StatusPool {
|
|||||||
Action::AdminAction(AdminAction::ServerInfoAdminAction),
|
Action::AdminAction(AdminAction::ServerInfoAdminAction),
|
||||||
Action::AdminAction(AdminAction::DecommissionAdminAction),
|
Action::AdminAction(AdminAction::DecommissionAdminAction),
|
||||||
],
|
],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -194,6 +197,7 @@ impl Operation for StartDecommission {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::DecommissionAdminAction)],
|
vec![Action::AdminAction(AdminAction::DecommissionAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -292,6 +296,7 @@ impl Operation for CancelDecommission {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::DecommissionAdminAction)],
|
vec![Action::AdminAction(AdminAction::DecommissionAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation},
|
admin::{auth::validate_admin_request, router::Operation},
|
||||||
auth::{check_key_valid, get_session_token},
|
auth::{check_key_valid, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -103,6 +104,7 @@ impl Operation for RebalanceStart {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -180,6 +182,7 @@ impl Operation for RebalanceStatus {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -297,6 +300,7 @@ impl Operation for RebalanceStop {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
vec![Action::AdminAction(AdminAction::RebalanceAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
use crate::admin::utils::has_space_be;
|
use crate::admin::utils::has_space_be;
|
||||||
use crate::auth::{constant_time_eq, get_condition_values, get_session_token};
|
use crate::auth::{constant_time_eq, get_condition_values, get_session_token};
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use crate::{admin::router::Operation, auth::check_key_valid};
|
use crate::{admin::router::Operation, auth::check_key_valid};
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
@@ -119,7 +120,13 @@ impl Operation for AddServiceAccount {
|
|||||||
groups: &cred.groups,
|
groups: &cred.groups,
|
||||||
action: Action::AdminAction(AdminAction::CreateServiceAccountAdminAction),
|
action: Action::AdminAction(AdminAction::CreateServiceAccountAdminAction),
|
||||||
bucket: "",
|
bucket: "",
|
||||||
conditions: &get_condition_values(&req.headers, &cred, None, None),
|
conditions: &get_condition_values(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
),
|
||||||
is_owner: owner,
|
is_owner: owner,
|
||||||
object: "",
|
object: "",
|
||||||
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
||||||
@@ -270,7 +277,13 @@ impl Operation for UpdateServiceAccount {
|
|||||||
groups: &cred.groups,
|
groups: &cred.groups,
|
||||||
action: Action::AdminAction(AdminAction::UpdateServiceAccountAdminAction),
|
action: Action::AdminAction(AdminAction::UpdateServiceAccountAdminAction),
|
||||||
bucket: "",
|
bucket: "",
|
||||||
conditions: &get_condition_values(&req.headers, &cred, None, None),
|
conditions: &get_condition_values(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
),
|
||||||
is_owner: owner,
|
is_owner: owner,
|
||||||
object: "",
|
object: "",
|
||||||
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
||||||
@@ -363,7 +376,13 @@ impl Operation for InfoServiceAccount {
|
|||||||
groups: &cred.groups,
|
groups: &cred.groups,
|
||||||
action: Action::AdminAction(AdminAction::ListServiceAccountsAdminAction),
|
action: Action::AdminAction(AdminAction::ListServiceAccountsAdminAction),
|
||||||
bucket: "",
|
bucket: "",
|
||||||
conditions: &get_condition_values(&req.headers, &cred, None, None),
|
conditions: &get_condition_values(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
),
|
||||||
is_owner: owner,
|
is_owner: owner,
|
||||||
object: "",
|
object: "",
|
||||||
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
||||||
@@ -491,7 +510,13 @@ impl Operation for ListServiceAccount {
|
|||||||
groups: &cred.groups,
|
groups: &cred.groups,
|
||||||
action: Action::AdminAction(AdminAction::UpdateServiceAccountAdminAction),
|
action: Action::AdminAction(AdminAction::UpdateServiceAccountAdminAction),
|
||||||
bucket: "",
|
bucket: "",
|
||||||
conditions: &get_condition_values(&req.headers, &cred, None, None),
|
conditions: &get_condition_values(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
),
|
||||||
is_owner: owner,
|
is_owner: owner,
|
||||||
object: "",
|
object: "",
|
||||||
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
||||||
@@ -589,7 +614,13 @@ impl Operation for DeleteServiceAccount {
|
|||||||
groups: &cred.groups,
|
groups: &cred.groups,
|
||||||
action: Action::AdminAction(AdminAction::RemoveServiceAccountAdminAction),
|
action: Action::AdminAction(AdminAction::RemoveServiceAccountAdminAction),
|
||||||
bucket: "",
|
bucket: "",
|
||||||
conditions: &get_condition_values(&req.headers, &cred, None, None),
|
conditions: &get_condition_values(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
),
|
||||||
is_owner: owner,
|
is_owner: owner,
|
||||||
object: "",
|
object: "",
|
||||||
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
claims: cred.claims.as_ref().unwrap_or(&HashMap::new()),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation},
|
admin::{auth::validate_admin_request, router::Operation},
|
||||||
auth::{check_key_valid, get_session_token},
|
auth::{check_key_valid, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -90,7 +91,15 @@ impl Operation for AddTier {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::SetTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::SetTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut input = req.input;
|
let mut input = req.input;
|
||||||
let body = match input.store_all_limited(MAX_ADMIN_REQUEST_BODY_SIZE).await {
|
let body = match input.store_all_limited(MAX_ADMIN_REQUEST_BODY_SIZE).await {
|
||||||
@@ -218,7 +227,15 @@ impl Operation for EditTier {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::SetTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::SetTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut input = req.input;
|
let mut input = req.input;
|
||||||
let body = match input.store_all_limited(MAX_ADMIN_REQUEST_BODY_SIZE).await {
|
let body = match input.store_all_limited(MAX_ADMIN_REQUEST_BODY_SIZE).await {
|
||||||
@@ -293,7 +310,15 @@ impl Operation for ListTiers {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::ListTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::ListTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut tier_config_mgr = GLOBAL_TierConfigMgr.read().await;
|
let mut tier_config_mgr = GLOBAL_TierConfigMgr.read().await;
|
||||||
let tiers = tier_config_mgr.list_tiers();
|
let tiers = tier_config_mgr.list_tiers();
|
||||||
@@ -329,7 +354,15 @@ impl Operation for RemoveTier {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::SetTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::SetTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut force: bool = false;
|
let mut force: bool = false;
|
||||||
let force_str = query.force.clone().unwrap_or_default();
|
let force_str = query.force.clone().unwrap_or_default();
|
||||||
@@ -392,7 +425,15 @@ impl Operation for VerifyTier {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::ListTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::ListTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut tier_config_mgr = GLOBAL_TierConfigMgr.write().await;
|
let mut tier_config_mgr = GLOBAL_TierConfigMgr.write().await;
|
||||||
tier_config_mgr.verify(&query.tier.unwrap()).await;
|
tier_config_mgr.verify(&query.tier.unwrap()).await;
|
||||||
@@ -415,7 +456,15 @@ impl Operation for GetTierInfo {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::ListTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::ListTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let query = {
|
let query = {
|
||||||
if let Some(query) = req.uri.query() {
|
if let Some(query) = req.uri.query() {
|
||||||
@@ -467,7 +516,15 @@ impl Operation for ClearTier {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::SetTierAction)]).await?;
|
validate_admin_request(
|
||||||
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::SetTierAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut force: bool = false;
|
let mut force: bool = false;
|
||||||
let force_str = query.force;
|
let force_str = query.force;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
admin::{auth::validate_admin_request, router::Operation, utils::has_space_be},
|
||||||
auth::{check_key_valid, constant_time_eq, get_session_token},
|
auth::{check_key_valid, constant_time_eq, get_session_token},
|
||||||
|
server::RemoteAddr,
|
||||||
};
|
};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
use matchit::Params;
|
use matchit::Params;
|
||||||
@@ -124,6 +125,7 @@ impl Operation for AddUser {
|
|||||||
owner,
|
owner,
|
||||||
deny_only,
|
deny_only,
|
||||||
vec![Action::AdminAction(AdminAction::CreateUserAdminAction)],
|
vec![Action::AdminAction(AdminAction::CreateUserAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -176,6 +178,7 @@ impl Operation for SetUserStatus {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::EnableUserAdminAction)],
|
vec![Action::AdminAction(AdminAction::EnableUserAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -220,6 +223,7 @@ impl Operation for ListUsers {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::ListUsersAdminAction)],
|
vec![Action::AdminAction(AdminAction::ListUsersAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -278,6 +282,7 @@ impl Operation for RemoveUser {
|
|||||||
owner,
|
owner,
|
||||||
false,
|
false,
|
||||||
vec![Action::AdminAction(AdminAction::DeleteUserAdminAction)],
|
vec![Action::AdminAction(AdminAction::DeleteUserAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -377,6 +382,7 @@ impl Operation for GetUserInfo {
|
|||||||
owner,
|
owner,
|
||||||
deny_only,
|
deny_only,
|
||||||
vec![Action::AdminAction(AdminAction::GetUserAdminAction)],
|
vec![Action::AdminAction(AdminAction::GetUserAdminAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -426,8 +432,15 @@ impl Operation for ExportIam {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::ExportIAMAction)])
|
validate_admin_request(
|
||||||
.await?;
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::ExportIAMAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let Ok(iam_store) = rustfs_iam::get() else {
|
let Ok(iam_store) = rustfs_iam::get() else {
|
||||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||||
@@ -633,8 +646,15 @@ impl Operation for ImportIam {
|
|||||||
let (cred, owner) =
|
let (cred, owner) =
|
||||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||||
|
|
||||||
validate_admin_request(&req.headers, &cred, owner, false, vec![Action::AdminAction(AdminAction::ExportIAMAction)])
|
validate_admin_request(
|
||||||
.await?;
|
&req.headers,
|
||||||
|
&cred,
|
||||||
|
owner,
|
||||||
|
false,
|
||||||
|
vec![Action::AdminAction(AdminAction::ExportIAMAction)],
|
||||||
|
req.extensions.get::<RemoteAddr>().map(|a| a.0),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut input = req.input;
|
let mut input = req.input;
|
||||||
let body = match input.store_all_limited(MAX_IAM_IMPORT_SIZE).await {
|
let body = match input.store_all_limited(MAX_IAM_IMPORT_SIZE).await {
|
||||||
|
|||||||
+166
-14
@@ -241,6 +241,7 @@ pub fn get_session_token<'a>(uri: &'a Uri, hds: &'a HeaderMap) -> Option<&'a str
|
|||||||
/// * `cred` - User credentials
|
/// * `cred` - User credentials
|
||||||
/// * `version_id` - Optional version ID of the object
|
/// * `version_id` - Optional version ID of the object
|
||||||
/// * `region` - Optional region/location constraint
|
/// * `region` - Optional region/location constraint
|
||||||
|
/// * `remote_addr` - Optional remote address of the connection
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// * `HashMap<String, Vec<String>>` - Condition values for policy evaluation
|
/// * `HashMap<String, Vec<String>>` - Condition values for policy evaluation
|
||||||
@@ -250,6 +251,7 @@ pub fn get_condition_values(
|
|||||||
cred: &Credentials,
|
cred: &Credentials,
|
||||||
version_id: Option<&str>,
|
version_id: Option<&str>,
|
||||||
region: Option<&str>,
|
region: Option<&str>,
|
||||||
|
remote_addr: Option<std::net::SocketAddr>,
|
||||||
) -> HashMap<String, Vec<String>> {
|
) -> HashMap<String, Vec<String>> {
|
||||||
let username = if cred.is_temp() || cred.is_service_account() {
|
let username = if cred.is_temp() || cred.is_service_account() {
|
||||||
cred.parent_user.clone()
|
cred.parent_user.clone()
|
||||||
@@ -297,12 +299,7 @@ pub fn get_condition_values(
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
// Get remote address from header or use default
|
// Get remote address from header or use default
|
||||||
let remote_addr = header
|
let remote_addr_s = remote_addr.map(|a| a.ip().to_string()).unwrap_or_default();
|
||||||
.get("x-forwarded-for")
|
|
||||||
.and_then(|v| v.to_str().ok())
|
|
||||||
.and_then(|s| s.split(',').next())
|
|
||||||
.or_else(|| header.get("x-real-ip").and_then(|v| v.to_str().ok()))
|
|
||||||
.unwrap_or("127.0.0.1");
|
|
||||||
|
|
||||||
let mut args = HashMap::new();
|
let mut args = HashMap::new();
|
||||||
|
|
||||||
@@ -310,7 +307,7 @@ pub fn get_condition_values(
|
|||||||
args.insert("CurrentTime".to_owned(), vec![curr_time.format(&Rfc3339).unwrap_or_default()]);
|
args.insert("CurrentTime".to_owned(), vec![curr_time.format(&Rfc3339).unwrap_or_default()]);
|
||||||
args.insert("EpochTime".to_owned(), vec![epoch_time.to_string()]);
|
args.insert("EpochTime".to_owned(), vec![epoch_time.to_string()]);
|
||||||
args.insert("SecureTransport".to_owned(), vec![is_tls.to_string()]);
|
args.insert("SecureTransport".to_owned(), vec![is_tls.to_string()]);
|
||||||
args.insert("SourceIp".to_owned(), vec![get_source_ip_raw(header, remote_addr)]);
|
args.insert("SourceIp".to_owned(), vec![get_source_ip_raw(header, &remote_addr_s)]);
|
||||||
|
|
||||||
// Add user agent and referer
|
// Add user agent and referer
|
||||||
if let Some(user_agent) = header.get("user-agent") {
|
if let Some(user_agent) = header.get("user-agent") {
|
||||||
@@ -848,7 +845,7 @@ mod tests {
|
|||||||
let cred = create_test_credentials();
|
let cred = create_test_credentials();
|
||||||
let headers = HeaderMap::new();
|
let headers = HeaderMap::new();
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("userid"), Some(&vec!["test-access-key".to_string()]));
|
assert_eq!(conditions.get("userid"), Some(&vec!["test-access-key".to_string()]));
|
||||||
assert_eq!(conditions.get("username"), Some(&vec!["test-access-key".to_string()]));
|
assert_eq!(conditions.get("username"), Some(&vec!["test-access-key".to_string()]));
|
||||||
@@ -860,7 +857,7 @@ mod tests {
|
|||||||
let cred = create_temp_credentials();
|
let cred = create_temp_credentials();
|
||||||
let headers = HeaderMap::new();
|
let headers = HeaderMap::new();
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("userid"), Some(&vec!["parent-user".to_string()]));
|
assert_eq!(conditions.get("userid"), Some(&vec!["parent-user".to_string()]));
|
||||||
assert_eq!(conditions.get("username"), Some(&vec!["parent-user".to_string()]));
|
assert_eq!(conditions.get("username"), Some(&vec!["parent-user".to_string()]));
|
||||||
@@ -872,7 +869,7 @@ mod tests {
|
|||||||
let cred = create_service_account_credentials();
|
let cred = create_service_account_credentials();
|
||||||
let headers = HeaderMap::new();
|
let headers = HeaderMap::new();
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("userid"), Some(&vec!["service-parent".to_string()]));
|
assert_eq!(conditions.get("userid"), Some(&vec!["service-parent".to_string()]));
|
||||||
assert_eq!(conditions.get("username"), Some(&vec!["service-parent".to_string()]));
|
assert_eq!(conditions.get("username"), Some(&vec!["service-parent".to_string()]));
|
||||||
@@ -887,7 +884,7 @@ mod tests {
|
|||||||
headers.insert("x-amz-object-lock-mode", HeaderValue::from_static("GOVERNANCE"));
|
headers.insert("x-amz-object-lock-mode", HeaderValue::from_static("GOVERNANCE"));
|
||||||
headers.insert("x-amz-object-lock-retain-until-date", HeaderValue::from_static("2024-12-31T23:59:59Z"));
|
headers.insert("x-amz-object-lock-retain-until-date", HeaderValue::from_static("2024-12-31T23:59:59Z"));
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("object-lock-mode"), Some(&vec!["GOVERNANCE".to_string()]));
|
assert_eq!(conditions.get("object-lock-mode"), Some(&vec!["GOVERNANCE".to_string()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -902,7 +899,7 @@ mod tests {
|
|||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.insert("x-amz-signature-age", HeaderValue::from_static("300"));
|
headers.insert("x-amz-signature-age", HeaderValue::from_static("300"));
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("signatureAge"), Some(&vec!["300".to_string()]));
|
assert_eq!(conditions.get("signatureAge"), Some(&vec!["300".to_string()]));
|
||||||
// Verify the header is removed after processing
|
// Verify the header is removed after processing
|
||||||
@@ -919,7 +916,7 @@ mod tests {
|
|||||||
|
|
||||||
let headers = HeaderMap::new();
|
let headers = HeaderMap::new();
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(conditions.get("username"), Some(&vec!["ldap-user".to_string()]));
|
assert_eq!(conditions.get("username"), Some(&vec!["ldap-user".to_string()]));
|
||||||
assert_eq!(conditions.get("groups"), Some(&vec!["group1".to_string(), "group2".to_string()]));
|
assert_eq!(conditions.get("groups"), Some(&vec!["group1".to_string(), "group2".to_string()]));
|
||||||
@@ -932,7 +929,7 @@ mod tests {
|
|||||||
|
|
||||||
let headers = HeaderMap::new();
|
let headers = HeaderMap::new();
|
||||||
|
|
||||||
let conditions = get_condition_values(&headers, &cred, None, None);
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
conditions.get("groups"),
|
conditions.get("groups"),
|
||||||
@@ -1208,4 +1205,159 @@ mod tests {
|
|||||||
assert!(constant_time_eq(key1, key2));
|
assert!(constant_time_eq(key1, key2));
|
||||||
assert!(!constant_time_eq(key1, key3));
|
assert!(!constant_time_eq(key1, key3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_condition_values_source_ip() {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
let cred = Credentials::default();
|
||||||
|
|
||||||
|
// Case 1: No headers, no remote addr -> empty string
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, None);
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "");
|
||||||
|
|
||||||
|
// Case 2: No headers, with remote addr -> remote addr
|
||||||
|
let remote_addr: std::net::SocketAddr = "192.168.0.10:12345".parse().unwrap();
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "192.168.0.10");
|
||||||
|
|
||||||
|
// Case 3: X-Forwarded-For present -> XFF (takes precedence over remote_addr)
|
||||||
|
headers.insert("x-forwarded-for", HeaderValue::from_static("10.0.0.1"));
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "10.0.0.1");
|
||||||
|
|
||||||
|
// Case 4: X-Forwarded-For with multiple IPs -> First IP
|
||||||
|
headers.insert("x-forwarded-for", HeaderValue::from_static("10.0.0.3, 10.0.0.4"));
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "10.0.0.3");
|
||||||
|
|
||||||
|
// Case 5: X-Real-IP present (XFF removed) -> X-Real-IP
|
||||||
|
headers.remove("x-forwarded-for");
|
||||||
|
headers.insert("x-real-ip", HeaderValue::from_static("10.0.0.2"));
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "10.0.0.2");
|
||||||
|
|
||||||
|
// Case 6: Forwarded header present (X-Real-IP removed) -> Forwarded
|
||||||
|
headers.remove("x-real-ip");
|
||||||
|
headers.insert("forwarded", HeaderValue::from_static("for=10.0.0.5;proto=http"));
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "10.0.0.5");
|
||||||
|
|
||||||
|
// Case 7: Forwarded header with quotes and multiple values
|
||||||
|
headers.insert("forwarded", HeaderValue::from_static("for=\"10.0.0.6\", for=10.0.0.7"));
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "10.0.0.6");
|
||||||
|
|
||||||
|
// Case 8: IPv6 Remote Addr
|
||||||
|
let remote_addr_v6: std::net::SocketAddr = "[2001:db8::1]:8080".parse().unwrap();
|
||||||
|
headers.clear();
|
||||||
|
let conditions = get_condition_values(&headers, &cred, None, None, Some(remote_addr_v6));
|
||||||
|
assert_eq!(conditions.get("SourceIp").unwrap()[0], "2001:db8::1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests_policy {
|
||||||
|
use rustfs_policy::policy::action::{Action, S3Action};
|
||||||
|
use rustfs_policy::policy::{Args, BucketPolicy, BucketPolicyArgs, Policy};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_iam_policy_source_ip() {
|
||||||
|
let policy_json = r#"{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["s3:GetObject"],
|
||||||
|
"Resource": ["arn:aws:s3:::mybucket/*"],
|
||||||
|
"Condition": {
|
||||||
|
"IpAddress": {
|
||||||
|
"aws:SourceIp": "192.168.1.0/24"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let policy: Policy = serde_json::from_str(policy_json).expect("Failed to parse IAM policy");
|
||||||
|
|
||||||
|
// Case 1: Matching IP
|
||||||
|
let mut conditions = HashMap::new();
|
||||||
|
conditions.insert("SourceIp".to_string(), vec!["192.168.1.10".to_string()]);
|
||||||
|
|
||||||
|
let claims = HashMap::new();
|
||||||
|
let args = Args {
|
||||||
|
account: "test-account",
|
||||||
|
groups: &None,
|
||||||
|
action: Action::S3Action(S3Action::GetObjectAction),
|
||||||
|
bucket: "mybucket",
|
||||||
|
conditions: &conditions,
|
||||||
|
is_owner: false,
|
||||||
|
object: "myobject",
|
||||||
|
claims: &claims,
|
||||||
|
deny_only: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(policy.is_allowed(&args).await, "IAM Policy should allow matching IP");
|
||||||
|
|
||||||
|
// Case 2: Non-matching IP
|
||||||
|
let mut conditions_fail = HashMap::new();
|
||||||
|
conditions_fail.insert("SourceIp".to_string(), vec!["10.0.0.1".to_string()]);
|
||||||
|
|
||||||
|
let args_fail = Args {
|
||||||
|
conditions: &conditions_fail,
|
||||||
|
..args
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!policy.is_allowed(&args_fail).await, "IAM Policy should deny non-matching IP");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_bucket_policy_source_ip() {
|
||||||
|
let policy_json = r#"{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {"AWS": ["*"]},
|
||||||
|
"Action": ["s3:GetObject"],
|
||||||
|
"Resource": ["arn:aws:s3:::mybucket/*"],
|
||||||
|
"Condition": {
|
||||||
|
"IpAddress": {
|
||||||
|
"aws:SourceIp": "192.168.1.0/24"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let policy: BucketPolicy = serde_json::from_str(policy_json).expect("Failed to parse Bucket policy");
|
||||||
|
|
||||||
|
// Case 1: Matching IP
|
||||||
|
let mut conditions = HashMap::new();
|
||||||
|
conditions.insert("SourceIp".to_string(), vec!["192.168.1.10".to_string()]);
|
||||||
|
|
||||||
|
let args = BucketPolicyArgs {
|
||||||
|
account: "test-account",
|
||||||
|
groups: &None,
|
||||||
|
action: Action::S3Action(S3Action::GetObjectAction),
|
||||||
|
bucket: "mybucket",
|
||||||
|
conditions: &conditions,
|
||||||
|
is_owner: false,
|
||||||
|
object: "myobject",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(policy.is_allowed(&args).await, "Bucket Policy should allow matching IP");
|
||||||
|
|
||||||
|
// Case 2: Non-matching IP
|
||||||
|
let mut conditions_fail = HashMap::new();
|
||||||
|
conditions_fail.insert("SourceIp".to_string(), vec!["10.0.0.1".to_string()]);
|
||||||
|
|
||||||
|
let args_fail = BucketPolicyArgs {
|
||||||
|
conditions: &conditions_fail,
|
||||||
|
..args
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(!policy.is_allowed(&args_fail).await, "Bucket Policy should deny non-matching IP");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use super::compress::{CompressionConfig, CompressionPredicate};
|
|||||||
use crate::admin;
|
use crate::admin;
|
||||||
use crate::auth::IAMAuth;
|
use crate::auth::IAMAuth;
|
||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::server::{ReadinessGateLayer, ServiceState, ServiceStateManager, hybrid::hybrid, layer::RedirectLayer};
|
use crate::server::{ReadinessGateLayer, RemoteAddr, ServiceState, ServiceStateManager, hybrid::hybrid, layer::RedirectLayer};
|
||||||
use crate::storage;
|
use crate::storage;
|
||||||
use crate::storage::tonic_service::make_server;
|
use crate::storage::tonic_service::make_server;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
@@ -44,6 +44,7 @@ use tokio::net::{TcpListener, TcpStream};
|
|||||||
use tokio_rustls::TlsAcceptor;
|
use tokio_rustls::TlsAcceptor;
|
||||||
use tonic::{Request, Status, metadata::MetadataValue};
|
use tonic::{Request, Status, metadata::MetadataValue};
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
|
use tower_http::add_extension::AddExtensionLayer;
|
||||||
use tower_http::catch_panic::CatchPanicLayer;
|
use tower_http::catch_panic::CatchPanicLayer;
|
||||||
use tower_http::compression::CompressionLayer;
|
use tower_http::compression::CompressionLayer;
|
||||||
use tower_http::cors::{AllowOrigin, Any, CorsLayer};
|
use tower_http::cors::{AllowOrigin, Any, CorsLayer};
|
||||||
@@ -528,9 +529,21 @@ fn process_connection(
|
|||||||
let rpc_service = NodeServiceServer::with_interceptor(make_server(), check_auth);
|
let rpc_service = NodeServiceServer::with_interceptor(make_server(), check_auth);
|
||||||
let service = hybrid(s3_service, rpc_service);
|
let service = hybrid(s3_service, rpc_service);
|
||||||
|
|
||||||
|
let remote_addr = match socket.peer_addr() {
|
||||||
|
Ok(addr) => Some(RemoteAddr(addr)),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(
|
||||||
|
error = %e,
|
||||||
|
"Failed to obtain peer address; policy evaluation may fall back to a default source IP"
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let hybrid_service = ServiceBuilder::new()
|
let hybrid_service = ServiceBuilder::new()
|
||||||
.layer(SetRequestIdLayer::x_request_id(MakeRequestUuid))
|
.layer(SetRequestIdLayer::x_request_id(MakeRequestUuid))
|
||||||
.layer(CatchPanicLayer::new())
|
.layer(CatchPanicLayer::new())
|
||||||
|
.layer(AddExtensionLayer::new(remote_addr))
|
||||||
// CRITICAL: Insert ReadinessGateLayer before business logic
|
// CRITICAL: Insert ReadinessGateLayer before business logic
|
||||||
// This stops requests from hitting IAMAuth or Storage if they are not ready.
|
// This stops requests from hitting IAMAuth or Storage if they are not ready.
|
||||||
.layer(ReadinessGateLayer::new(readiness))
|
.layer(ReadinessGateLayer::new(readiness))
|
||||||
|
|||||||
@@ -36,3 +36,6 @@ pub(crate) use service_state::ServiceState;
|
|||||||
pub(crate) use service_state::ServiceStateManager;
|
pub(crate) use service_state::ServiceStateManager;
|
||||||
pub(crate) use service_state::ShutdownSignal;
|
pub(crate) use service_state::ShutdownSignal;
|
||||||
pub(crate) use service_state::wait_for_shutdown;
|
pub(crate) use service_state::wait_for_shutdown;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct RemoteAddr(pub std::net::SocketAddr);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use super::ecfs::FS;
|
use super::ecfs::FS;
|
||||||
use crate::auth::{check_key_valid, get_condition_values, get_session_token};
|
use crate::auth::{check_key_valid, get_condition_values, get_session_token};
|
||||||
use crate::license::license_check;
|
use crate::license::license_check;
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use rustfs_ecstore::bucket::policy_sys::PolicySys;
|
use rustfs_ecstore::bucket::policy_sys::PolicySys;
|
||||||
use rustfs_iam::error::Error as IamError;
|
use rustfs_iam::error::Error as IamError;
|
||||||
use rustfs_policy::policy::action::{Action, S3Action};
|
use rustfs_policy::policy::action::{Action, S3Action};
|
||||||
@@ -36,6 +37,7 @@ pub(crate) struct ReqInfo {
|
|||||||
|
|
||||||
/// Authorizes the request based on the action and credentials.
|
/// Authorizes the request based on the action and credentials.
|
||||||
pub async fn authorize_request<T>(req: &mut S3Request<T>, action: Action) -> S3Result<()> {
|
pub async fn authorize_request<T>(req: &mut S3Request<T>, action: Action) -> S3Result<()> {
|
||||||
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
let req_info = req.extensions.get_mut::<ReqInfo>().expect("ReqInfo not found");
|
let req_info = req.extensions.get_mut::<ReqInfo>().expect("ReqInfo not found");
|
||||||
|
|
||||||
if let Some(cred) = &req_info.cred {
|
if let Some(cred) = &req_info.cred {
|
||||||
@@ -48,7 +50,7 @@ pub async fn authorize_request<T>(req: &mut S3Request<T>, action: Action) -> S3R
|
|||||||
|
|
||||||
let default_claims = HashMap::new();
|
let default_claims = HashMap::new();
|
||||||
let claims = cred.claims.as_ref().unwrap_or(&default_claims);
|
let claims = cred.claims.as_ref().unwrap_or(&default_claims);
|
||||||
let conditions = get_condition_values(&req.headers, cred, req_info.version_id.as_deref(), None);
|
let conditions = get_condition_values(&req.headers, cred, req_info.version_id.as_deref(), None, remote_addr);
|
||||||
|
|
||||||
if action == Action::S3Action(S3Action::DeleteObjectAction)
|
if action == Action::S3Action(S3Action::DeleteObjectAction)
|
||||||
&& req_info.version_id.is_some()
|
&& req_info.version_id.is_some()
|
||||||
@@ -109,6 +111,7 @@ pub async fn authorize_request<T>(req: &mut S3Request<T>, action: Action) -> S3R
|
|||||||
&rustfs_credentials::Credentials::default(),
|
&rustfs_credentials::Credentials::default(),
|
||||||
req_info.version_id.as_deref(),
|
req_info.version_id.as_deref(),
|
||||||
req.region.as_deref(),
|
req.region.as_deref(),
|
||||||
|
remote_addr,
|
||||||
);
|
);
|
||||||
|
|
||||||
if action != Action::S3Action(S3Action::ListAllMyBucketsAction) {
|
if action != Action::S3Action(S3Action::ListAllMyBucketsAction) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use crate::config::workload_profiles::{
|
|||||||
RustFSBufferConfig, WorkloadProfile, get_global_buffer_config, is_buffer_profile_enabled,
|
RustFSBufferConfig, WorkloadProfile, get_global_buffer_config, is_buffer_profile_enabled,
|
||||||
};
|
};
|
||||||
use crate::error::ApiError;
|
use crate::error::ApiError;
|
||||||
|
use crate::server::RemoteAddr;
|
||||||
use crate::storage::concurrency::{
|
use crate::storage::concurrency::{
|
||||||
CachedGetObject, ConcurrencyManager, GetObjectGuard, get_concurrency_aware_buffer_size, get_concurrency_manager,
|
CachedGetObject, ConcurrencyManager, GetObjectGuard, get_concurrency_aware_buffer_size, get_concurrency_manager,
|
||||||
};
|
};
|
||||||
@@ -4689,7 +4690,8 @@ impl S3 for FS {
|
|||||||
.await
|
.await
|
||||||
.map_err(ApiError::from)?;
|
.map_err(ApiError::from)?;
|
||||||
|
|
||||||
let conditions = get_condition_values(&req.headers, &rustfs_credentials::Credentials::default(), None, None);
|
let remote_addr = req.extensions.get::<RemoteAddr>().map(|a| a.0);
|
||||||
|
let conditions = get_condition_values(&req.headers, &rustfs_credentials::Credentials::default(), None, None, remote_addr);
|
||||||
|
|
||||||
let read_only = PolicySys::is_allowed(&BucketPolicyArgs {
|
let read_only = PolicySys::is_allowed(&BucketPolicyArgs {
|
||||||
bucket: &bucket,
|
bucket: &bucket,
|
||||||
|
|||||||
Reference in New Issue
Block a user