mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
refactor: route IAM reads through app context (#3786)
This commit is contained in:
@@ -5,15 +5,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
## Current Context
|
||||
|
||||
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
||||
- Branch: `overtrue/arch-runtime-context-consumer-batch`
|
||||
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168/API-169/API-170/API-171/API-172/API-173/API-174/API-175/API-176/API-177`.
|
||||
- Based on: API-170 merged in PR #3783; this branch batches API-171 through
|
||||
API-177 on top of latest `main`.
|
||||
- Branch: `overtrue/arch-iam-global-read-batch`
|
||||
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123/API-124/API-125/API-126/API-127/API-128/API-129/API-130/API-131/API-132/API-133/API-134/API-135/API-136/API-137/API-138/API-139/API-140/API-141/API-142/API-143/API-144/API-145/API-146/API-147/API-148/API-149/API-150/API-151/API-152/API-153/API-154/API-155/API-156/API-157/API-158/API-159/API-160/API-161/API-162/API-163/API-164/API-165/API-166/API-167/API-168/API-169/API-170/API-171/API-172/API-173/API-174/API-175/API-176/API-177/API-178`.
|
||||
- Based on: API-171 through API-177 prepared in PR #3785; this branch batches
|
||||
the next IAM consumer migration on top of that branch.
|
||||
- PR type for this branch: `consumer-migration`
|
||||
- Runtime behavior changes: none.
|
||||
- Rust code changes: route replication pool, outbound TLS generation, runtime
|
||||
region, KMS encryption service, runtime support handles, S3 Select DB, and
|
||||
internode RPC metrics through AppContext-first resolvers.
|
||||
region, KMS encryption service, runtime support handles, S3 Select DB,
|
||||
internode RPC metrics, and IAM authorization/handler reads through
|
||||
AppContext-first resolvers.
|
||||
- CI/script changes: lock completed owner and test/fuzz boundaries against
|
||||
bare/glob imports, scattered raw ECStore facade subpaths, and startup
|
||||
runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade
|
||||
@@ -22,7 +23,7 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
and storage owner thin bridge regressions, plus app context and notify
|
||||
event-bridge thin module regressions; accept the reviewed AppContext resolver
|
||||
reverse dependencies in the layer baseline.
|
||||
- Docs changes: record the API-136 through API-177 owner facade cleanup.
|
||||
- Docs changes: record the API-136 through API-178 owner facade cleanup.
|
||||
|
||||
## Phase 0 Tasks
|
||||
|
||||
@@ -4556,6 +4557,20 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
metrics scan, Rust risk scan, branch freshness check, and three-expert
|
||||
review.
|
||||
|
||||
- [x] `API-178` Route IAM runtime reads through AppContext.
|
||||
- Do: route auth, storage authorization, admin auth, admin IAM handlers, STS,
|
||||
and table-catalog credential issuance through an AppContext-first ready IAM
|
||||
resolver.
|
||||
- Acceptance: production auth/admin/storage request paths no longer call the
|
||||
IAM global getter directly, while the resolver preserves the legacy ready
|
||||
check and global fallback.
|
||||
- Must preserve: signature secret lookup, access-key validation, S3 policy
|
||||
authorization, table data-plane authorization, admin IAM CRUD, STS temp-user
|
||||
creation, service-account flows, and table credential issuance.
|
||||
- Verification: RustFS compile coverage, targeted context resolver tests,
|
||||
migration guard, layer guard, formatting, diff hygiene, residual IAM getter
|
||||
scan, Rust risk scan, branch freshness check, and three-expert review.
|
||||
|
||||
## Next PRs
|
||||
|
||||
1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries.
|
||||
@@ -4643,11 +4658,30 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
| Quality/architecture | pass | API-177 keeps internode RPC metrics behind an AppContext-first resolver across HTTP and gRPC RPC paths. |
|
||||
| Migration preservation | pass | Request counters, byte accounting, transport backend labels, and error metrics preserve existing global fallback behavior. |
|
||||
| Testing/verification | pass | RustFS focused compile, targeted context resolver test, formatting, migration/layer guards, diff hygiene, residual internode metrics scan, and Rust risk scan passed for API-177. |
|
||||
| Quality/architecture | pass | API-178 keeps ready IAM access behind an AppContext-first resolver without widening handler semantics. |
|
||||
| Migration preservation | pass | Auth, storage authorization, admin IAM handlers, STS, and table credential flows keep existing error mapping and ready-check fallback. |
|
||||
| Testing/verification | pass | RustFS focused compile, targeted context resolver test, formatting, migration/layer guards, diff hygiene, residual IAM getter scan, Rust risk scan, and pre-commit passed for API-178. |
|
||||
|
||||
## Verification Notes
|
||||
|
||||
Passed before push:
|
||||
|
||||
- Issue #660 API-178 current slice:
|
||||
- `cargo check --tests -p rustfs`: passed.
|
||||
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
|
||||
passed.
|
||||
- `cargo fmt --all`: passed.
|
||||
- `cargo fmt --all --check`: passed.
|
||||
- `git diff --check`: passed.
|
||||
- `bash -n scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||
- IAM getter scan: passed; production auth/admin/storage IAM reads now go
|
||||
through the AppContext ready IAM resolver.
|
||||
- Rust risk scan: no new production unwrap/expect, panic/todo/unsafe, or cast
|
||||
risks added.
|
||||
- `make pre-commit`: passed.
|
||||
|
||||
- Issue #660 API-176 current slice:
|
||||
- `cargo check --tests -p rustfs`: passed.
|
||||
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
|
||||
|
||||
@@ -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