mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-06 21:33:14 +00:00
refactor: route IAM reads through app context (#3786)
This commit is contained in:
@@ -56,7 +56,7 @@ pub async fn validate_admin_request(
|
||||
actions: Vec<Action>,
|
||||
remote_addr: Option<std::net::SocketAddr>,
|
||||
) -> S3Result<()> {
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam not init"));
|
||||
};
|
||||
let ctx = AuthContext {
|
||||
@@ -146,7 +146,7 @@ pub async fn validate_admin_request_with_bucket_object(
|
||||
remote_addr: Option<std::net::SocketAddr>,
|
||||
resource: AdminResourceScope<'_>,
|
||||
) -> S3Result<()> {
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam not init"));
|
||||
};
|
||||
let ctx = AuthContext {
|
||||
|
||||
@@ -69,7 +69,7 @@ impl Operation for AccountInfoHandler {
|
||||
|
||||
let (cred, owner) = authenticate_request(&req.headers, &req.uri, &input_cred).await?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ impl Operation for ListGroups {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -180,7 +180,7 @@ impl Operation for GetGroup {
|
||||
GroupQuery::default()
|
||||
}
|
||||
};
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -256,7 +256,7 @@ impl Operation for DeleteGroup {
|
||||
|
||||
let group = decode_delete_group_name(¶ms)?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -394,7 +394,7 @@ impl Operation for SetGroupStatus {
|
||||
return Err(s3_error!(InvalidArgument, "group is required"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -537,7 +537,7 @@ impl Operation for UpdateGroupMembers {
|
||||
"admin group state"
|
||||
);
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
|
||||
@@ -58,7 +58,8 @@ impl Operation for IsAdminHandler {
|
||||
true
|
||||
} else {
|
||||
let empty_claims = HashMap::new();
|
||||
let iam_store = rustfs_iam::get().map_err(|_| s3_error!(InternalError, "iam not init"))?;
|
||||
let iam_store =
|
||||
crate::app::context::resolve_ready_iam_handle().map_err(|_| s3_error!(InternalError, "iam not init"))?;
|
||||
let conditions = get_condition_values(&req.headers, &cred, None, None, None);
|
||||
iam_store
|
||||
.is_allowed(&Args {
|
||||
|
||||
@@ -144,7 +144,7 @@ impl Operation for ListCannedPolicies {
|
||||
}
|
||||
};
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -252,7 +252,7 @@ impl Operation for AddCannedPolicy {
|
||||
if policy.version.is_empty() {
|
||||
return Err(s3_error!(InvalidArgument, "policy version is required"));
|
||||
}
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -340,7 +340,7 @@ impl Operation for InfoCannedPolicy {
|
||||
return Err(s3_error!(InvalidArgument, "too many policies"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -401,7 +401,7 @@ impl Operation for RemoveCannedPolicy {
|
||||
return Err(s3_error!(InvalidArgument, "policy name is required"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -492,7 +492,7 @@ impl Operation for SetPolicyForUserOrGroup {
|
||||
return Err(s3_error!(InvalidArgument, "user or group is required"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -825,7 +825,9 @@ async fn handle_builtin_policy_entities(req: S3Request<Body>) -> S3Result<S3Resp
|
||||
|
||||
let query = parse_policy_entities_query(req.uri.query());
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam not init"));
|
||||
};
|
||||
|
||||
let all_group_policy_mappings = collect_group_policy_mappings(&iam_store, &[]).await?;
|
||||
let users = iam_store.list_users().await.map_err(|e| {
|
||||
@@ -959,7 +961,9 @@ async fn handle_builtin_policy_association(req: S3Request<Body>, is_attach: bool
|
||||
.map_err(|e| s3_error!(InvalidRequest, "unmarshal policy association body failed, e: {:?}", e))?;
|
||||
validate_policy_association_req(&assoc_req)?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam not init"));
|
||||
};
|
||||
|
||||
let (target_name, is_group, existing_policies) = if !assoc_req.user.is_empty() {
|
||||
match iam_store.is_temp_user(&assoc_req.user).await {
|
||||
|
||||
@@ -292,7 +292,7 @@ impl Operation for AddServiceAccount {
|
||||
req_is_derived_cred = true;
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -513,7 +513,7 @@ impl Operation for UpdateServiceAccount {
|
||||
return Err(s3_error!(InvalidRequest, "get cred failed"));
|
||||
};
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -642,7 +642,7 @@ impl Operation for InfoServiceAccount {
|
||||
|
||||
let access_key = query.access_key;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -719,7 +719,7 @@ impl Operation for TemporaryAccountInfo {
|
||||
let (cred, owner) =
|
||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -789,7 +789,7 @@ impl Operation for InfoAccessKey {
|
||||
query.access_key
|
||||
};
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -912,7 +912,7 @@ impl Operation for ListServiceAccount {
|
||||
// cred.parent_user
|
||||
// };
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -1049,7 +1049,7 @@ impl Operation for ListAccessKeysBulk {
|
||||
let (cred, owner) =
|
||||
check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -1252,7 +1252,7 @@ impl Operation for DeleteServiceAccount {
|
||||
return Err(s3_error!(InvalidArgument, "access key is empty"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ async fn handle_assume_role(
|
||||
return Err(s3_error!(InvalidRequest, "AccessDenied"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
let conditions = crate::auth::get_condition_values(&headers, &cred, None, None, remote_addr);
|
||||
@@ -438,7 +438,8 @@ pub async fn create_oidc_sts_credentials(
|
||||
new_cred.groups = Some(groups.to_vec());
|
||||
|
||||
// Store temp user in IAM
|
||||
let iam_store = rustfs_iam::get().map_err(|_| s3_error!(InternalError, "IAM not initialized"))?;
|
||||
let iam_store =
|
||||
crate::app::context::resolve_ready_iam_handle().map_err(|_| s3_error!(InternalError, "IAM not initialized"))?;
|
||||
|
||||
let updated_at = iam_store
|
||||
.set_temp_user(&new_cred.access_key, &new_cred, None)
|
||||
|
||||
@@ -701,7 +701,7 @@ impl TableCredentialIssuer for IamTableCredentialIssuer {
|
||||
.map_err(|err| s3_error!(InternalError, "failed to generate table credentials: {}", err))?;
|
||||
bind_table_credential_parent(&mut credential, principal);
|
||||
|
||||
let iam_store = rustfs_iam::get().map_err(|_| s3_error!(InternalError, "iam not init"))?;
|
||||
let iam_store = crate::app::context::resolve_ready_iam_handle().map_err(|_| s3_error!(InternalError, "iam not init"))?;
|
||||
iam_store
|
||||
.set_temp_user(&credential.access_key, &credential, None)
|
||||
.await
|
||||
|
||||
@@ -227,7 +227,7 @@ impl Operation for AddUser {
|
||||
return Err(s3_error!(InvalidArgument, "cannot create a user with the system access key"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -356,7 +356,7 @@ impl Operation for SetUserStatus {
|
||||
let status = AccountStatus::try_from(query.status.as_deref().unwrap_or_default())
|
||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InvalidArgument, e))?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -408,7 +408,7 @@ impl Operation for ListUsers {
|
||||
}
|
||||
};
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -481,7 +481,7 @@ impl Operation for RemoveUser {
|
||||
return Err(s3_error!(InvalidArgument, "cannot remove the current user"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -558,7 +558,7 @@ impl Operation for GetUserInfo {
|
||||
return Err(s3_error!(InvalidArgument, "access key is empty"));
|
||||
}
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam is not initialized"));
|
||||
};
|
||||
|
||||
@@ -654,7 +654,7 @@ impl Operation for ExportIam {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
@@ -888,7 +888,7 @@ impl Operation for ImportIam {
|
||||
let mut zip_reader =
|
||||
ZipArchive::new(Cursor::new(body)).map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?;
|
||||
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InvalidRequest, "iam not init"));
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ use super::{BucketBandwidthMonitor, DynReplicationPool, NotificationSys, Replica
|
||||
use crate::config::RustFSBufferConfig;
|
||||
use rustfs_config::server_config::Config;
|
||||
use rustfs_credentials::Credentials;
|
||||
use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_iam::{error::Error as IamError, store::object::ObjectStore, sys::IamSys};
|
||||
use rustfs_io_metrics::{PerformanceMetrics, internode_metrics::InternodeMetrics};
|
||||
use rustfs_kms::{KmsServiceManager, ObjectEncryptionService, init_global_kms_service_manager};
|
||||
use rustfs_lock::LockClient;
|
||||
@@ -84,6 +84,11 @@ pub fn resolve_iam_handle() -> Option<Arc<IamSys<ObjectStore>>> {
|
||||
resolve_iam_handle_with(get_global_app_context(), rustfs_iam::get_global_iam_sys)
|
||||
}
|
||||
|
||||
/// Resolve a ready IAM system handle using AppContext-first precedence.
|
||||
pub fn resolve_ready_iam_handle() -> rustfs_iam::error::Result<Arc<IamSys<ObjectStore>>> {
|
||||
resolve_ready_iam_handle_with(get_global_app_context(), rustfs_iam::get)
|
||||
}
|
||||
|
||||
/// Resolve bucket metadata handle using AppContext-first precedence.
|
||||
pub fn resolve_bucket_metadata_handle() -> Option<Arc<RwLock<BucketMetadataSys>>> {
|
||||
resolve_bucket_metadata_handle_with(get_global_app_context(), || default_bucket_metadata_interface().handle())
|
||||
@@ -290,6 +295,21 @@ fn resolve_iam_handle_with(
|
||||
context.map(|context| context.iam().handle()).or_else(fallback)
|
||||
}
|
||||
|
||||
fn resolve_ready_iam_handle_with(
|
||||
context: Option<Arc<AppContext>>,
|
||||
fallback: impl FnOnce() -> rustfs_iam::error::Result<Arc<IamSys<ObjectStore>>>,
|
||||
) -> rustfs_iam::error::Result<Arc<IamSys<ObjectStore>>> {
|
||||
if let Some(context) = context {
|
||||
if context.iam().is_ready() {
|
||||
return Ok(context.iam().handle());
|
||||
}
|
||||
|
||||
return Err(IamError::IamSysNotInitialized);
|
||||
}
|
||||
|
||||
fallback()
|
||||
}
|
||||
|
||||
fn resolve_bucket_metadata_handle_with(
|
||||
context: Option<Arc<AppContext>>,
|
||||
fallback: impl FnOnce() -> Option<Arc<RwLock<BucketMetadataSys>>>,
|
||||
|
||||
+2
-2
@@ -186,7 +186,7 @@ impl S3Auth for IAMAuth {
|
||||
return Ok(key);
|
||||
}
|
||||
|
||||
if let Ok(iam_store) = rustfs_iam::get() {
|
||||
if let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() {
|
||||
// Use check_key instead of get_user to ensure user is loaded from disk if not in cache
|
||||
// This is important for newly created users that may not be in cache yet.
|
||||
// check_key will automatically attempt to load the user from disk if not found in cache.
|
||||
@@ -341,7 +341,7 @@ pub async fn check_key_valid(session_token: &str, access_key: &str) -> S3Result<
|
||||
let sys_cred = cred.clone();
|
||||
|
||||
if !constant_time_eq(&cred.access_key, access_key) {
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(S3Error::with_message(
|
||||
S3ErrorCode::InternalError,
|
||||
format!("check_key_valid {:?}", IamError::IamSysNotInitialized),
|
||||
|
||||
@@ -328,7 +328,7 @@ pub async fn authorize_request<T>(req: &mut S3Request<T>, action: Action) -> S3R
|
||||
let version_id = req_info.version_id.clone();
|
||||
|
||||
if let Some(cred) = &cred {
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(S3Error::with_message(
|
||||
S3ErrorCode::InternalError,
|
||||
format!("authorize_request {:?}", IamError::IamSysNotInitialized),
|
||||
@@ -841,7 +841,7 @@ async fn authorize_table_data_plane_if_needed(
|
||||
let Some(resource) = table_data_plane_resource_for_request(bucket, object).await? else {
|
||||
return Ok(());
|
||||
};
|
||||
let Ok(iam_store) = rustfs_iam::get() else {
|
||||
let Ok(iam_store) = crate::app::context::resolve_ready_iam_handle() else {
|
||||
return Err(s3_error!(InternalError, "iam not init"));
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user