refactor: route admin runtime reads through app context (#3773)

This commit is contained in:
Zhengchao An
2026-06-23 10:30:55 +08:00
committed by GitHub
parent 9615086154
commit 0acc8f8b43
18 changed files with 215 additions and 78 deletions
+39 -6
View File
@@ -5,13 +5,13 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
## Current Context ## Current Context
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
- Branch: `overtrue/arch-rpc-node-context-resolvers` - Branch: `overtrue/arch-admin-runtime-context-resolvers`
- 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`. - 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`.
- Based on: `main` after API-158. - Based on: API-159 branch while PR #3772 is pending.
- PR type for this branch: `consumer-migration` - PR type for this branch: `consumer-migration`
- Runtime behavior changes: none. - Runtime behavior changes: none.
- Rust code changes: route RPC node lock-client and local-node-name consumers - Rust code changes: route admin/server action credentials, region, and server
through AppContext resolvers with legacy global fallback. config consumers through AppContext resolvers with legacy global fallback.
- CI/script changes: lock completed owner and test/fuzz boundaries against - CI/script changes: lock completed owner and test/fuzz boundaries against
bare/glob imports, scattered raw ECStore facade subpaths, and startup bare/glob imports, scattered raw ECStore facade subpaths, and startup
runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade runtime/root-server/table/S3/app shared/app bucket/app ECStore/admin facade
@@ -19,7 +19,7 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
ECStore compatibility bypasses, plus runtime crate, owner crate, test/fuzz, ECStore compatibility bypasses, plus runtime crate, owner crate, test/fuzz,
and storage owner thin bridge regressions, plus app context and notify and storage owner thin bridge regressions, plus app context and notify
event-bridge thin module regressions. event-bridge thin module regressions.
- Docs changes: record the 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 owner facade cleanup. - Docs changes: record the 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 owner facade cleanup.
## Phase 0 Tasks ## Phase 0 Tasks
@@ -4298,6 +4298,20 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
migration guard, formatting, diff hygiene, Rust risk scan, branch freshness migration guard, formatting, diff hygiene, Rust risk scan, branch freshness
check, pre-commit, and three-expert review. check, pre-commit, and three-expert review.
- [x] `API-160` Route admin runtime reads through AppContext resolvers.
- Do: add action-credential and region AppContext interfaces, resolver
helpers, default legacy adapters, and use them with the existing server
config resolver across admin/server read paths.
- Acceptance: admin handlers and router code no longer directly read action
credentials, region, or server config globals when an AppContext resolver
owns that boundary.
- Must preserve: admin auth decisions, object-ZIP token signing, object lambda
signing region fallback, OIDC restart detection, site replication metadata,
and legacy global fallback when AppContext is absent.
- Verification: RustFS compile coverage, targeted context resolver tests,
migration guard, formatting, diff hygiene, Rust risk scan, branch freshness
check, pre-commit, and three-expert review.
## Next PRs ## Next PRs
1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries. 1. `consumer-migration`: continue reducing direct global reads behind AppContext resolver boundaries.
@@ -4330,11 +4344,30 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
| Quality/architecture | pass | API-159 keeps RPC node lock client and node identity reads behind AppContext resolver boundaries. | | Quality/architecture | pass | API-159 keeps RPC node lock client and node identity reads behind AppContext resolver boundaries. |
| Migration preservation | pass | RPC lock initialization errors and health metric node-name inputs keep legacy fallback behavior. | | Migration preservation | pass | RPC lock initialization errors and health metric node-name inputs keep legacy fallback behavior. |
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration guard, diff hygiene, Rust risk scan, and pre-commit passed for API-159. | | Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration guard, diff hygiene, Rust risk scan, and pre-commit passed for API-159. |
| Quality/architecture | pass | API-160 keeps admin runtime action credentials, region, and server config reads behind AppContext resolver boundaries. |
| Migration preservation | pass | Admin authorization, object-ZIP token encryption, object-lambda signing, OIDC restart detection, and site replication metadata keep legacy fallback behavior. |
| Testing/verification | pass | RustFS focused compile, targeted context tests, formatting, migration guard, diff hygiene, Rust risk scan, and pre-commit passed for API-160. |
## Verification Notes ## Verification Notes
Passed before push: Passed before push:
- Issue #660 API-160 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.
- `make pre-commit`: passed.
- AppContext admin runtime resolver scan: passed; direct admin action
credential, server config, and region global reads are isolated to
AppContext default adapters or tests.
- Rust risk scan: no new production panic/todo/unsafe/cast risks added; new
unwrap/expect hits are resolver fallback plumbing or test assertions.
- Issue #660 API-159 current slice: - Issue #660 API-159 current slice:
- `cargo check --tests -p rustfs`: passed. - `cargo check --tests -p rustfs`: passed.
- `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`: - `cargo test -p rustfs resolver_helpers_are_context_first_and_fallback_when_context_is_absent --lib`:
+3 -4
View File
@@ -15,13 +15,12 @@
use super::super::versioning_sys::BucketVersioningSys; use super::super::versioning_sys::BucketVersioningSys;
use crate::admin::auth::authenticate_request; use crate::admin::auth::authenticate_request;
use crate::admin::router::{AdminOperation, Operation, S3Router}; use crate::admin::router::{AdminOperation, Operation, S3Router};
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_action_credentials, resolve_object_store_handle};
use crate::auth::get_condition_values; use crate::auth::get_condition_values;
use crate::server::{ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, RemoteAddr};
use http::{HeaderMap, HeaderValue}; use http::{HeaderMap, HeaderValue};
use hyper::{Method, StatusCode}; use hyper::{Method, StatusCode};
use matchit::Params; use matchit::Params;
use rustfs_credentials::get_global_action_cred;
use rustfs_policy::policy::BucketPolicy; use rustfs_policy::policy::BucketPolicy;
use rustfs_policy::policy::default::DEFAULT_POLICIES; use rustfs_policy::policy::default::DEFAULT_POLICIES;
use rustfs_policy::policy::{Args, action::Action, action::S3Action}; use rustfs_policy::policy::{Args, action::Action, action::S3Action};
@@ -145,10 +144,10 @@ impl Operation for AccountInfoHandler {
cred.access_key.clone() cred.access_key.clone()
}; };
let Some(admin_cred) = get_global_action_cred() else { let Some(admin_cred) = resolve_action_credentials() else {
return Err(S3Error::with_message( return Err(S3Error::with_message(
S3ErrorCode::InternalError, S3ErrorCode::InternalError,
"get_global_action_cred failed".to_string(), "action credentials are not initialized".to_string(),
)); ));
}; };
+3 -5
View File
@@ -24,7 +24,7 @@ use crate::admin::service::config::{
validate_server_config, validate_server_config,
}; };
use crate::admin::utils::{encode_compatible_admin_payload, is_compat_admin_request, read_compatible_admin_body}; use crate::admin::utils::{encode_compatible_admin_payload, is_compat_admin_request, read_compatible_admin_body};
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_object_store_handle, resolve_server_config};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::error::ApiError; use crate::error::ApiError;
use crate::server::{ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, RemoteAddr};
@@ -54,9 +54,7 @@ use rustfs_config::oidc::{
OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_CONFIG_URL, OIDC_DISPLAY_NAME, OIDC_EMAIL_CLAIM, OIDC_GROUPS_CLAIM, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_CONFIG_URL, OIDC_DISPLAY_NAME, OIDC_EMAIL_CLAIM, OIDC_GROUPS_CLAIM,
OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_SCOPES, OIDC_USERNAME_CLAIM, OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_SCOPES, OIDC_USERNAME_CLAIM,
}; };
use rustfs_config::server_config::{ use rustfs_config::server_config::{Config as ServerConfig, DEFAULT_KVS, KV, KVS, set_global_server_config};
Config as ServerConfig, DEFAULT_KVS, KV, KVS, get_global_server_config, set_global_server_config,
};
use rustfs_config::{ use rustfs_config::{
COMMENT_KEY, DEFAULT_DELIMITER, ENABLE_KEY, ENV_PREFIX, ENV_SCANNER_ALERT_EXCESS_FOLDERS, COMMENT_KEY, DEFAULT_DELIMITER, ENABLE_KEY, ENV_PREFIX, ENV_SCANNER_ALERT_EXCESS_FOLDERS,
ENV_SCANNER_ALERT_EXCESS_VERSION_SIZE, ENV_SCANNER_ALERT_EXCESS_VERSIONS, ENV_SCANNER_BITROT_CYCLE_SECS, ENV_SCANNER_ALERT_EXCESS_VERSION_SIZE, ENV_SCANNER_ALERT_EXCESS_VERSIONS, ENV_SCANNER_BITROT_CYCLE_SECS,
@@ -727,7 +725,7 @@ async fn load_active_server_config() -> S3Result<ServerConfig> {
return Ok(config); return Ok(config);
} }
get_global_server_config().ok_or_else(|| s3_error!(InternalError, "server config is not initialized")) resolve_server_config().ok_or_else(|| s3_error!(InternalError, "server config is not initialized"))
} }
async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> { async fn save_server_config_to_store(config: &ServerConfig) -> S3Result<()> {
+2 -2
View File
@@ -20,6 +20,7 @@ use crate::{
router::{AdminOperation, Operation, S3Router}, router::{AdminOperation, Operation, S3Router},
utils::has_space_be, utils::has_space_be,
}, },
app::context::resolve_action_credentials,
auth::{check_key_valid, constant_time_eq, get_session_token}, auth::{check_key_valid, constant_time_eq, get_session_token},
server::{ADMIN_PREFIX, RemoteAddr}, server::{ADMIN_PREFIX, RemoteAddr},
}; };
@@ -28,7 +29,6 @@ use hyper::Method;
use matchit::Params; use matchit::Params;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::get_global_action_cred;
use rustfs_iam::error::{is_err_no_such_group, is_err_no_such_user}; use rustfs_iam::error::{is_err_no_such_group, is_err_no_such_user};
use rustfs_madmin::{GroupAddRemove, GroupStatus, SITE_REPL_API_VERSION, SRGroupInfo, SRIAMItem}; use rustfs_madmin::{GroupAddRemove, GroupStatus, SITE_REPL_API_VERSION, SRGroupInfo, SRIAMItem};
use rustfs_policy::policy::action::{Action, AdminAction}; use rustfs_policy::policy::action::{Action, AdminAction};
@@ -551,7 +551,7 @@ impl Operation for UpdateGroupMembers {
)); ));
} }
get_global_action_cred() resolve_action_credentials()
.map(|cred| { .map(|cred| {
if constant_time_eq(&cred.access_key, member) { if constant_time_eq(&cred.access_key, member) {
return Err(S3Error::with_message( return Err(S3Error::with_message(
+2 -2
View File
@@ -13,11 +13,11 @@
// limitations under the License. // limitations under the License.
use crate::admin::router::Operation; use crate::admin::router::Operation;
use crate::app::context::resolve_action_credentials;
use crate::auth::{check_key_valid, constant_time_eq, get_condition_values, get_session_token}; use crate::auth::{check_key_valid, constant_time_eq, get_condition_values, get_session_token};
use http::{HeaderMap, HeaderValue}; use http::{HeaderMap, HeaderValue};
use hyper::StatusCode; use hyper::StatusCode;
use matchit::Params; use matchit::Params;
use rustfs_credentials::get_global_action_cred;
use rustfs_policy::policy::Args; use rustfs_policy::policy::Args;
use rustfs_policy::policy::action::{Action, AdminAction}; use rustfs_policy::policy::action::{Action, AdminAction};
use s3s::header::CONTENT_TYPE; use s3s::header::CONTENT_TYPE;
@@ -47,7 +47,7 @@ impl Operation for IsAdminHandler {
let access_key_to_check = input_cred.access_key.clone(); let access_key_to_check = input_cred.access_key.clone();
// Check if the user is admin: root user check, then evaluate through the policy engine // Check if the user is admin: root user check, then evaluate through the policy engine
let is_admin = if let Some(sys_cred) = get_global_action_cred() { let is_admin = if let Some(sys_cred) = resolve_action_credentials() {
constant_time_eq(&access_key_to_check, &sys_cred.access_key) constant_time_eq(&access_key_to_check, &sys_cred.access_key)
|| constant_time_eq(&cred.parent_user, &sys_cred.access_key) || constant_time_eq(&cred.parent_user, &sys_cred.access_key)
} else { } else {
@@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::super::get_global_region;
use crate::admin::router::{ADMIN_OBJECT_ZIP_DOWNLOADS_PATH, AdminOperation, Operation, S3Router}; use crate::admin::router::{ADMIN_OBJECT_ZIP_DOWNLOADS_PATH, AdminOperation, Operation, S3Router};
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_action_credentials, resolve_object_store_handle, resolve_region};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::error::ApiError; use crate::error::ApiError;
use crate::license::license_check; use crate::license::license_check;
@@ -31,7 +30,6 @@ use hyper::{Method, Uri};
use matchit::Params; use matchit::Params;
use rand::RngExt; use rand::RngExt;
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::get_global_action_cred;
use rustfs_policy::policy::action::{Action, S3Action}; use rustfs_policy::policy::action::{Action, S3Action};
use rustfs_storage_api::{BucketOperations, ListOperations as _, ObjectIO as _, ObjectOperations as _, bucket::BucketOptions}; use rustfs_storage_api::{BucketOperations, ListOperations as _, ObjectIO as _, ObjectOperations as _, bucket::BucketOptions};
use rustfs_trusted_proxies::{ClientInfo, ValidationMode}; use rustfs_trusted_proxies::{ClientInfo, ValidationMode};
@@ -206,7 +204,7 @@ impl From<ObjectZipDownloadReqInfoSnapshot> for ReqInfo {
bucket: snapshot.bucket, bucket: snapshot.bucket,
object: snapshot.object, object: snapshot.object,
version_id: snapshot.version_id, version_id: snapshot.version_id,
region: get_global_region(), region: resolve_region(),
request_context: None, request_context: None,
} }
} }
@@ -284,7 +282,7 @@ impl From<ClientInfoSnapshot> for ClientInfo {
fn download_token_encryption_key() -> S3Result<[u8; 32]> { fn download_token_encryption_key() -> S3Result<[u8; 32]> {
let credentials = let credentials =
get_global_action_cred().ok_or_else(|| s3_error!(InternalError, "global action credentials are not initialized"))?; resolve_action_credentials().ok_or_else(|| s3_error!(InternalError, "global action credentials are not initialized"))?;
if credentials.secret_key.is_empty() { if credentials.secret_key.is_empty() {
return Err(s3_error!(InternalError, "global action credentials are not initialized")); return Err(s3_error!(InternalError, "global action credentials are not initialized"));
} }
@@ -401,7 +399,7 @@ async fn authenticate_object_zip_download_request(req: &mut S3Request<Body>) ->
req.extensions.insert(ReqInfo { req.extensions.insert(ReqInfo {
cred: Some(cred), cred: Some(cred),
is_owner: owner, is_owner: owner,
region: get_global_region(), region: resolve_region(),
request_context: req.extensions.get().cloned(), request_context: req.extensions.get().cloned(),
..Default::default() ..Default::default()
}); });
@@ -698,7 +696,7 @@ async fn authorize_zip_items_for_download(record: &ObjectZipDownloadToken, items
extensions extensions
}, },
credentials: None, credentials: None,
region: get_global_region(), region: resolve_region(),
service: None, service: None,
trailing_headers: None, trailing_headers: None,
}; };
@@ -1093,7 +1091,7 @@ mod tests {
"object ZIP download token should carry an authenticated payload" "object ZIP download token should carry an authenticated payload"
); );
assert!( assert!(
src.contains("get_global_action_cred"), src.contains("resolve_action_credentials"),
"object ZIP download token should be verifiable by any node sharing global credentials" "object ZIP download token should be verifiable by any node sharing global credentials"
); );
assert!( assert!(
@@ -1378,7 +1376,7 @@ mod tests {
} }
fn ensure_test_signing_credentials() { fn ensure_test_signing_credentials() {
if get_global_action_cred().is_none() { if resolve_action_credentials().is_none() {
let _ = init_global_action_credentials( let _ = init_global_action_credentials(
Some("TESTROOTACCESSKEY".to_string()), Some("TESTROOTACCESSKEY".to_string()),
Some("TESTROOTSECRET1234567890".to_string()), Some("TESTROOTSECRET1234567890".to_string()),
@@ -1401,7 +1399,7 @@ mod tests {
bucket: Some("photos".to_string()), bucket: Some("photos".to_string()),
object: None, object: None,
version_id: None, version_id: None,
region: get_global_region(), region: resolve_region(),
request_context: None, request_context: None,
} }
} }
+2 -3
View File
@@ -16,7 +16,7 @@ use super::super::{read_admin_config_without_migrate, save_admin_server_config};
use super::sts::create_oidc_sts_credentials; use super::sts::create_oidc_sts_credentials;
use crate::admin::auth::validate_admin_request; use crate::admin::auth::validate_admin_request;
use crate::admin::router::{AdminOperation, Operation, S3Router}; use crate::admin::router::{AdminOperation, Operation, S3Router};
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_object_store_handle, resolve_server_config};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::server::{ADMIN_PREFIX, MINIO_ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, MINIO_ADMIN_PREFIX, RemoteAddr};
use http::StatusCode; use http::StatusCode;
@@ -29,7 +29,6 @@ use rustfs_config::oidc::{
OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_ROLES_CLAIM, OIDC_SCOPES, OIDC_USERNAME_CLAIM, OIDC_REDIRECT_URI, OIDC_REDIRECT_URI_DYNAMIC, OIDC_ROLE_POLICY, OIDC_ROLES_CLAIM, OIDC_SCOPES, OIDC_USERNAME_CLAIM,
}; };
use rustfs_config::server_config::Config as ServerConfig; use rustfs_config::server_config::Config as ServerConfig;
use rustfs_config::server_config::get_global_server_config;
use rustfs_config::{DEFAULT_DELIMITER, ENABLE_KEY, EnableState, MAX_ADMIN_REQUEST_BODY_SIZE}; use rustfs_config::{DEFAULT_DELIMITER, ENABLE_KEY, EnableState, MAX_ADMIN_REQUEST_BODY_SIZE};
use rustfs_policy::policy::action::{Action, AdminAction}; use rustfs_policy::policy::action::{Action, AdminAction};
use rustfs_utils::egress::validate_outbound_url; use rustfs_utils::egress::validate_outbound_url;
@@ -827,7 +826,7 @@ fn provider_instance_key(provider_id: &str) -> String {
} }
fn oidc_restart_required(config: &ServerConfig) -> bool { fn oidc_restart_required(config: &ServerConfig) -> bool {
let active_config = get_global_server_config(); let active_config = resolve_server_config();
oidc_restart_required_from_active_config(config, active_config.as_ref()) oidc_restart_required_from_active_config(config, active_config.as_ref())
} }
+3 -3
View File
@@ -20,6 +20,7 @@ use crate::{
router::{AdminOperation, Operation, S3Router}, router::{AdminOperation, Operation, S3Router},
utils::{encode_compatible_admin_payload, has_space_be, read_compatible_admin_body}, utils::{encode_compatible_admin_payload, has_space_be, read_compatible_admin_body},
}, },
app::context::resolve_action_credentials,
auth::{check_key_valid, get_session_token}, auth::{check_key_valid, get_session_token},
server::{ADMIN_PREFIX, RemoteAddr}, server::{ADMIN_PREFIX, RemoteAddr},
}; };
@@ -27,7 +28,6 @@ use http::{HeaderMap, StatusCode};
use hyper::Method; use hyper::Method;
use matchit::Params; use matchit::Params;
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::get_global_action_cred;
use rustfs_iam::error::is_err_no_such_user; use rustfs_iam::error::is_err_no_such_user;
use rustfs_iam::store::MappedPolicy; use rustfs_iam::store::MappedPolicy;
use rustfs_madmin::{ use rustfs_madmin::{
@@ -520,7 +520,7 @@ impl Operation for SetPolicyForUserOrGroup {
} }
}; };
let Some(sys_cred) = get_global_action_cred() else { let Some(sys_cred) = resolve_action_credentials() else {
return Err(s3_error!(InternalError, "failed to load global credentials")); return Err(s3_error!(InternalError, "failed to load global credentials"));
}; };
@@ -982,7 +982,7 @@ async fn handle_builtin_policy_association(req: S3Request<Body>, is_attach: bool
} }
} }
let Some(sys_cred) = get_global_action_cred() else { let Some(sys_cred) = resolve_action_credentials() else {
return Err(s3_error!(InternalError, "get global action cred failed")); return Err(s3_error!(InternalError, "get global action cred failed"));
}; };
+4 -3
View File
@@ -16,6 +16,7 @@ use super::iam_error::iam_error_to_s3_error;
use crate::admin::access_key_identity; use crate::admin::access_key_identity;
use crate::admin::handlers::site_replication::site_replication_iam_change_hook; use crate::admin::handlers::site_replication::site_replication_iam_change_hook;
use crate::admin::utils::{encode_compatible_admin_payload, has_space_be, is_compat_admin_request, read_compatible_admin_body}; use crate::admin::utils::{encode_compatible_admin_payload, has_space_be, is_compat_admin_request, read_compatible_admin_body};
use crate::app::context::resolve_action_credentials;
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::{ADMIN_PREFIX, RemoteAddr}; use crate::server::{ADMIN_PREFIX, RemoteAddr};
use crate::{ use crate::{
@@ -26,7 +27,7 @@ use http::HeaderMap;
use hyper::{Method, StatusCode}; use hyper::{Method, StatusCode};
use matchit::Params; use matchit::Params;
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::{Credentials as StoredCredentials, get_global_action_cred}; use rustfs_credentials::Credentials as StoredCredentials;
use rustfs_iam::error::{is_err_no_such_service_account, is_err_no_such_temp_account}; use rustfs_iam::error::{is_err_no_such_service_account, is_err_no_such_temp_account};
use rustfs_iam::store::Store as IamStore; use rustfs_iam::store::Store as IamStore;
use rustfs_iam::sys::{NewServiceAccountOpts, UpdateServiceAccountOpts}; use rustfs_iam::sys::{NewServiceAccountOpts, UpdateServiceAccountOpts};
@@ -267,7 +268,7 @@ impl Operation for AddServiceAccount {
None None
}; };
let Some(sys_cred) = get_global_action_cred() else { let Some(sys_cred) = resolve_action_credentials() else {
return Err(s3_error!(InvalidRequest, "get sys cred failed")); return Err(s3_error!(InvalidRequest, "get sys cred failed"));
}; };
@@ -1120,7 +1121,7 @@ impl Operation for ListAccessKeysBulk {
.into_keys() .into_keys()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if let Some(sys_cred) = get_global_action_cred() { if let Some(sys_cred) = resolve_action_credentials() {
users.push(sys_cred.access_key); users.push(sys_cred.access_key);
} }
users users
@@ -25,7 +25,7 @@ use super::super::replication::{ResyncOpts, get_global_replication_pool};
use super::super::target::{ARN, BucketTarget, BucketTargetType, BucketTargets, Credentials}; use super::super::target::{ARN, BucketTarget, BucketTargetType, BucketTargets, Credentials};
use super::super::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _}; use super::super::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _};
use super::super::{delete_admin_config, read_admin_config, save_admin_config}; use super::super::{delete_admin_config, read_admin_config, save_admin_config};
use super::super::{get_global_deployment_id, get_global_endpoints_opt, get_global_region, global_rustfs_port}; use super::super::{get_global_deployment_id, get_global_endpoints_opt, global_rustfs_port};
use crate::admin::auth::validate_admin_request; use crate::admin::auth::validate_admin_request;
use crate::admin::router::{AdminOperation, Operation, S3Router}; use crate::admin::router::{AdminOperation, Operation, S3Router};
use crate::admin::site_replication_identity::{ use crate::admin::site_replication_identity::{
@@ -33,7 +33,7 @@ use crate::admin::site_replication_identity::{
site_identity_key, site_identity_key,
}; };
use crate::admin::utils::{encode_compatible_admin_payload, read_compatible_admin_body}; use crate::admin::utils::{encode_compatible_admin_payload, read_compatible_admin_body};
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_object_store_handle, resolve_region, resolve_server_config};
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::config::get_config_snapshot; use crate::config::get_config_snapshot;
use crate::error::ApiError; use crate::error::ApiError;
@@ -45,7 +45,6 @@ use http::header::{CONTENT_TYPE, HOST};
use http::{HeaderMap, HeaderValue, Uri}; use http::{HeaderMap, HeaderValue, Uri};
use hyper::{Method, StatusCode}; use hyper::{Method, StatusCode};
use matchit::Params; use matchit::Params;
use rustfs_config::server_config::get_global_server_config;
use rustfs_config::{ use rustfs_config::{
DEFAULT_CONSOLE_ADDRESS, DEFAULT_DELIMITER, DEFAULT_RUSTFS_TLS_PATH, ENV_RUSTFS_CONSOLE_ADDRESS, ENV_RUSTFS_TLS_PATH, DEFAULT_CONSOLE_ADDRESS, DEFAULT_DELIMITER, DEFAULT_RUSTFS_TLS_PATH, ENV_RUSTFS_CONSOLE_ADDRESS, ENV_RUSTFS_TLS_PATH,
MAX_ADMIN_REQUEST_BODY_SIZE, MAX_ADMIN_REQUEST_BODY_SIZE,
@@ -783,7 +782,7 @@ fn ldap_settings_from_kvs(kvs: &rustfs_config::server_config::KVS) -> (LDAPSetti
} }
fn load_ldap_idp_settings() -> (LDAPSettings, LDAPConfigSettings) { fn load_ldap_idp_settings() -> (LDAPSettings, LDAPConfigSettings) {
let Some(config) = get_global_server_config() else { let Some(config) = resolve_server_config() else {
return (LDAPSettings::default(), LDAPConfigSettings::default()); return (LDAPSettings::default(), LDAPConfigSettings::default());
}; };
@@ -1231,7 +1230,7 @@ async fn send_peer_admin_request<T: Serialize>(
access_key, access_key,
secret_key, secret_key,
"", "",
get_global_region() resolve_region()
.map(|region| region.to_string()) .map(|region| region.to_string())
.as_deref() .as_deref()
.unwrap_or("us-east-1"), .unwrap_or("us-east-1"),
@@ -1344,7 +1343,7 @@ async fn send_peer_admin_get_request(endpoint: &str, path: &str, access_key: &st
access_key, access_key,
secret_key, secret_key,
"", "",
get_global_region() resolve_region()
.map(|region| region.to_string()) .map(|region| region.to_string())
.as_deref() .as_deref()
.unwrap_or("us-east-1"), .unwrap_or("us-east-1"),
@@ -1590,7 +1589,7 @@ async fn build_sr_info(state: &SiteReplicationState, local_peer: &PeerInfo) -> S
let mut entry = SRBucketInfo { let mut entry = SRBucketInfo {
bucket: bucket.name.clone(), bucket: bucket.name.clone(),
created_at: bucket.created, created_at: bucket.created,
location: get_global_region().map(|region| region.to_string()).unwrap_or_default(), location: resolve_region().map(|region| region.to_string()).unwrap_or_default(),
api_version: Some(SITE_REPL_API_VERSION.to_string()), api_version: Some(SITE_REPL_API_VERSION.to_string()),
..Default::default() ..Default::default()
}; };
@@ -2734,7 +2733,7 @@ fn site_replication_bucket_target_for_peer(
let port = parsed.port_or_known_default().ok_or_else(|| { let port = parsed.port_or_known_default().ok_or_else(|| {
S3Error::with_message(S3ErrorCode::InvalidRequest, format!("peer endpoint missing port: {}", peer.endpoint)) S3Error::with_message(S3ErrorCode::InvalidRequest, format!("peer endpoint missing port: {}", peer.endpoint))
})?; })?;
let region = get_global_region() let region = resolve_region()
.map(|region| region.to_string()) .map(|region| region.to_string())
.filter(|region| !region.is_empty()) .filter(|region| !region.is_empty())
.unwrap_or_else(|| "us-east-1".to_string()); .unwrap_or_else(|| "us-east-1".to_string());
@@ -4231,7 +4230,7 @@ impl Operation for SRPeerGetIDPSettingsHandler {
if let Some(oidc) = get_oidc() { if let Some(oidc) = get_oidc() {
let providers = oidc.list_providers(); let providers = oidc.list_providers();
settings.open_id.enabled = !providers.is_empty(); settings.open_id.enabled = !providers.is_empty();
settings.open_id.region = get_global_region().map(|region| region.to_string()).unwrap_or_default(); settings.open_id.region = resolve_region().map(|region| region.to_string()).unwrap_or_default();
for provider in providers { for provider in providers {
let Some(config) = oidc.get_provider_config(&provider.provider_id) else { let Some(config) = oidc.get_provider_config(&provider.provider_id) else {
+2 -2
View File
@@ -19,6 +19,7 @@ use crate::{
handlers::site_replication::site_replication_iam_change_hook, handlers::site_replication::site_replication_iam_change_hook,
router::{AdminOperation, Operation, S3Router}, router::{AdminOperation, Operation, S3Router},
}, },
app::context::resolve_action_credentials,
auth::{check_key_valid, extract_string_list_claim, get_session_token}, auth::{check_key_valid, extract_string_list_claim, get_session_token},
server::ADMIN_PREFIX, server::ADMIN_PREFIX,
server::RemoteAddr, server::RemoteAddr,
@@ -28,7 +29,6 @@ use http::header::HeaderValue;
use hyper::Method; use hyper::Method;
use matchit::Params; use matchit::Params;
use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE;
use rustfs_credentials::get_global_action_cred;
use rustfs_iam::{manager::get_token_signing_key, oidc::OidcClaims, sys::SESSION_POLICY_NAME}; use rustfs_iam::{manager::get_token_signing_key, oidc::OidcClaims, sys::SESSION_POLICY_NAME};
use rustfs_madmin::{SITE_REPL_API_VERSION, SRIAMItem, SRSTSCredential}; use rustfs_madmin::{SITE_REPL_API_VERSION, SRIAMItem, SRSTSCredential};
use rustfs_policy::{ use rustfs_policy::{
@@ -262,7 +262,7 @@ async fn handle_assume_role(
.await .await
.map_err(|_| s3_error!(InternalError, "set_temp_user failed"))?; .map_err(|_| s3_error!(InternalError, "set_temp_user failed"))?;
let root_access_key = get_global_action_cred().map(|cred| cred.access_key); let root_access_key = resolve_action_credentials().map(|cred| cred.access_key);
if root_access_key.as_deref() != Some(new_cred.parent_user.as_str()) if root_access_key.as_deref() != Some(new_cred.parent_user.as_str())
&& let Err(err) = site_replication_iam_change_hook(SRIAMItem { && let Err(err) = site_replication_iam_change_hook(SRIAMItem {
r#type: "sts-credential".to_string(), r#type: "sts-credential".to_string(),
+5 -4
View File
@@ -21,13 +21,14 @@ use crate::{
router::{AdminOperation, Operation, S3Router}, router::{AdminOperation, Operation, S3Router},
utils::{encode_compatible_admin_payload, has_space_be, read_compatible_admin_body}, utils::{encode_compatible_admin_payload, has_space_be, read_compatible_admin_body},
}, },
app::context::resolve_action_credentials,
auth::{check_key_valid, constant_time_eq, get_session_token}, auth::{check_key_valid, constant_time_eq, get_session_token},
server::RemoteAddr, server::RemoteAddr,
}; };
use http::{HeaderMap, StatusCode}; use http::{HeaderMap, StatusCode};
use matchit::Params; use matchit::Params;
use rustfs_config::{MAX_ADMIN_REQUEST_BODY_SIZE, MAX_IAM_IMPORT_SIZE}; use rustfs_config::{MAX_ADMIN_REQUEST_BODY_SIZE, MAX_IAM_IMPORT_SIZE};
use rustfs_credentials::{Credentials, get_global_action_cred}; use rustfs_credentials::Credentials;
use rustfs_iam::{ use rustfs_iam::{
store::{GroupInfo, MappedPolicy, UserType}, store::{GroupInfo, MappedPolicy, UserType},
sys::{NewServiceAccountOpts, UpdateServiceAccountOpts}, sys::{NewServiceAccountOpts, UpdateServiceAccountOpts},
@@ -220,7 +221,7 @@ impl Operation for AddUser {
return Err(s3_error!(InvalidArgument, "secret key is required")); return Err(s3_error!(InvalidArgument, "secret key is required"));
} }
if let Some(sys_cred) = get_global_action_cred() if let Some(sys_cred) = resolve_action_credentials()
&& constant_time_eq(&sys_cred.access_key, ak) && constant_time_eq(&sys_cred.access_key, ak)
{ {
return Err(s3_error!(InvalidArgument, "cannot create a user with the system access key")); return Err(s3_error!(InvalidArgument, "cannot create a user with the system access key"));
@@ -473,7 +474,7 @@ impl Operation for RemoveUser {
return Err(s3_error!(InvalidArgument, "access key is empty")); return Err(s3_error!(InvalidArgument, "access key is empty"));
} }
let sys_cred = get_global_action_cred() let sys_cred = resolve_action_credentials()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InternalError, "failed to load global credentials"))?; .ok_or_else(|| S3Error::with_message(S3ErrorCode::InternalError, "failed to load global credentials"))?;
if ak == sys_cred.access_key || ak == cred.access_key || cred.parent_user == ak { if ak == sys_cred.access_key || ak == cred.access_key || cred.parent_user == ak {
@@ -932,7 +933,7 @@ impl Operation for ImportIam {
} }
} }
let Some(sys_cred) = get_global_action_cred() else { let Some(sys_cred) = resolve_action_credentials() else {
return Err(s3_error!(InvalidRequest, "get sys cred failed")); return Err(s3_error!(InvalidRequest, "get sys cred failed"));
}; };
+1 -6
View File
@@ -137,8 +137,7 @@ mod ecstore_error {
mod ecstore_global { mod ecstore_global {
pub(crate) use crate::storage::ecstore_global::{ pub(crate) use crate::storage::ecstore_global::{
GLOBAL_BOOT_TIME, get_global_bucket_monitor, get_global_deployment_id, get_global_endpoints_opt, get_global_region, GLOBAL_BOOT_TIME, get_global_bucket_monitor, get_global_deployment_id, get_global_endpoints_opt, global_rustfs_port,
global_rustfs_port,
}; };
} }
@@ -525,10 +524,6 @@ pub(crate) fn get_global_endpoints_opt() -> Option<EndpointServerPools> {
ecstore_global::get_global_endpoints_opt() ecstore_global::get_global_endpoints_opt()
} }
pub(crate) fn get_global_region() -> Option<s3s::region::Region> {
ecstore_global::get_global_region()
}
pub(crate) fn global_rustfs_port() -> u16 { pub(crate) fn global_rustfs_port() -> u16 {
ecstore_global::global_rustfs_port() ecstore_global::global_rustfs_port()
} }
+7 -8
View File
@@ -26,10 +26,10 @@ use super::replication::{
use super::target::{BucketTarget, BucketTargetType, BucketTargets}; use super::target::{BucketTarget, BucketTargetType, BucketTargets};
use super::versioning_sys::BucketVersioningSys; use super::versioning_sys::BucketVersioningSys;
use super::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _}; use super::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _};
use super::{get_global_bucket_monitor, get_global_deployment_id, get_global_region}; use super::{get_global_bucket_monitor, get_global_deployment_id};
use crate::admin::console::{is_console_path, make_console_server}; use crate::admin::console::{is_console_path, make_console_server};
use crate::admin::handlers::oidc::is_oidc_path; use crate::admin::handlers::oidc::is_oidc_path;
use crate::app::context::resolve_object_store_handle; use crate::app::context::{resolve_object_store_handle, resolve_region, resolve_server_config};
use crate::app::object_usecase::DefaultObjectUsecase; use crate::app::object_usecase::DefaultObjectUsecase;
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
use crate::error::ApiError; use crate::error::ApiError;
@@ -54,7 +54,6 @@ use matchit::Router;
use reqwest::Url; use reqwest::Url;
use rustfs_config::notify::NOTIFY_WEBHOOK_SUB_SYS; use rustfs_config::notify::NOTIFY_WEBHOOK_SUB_SYS;
use rustfs_config::server_config::Config; use rustfs_config::server_config::Config;
use rustfs_config::server_config::get_global_server_config;
use rustfs_config::{ use rustfs_config::{
ENABLE_KEY, WEBHOOK_AUTH_TOKEN, WEBHOOK_CLIENT_CA, WEBHOOK_CLIENT_CERT, WEBHOOK_CLIENT_KEY, WEBHOOK_ENDPOINT, ENABLE_KEY, WEBHOOK_AUTH_TOKEN, WEBHOOK_CLIENT_CA, WEBHOOK_CLIENT_CERT, WEBHOOK_CLIENT_KEY, WEBHOOK_ENDPOINT,
WEBHOOK_SKIP_TLS_VERIFY, WEBHOOK_SKIP_TLS_VERIFY,
@@ -648,7 +647,7 @@ async fn load_current_server_config() -> S3Result<Config> {
} }
} }
let config = get_global_server_config().ok_or_else(|| s3_error!(InternalError, "server config is not initialized"))?; let config = resolve_server_config().ok_or_else(|| s3_error!(InternalError, "server config is not initialized"))?;
Ok(config) Ok(config)
} }
@@ -751,7 +750,7 @@ fn build_object_lambda_source_url(req: &S3Request<Body>) -> S3Result<String> {
let region = req let region = req
.region .region
.clone() .clone()
.or_else(get_global_region) .or_else(resolve_region)
.map(|value| value.as_str().to_string()) .map(|value| value.as_str().to_string())
.unwrap_or_else(|| "us-east-1".to_string()); .unwrap_or_else(|| "us-east-1".to_string());
let session_token = get_session_token(&req.uri, &req.headers).unwrap_or_default().to_string(); let session_token = get_session_token(&req.uri, &req.headers).unwrap_or_default().to_string();
@@ -1515,7 +1514,7 @@ async fn authorize_replication_extension_request(req: &mut S3Request<Body>, ext_
bucket: Some(ext_req.bucket.clone()), bucket: Some(ext_req.bucket.clone()),
object: None, object: None,
version_id: None, version_id: None,
region: get_global_region(), region: resolve_region(),
..Default::default() ..Default::default()
}); });
@@ -2244,7 +2243,7 @@ async fn authorize_misc_extension_request(req: &mut S3Request<Body>, route: &Mis
bucket, bucket,
object, object,
version_id: None, version_id: None,
region: get_global_region(), region: resolve_region(),
..Default::default() ..Default::default()
}); });
@@ -3663,7 +3662,7 @@ mod tests {
access_key: "rustfsadmin".to_string(), access_key: "rustfsadmin".to_string(),
secret_key: s3s::auth::SecretKey::from("rustfssecret"), secret_key: s3s::auth::SecretKey::from("rustfssecret"),
}), }),
region: get_global_region(), region: resolve_region(),
service: None, service: None,
trailing_headers: None, trailing_headers: None,
}; };
+87 -4
View File
@@ -32,6 +32,7 @@ use super::metadata_sys::BucketMetadataSys;
use super::new_object_layer_fn; use super::new_object_layer_fn;
use crate::config::RustFSBufferConfig; use crate::config::RustFSBufferConfig;
use rustfs_config::server_config::Config; use rustfs_config::server_config::Config;
use rustfs_credentials::Credentials;
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::KmsServiceManager; use rustfs_kms::KmsServiceManager;
use rustfs_lock::LockClient; use rustfs_lock::LockClient;
@@ -93,6 +94,16 @@ pub async fn resolve_local_node_name() -> String {
resolve_local_node_name_with(get_global_app_context(), rustfs_common::get_global_local_node_name).await resolve_local_node_name_with(get_global_app_context(), rustfs_common::get_global_local_node_name).await
} }
/// Resolve action credentials using AppContext-first precedence.
pub fn resolve_action_credentials() -> Option<Credentials> {
resolve_action_credentials_with(get_global_app_context(), || default_action_credential_interface().get())
}
/// Resolve region using AppContext-first precedence.
pub fn resolve_region() -> Option<s3s::region::Region> {
resolve_region_with(get_global_app_context(), || default_region_interface().get())
}
/// Resolve tier config handle using AppContext-first precedence. /// Resolve tier config handle using AppContext-first precedence.
pub fn resolve_tier_config_handle() -> Arc<RwLock<TierConfigMgr>> { pub fn resolve_tier_config_handle() -> Arc<RwLock<TierConfigMgr>> {
resolve_tier_config_handle_with(get_global_app_context(), || default_tier_config_interface().handle()) resolve_tier_config_handle_with(get_global_app_context(), || default_tier_config_interface().handle())
@@ -171,6 +182,22 @@ where
fallback().await fallback().await
} }
fn resolve_action_credentials_with(
context: Option<Arc<AppContext>>,
fallback: impl FnOnce() -> Option<Credentials>,
) -> Option<Credentials> {
context
.map(|context| context.action_credentials().get())
.unwrap_or_else(fallback)
}
fn resolve_region_with(
context: Option<Arc<AppContext>>,
fallback: impl FnOnce() -> Option<s3s::region::Region>,
) -> Option<s3s::region::Region> {
context.map(|context| context.region().get()).unwrap_or_else(fallback)
}
fn resolve_tier_config_handle_with( fn resolve_tier_config_handle_with(
context: Option<Arc<AppContext>>, context: Option<Arc<AppContext>>,
fallback: impl FnOnce() -> Arc<RwLock<TierConfigMgr>>, fallback: impl FnOnce() -> Arc<RwLock<TierConfigMgr>>,
@@ -197,10 +224,11 @@ mod tests {
use super::super::{Endpoints, PoolEndpoints}; use super::super::{Endpoints, PoolEndpoints};
use super::*; use super::*;
use crate::app::context::global::AppContextTestInterfaces; use crate::app::context::global::AppContextTestInterfaces;
use crate::app::context::handles::{default_notify_interface, default_region_interface}; use crate::app::context::handles::default_notify_interface;
use crate::app::context::interfaces::{ use crate::app::context::interfaces::{
BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, ActionCredentialInterface, BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface,
LocalNodeNameInterface, LockClientInterface, ServerConfigInterface, TierConfigInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, RegionInterface, ServerConfigInterface,
TierConfigInterface,
}; };
use crate::config::{RustFSBufferConfig, WorkloadProfile}; use crate::config::{RustFSBufferConfig, WorkloadProfile};
use async_trait::async_trait; use async_trait::async_trait;
@@ -285,6 +313,26 @@ mod tests {
} }
} }
struct TestActionCredentialInterface {
credentials: Option<Credentials>,
}
impl ActionCredentialInterface for TestActionCredentialInterface {
fn get(&self) -> Option<Credentials> {
self.credentials.clone()
}
}
struct TestRegionInterface {
region: Option<s3s::region::Region>,
}
impl RegionInterface for TestRegionInterface {
fn get(&self) -> Option<s3s::region::Region> {
self.region.clone()
}
}
struct TestTierConfigInterface { struct TestTierConfigInterface {
tier_config: Arc<RwLock<TierConfigMgr>>, tier_config: Arc<RwLock<TierConfigMgr>>,
} }
@@ -378,6 +426,16 @@ mod tests {
let fallback_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new()); let fallback_lock_client: Arc<dyn LockClient> = Arc::new(LocalClient::new());
let context_node_name = "context-node".to_string(); let context_node_name = "context-node".to_string();
let fallback_node_name = "fallback-node".to_string(); let fallback_node_name = "fallback-node".to_string();
let context_credentials = Credentials {
access_key: "context-access-key".to_string(),
..Default::default()
};
let fallback_credentials = Credentials {
access_key: "fallback-access-key".to_string(),
..Default::default()
};
let context_region: s3s::region::Region = "context-region".parse().expect("test region");
let fallback_region: s3s::region::Region = "fallback-region".parse().expect("test region");
let context = Arc::new(AppContext::with_test_interfaces( let context = Arc::new(AppContext::with_test_interfaces(
object_store.clone(), object_store.clone(),
@@ -402,7 +460,12 @@ mod tests {
local_node_name: Arc::new(TestLocalNodeNameInterface { local_node_name: Arc::new(TestLocalNodeNameInterface {
name: context_node_name.clone(), name: context_node_name.clone(),
}), }),
region: default_region_interface(), action_credentials: Arc::new(TestActionCredentialInterface {
credentials: Some(context_credentials.clone()),
}),
region: Arc::new(TestRegionInterface {
region: Some(context_region.clone()),
}),
tier_config: Arc::new(TestTierConfigInterface { tier_config: Arc::new(TestTierConfigInterface {
tier_config: tier_config.clone(), tier_config: tier_config.clone(),
}), }),
@@ -442,6 +505,16 @@ mod tests {
resolve_local_node_name_with(Some(context.clone()), || async { fallback_node_name.clone() }).await, resolve_local_node_name_with(Some(context.clone()), || async { fallback_node_name.clone() }).await,
context_node_name context_node_name
); );
assert_eq!(
resolve_action_credentials_with(Some(context.clone()), || Some(fallback_credentials.clone()))
.expect("context action credentials")
.access_key,
context_credentials.access_key
);
assert_eq!(
resolve_region_with(Some(context.clone()), || Some(fallback_region.clone())).expect("context region"),
context_region
);
assert!(Arc::ptr_eq( assert!(Arc::ptr_eq(
&resolve_tier_config_handle_with(Some(context.clone()), TierConfigMgr::new), &resolve_tier_config_handle_with(Some(context.clone()), TierConfigMgr::new),
&tier_config &tier_config
@@ -484,6 +557,16 @@ mod tests {
resolve_local_node_name_with(None, || async { fallback_node_name.clone() }).await, resolve_local_node_name_with(None, || async { fallback_node_name.clone() }).await,
fallback_node_name fallback_node_name
); );
assert_eq!(
resolve_action_credentials_with(None, || Some(fallback_credentials.clone()))
.expect("fallback action credentials")
.access_key,
fallback_credentials.access_key
);
assert_eq!(
resolve_region_with(None, || Some(fallback_region.clone())).expect("fallback region"),
fallback_region
);
assert!(Arc::ptr_eq(&resolve_tier_config_handle_with(None, || tier_config.clone()), &tier_config)); assert!(Arc::ptr_eq(&resolve_tier_config_handle_with(None, || tier_config.clone()), &tier_config));
assert_eq!( assert_eq!(
resolve_server_config_with(None, || Some(server_config.clone())).expect("fallback server config"), resolve_server_config_with(None, || Some(server_config.clone())).expect("fallback server config"),
+15 -5
View File
@@ -14,13 +14,15 @@
use super::super::{ECStore, set_object_store_resolver}; use super::super::{ECStore, set_object_store_resolver};
use super::handles::{ use super::handles::{
IamHandle, KmsHandle, default_bucket_metadata_interface, default_buffer_config_interface, default_endpoints_interface, IamHandle, KmsHandle, default_action_credential_interface, default_bucket_metadata_interface,
default_kms_runtime_interface, default_local_node_name_interface, default_lock_client_interface, default_notify_interface, default_buffer_config_interface, default_endpoints_interface, default_kms_runtime_interface,
default_region_interface, default_server_config_interface, default_tier_config_interface, default_local_node_name_interface, default_lock_client_interface, default_notify_interface, default_region_interface,
default_server_config_interface, default_tier_config_interface,
}; };
use super::interfaces::{ use super::interfaces::{
BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, ActionCredentialInterface, BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface,
LocalNodeNameInterface, LockClientInterface, NotifyInterface, RegionInterface, ServerConfigInterface, TierConfigInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, NotifyInterface, RegionInterface, ServerConfigInterface,
TierConfigInterface,
}; };
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::KmsServiceManager; use rustfs_kms::KmsServiceManager;
@@ -39,6 +41,7 @@ pub struct AppContext {
endpoints: Arc<dyn EndpointsInterface>, endpoints: Arc<dyn EndpointsInterface>,
lock_client: Arc<dyn LockClientInterface>, lock_client: Arc<dyn LockClientInterface>,
local_node_name: Arc<dyn LocalNodeNameInterface>, local_node_name: Arc<dyn LocalNodeNameInterface>,
action_credentials: Arc<dyn ActionCredentialInterface>,
region: Arc<dyn RegionInterface>, region: Arc<dyn RegionInterface>,
tier_config: Arc<dyn TierConfigInterface>, tier_config: Arc<dyn TierConfigInterface>,
server_config: Arc<dyn ServerConfigInterface>, server_config: Arc<dyn ServerConfigInterface>,
@@ -57,6 +60,7 @@ impl AppContext {
endpoints: default_endpoints_interface(), endpoints: default_endpoints_interface(),
lock_client: default_lock_client_interface(), lock_client: default_lock_client_interface(),
local_node_name: default_local_node_name_interface(), local_node_name: default_local_node_name_interface(),
action_credentials: default_action_credential_interface(),
region: default_region_interface(), region: default_region_interface(),
tier_config: default_tier_config_interface(), tier_config: default_tier_config_interface(),
server_config: default_server_config_interface(), server_config: default_server_config_interface(),
@@ -109,6 +113,10 @@ impl AppContext {
self.local_node_name.clone() self.local_node_name.clone()
} }
pub fn action_credentials(&self) -> Arc<dyn ActionCredentialInterface> {
self.action_credentials.clone()
}
pub fn region(&self) -> Arc<dyn RegionInterface> { pub fn region(&self) -> Arc<dyn RegionInterface> {
self.region.clone() self.region.clone()
} }
@@ -136,6 +144,7 @@ pub(super) struct AppContextTestInterfaces {
pub(super) endpoints: Arc<dyn EndpointsInterface>, pub(super) endpoints: Arc<dyn EndpointsInterface>,
pub(super) lock_client: Arc<dyn LockClientInterface>, pub(super) lock_client: Arc<dyn LockClientInterface>,
pub(super) local_node_name: Arc<dyn LocalNodeNameInterface>, pub(super) local_node_name: Arc<dyn LocalNodeNameInterface>,
pub(super) action_credentials: Arc<dyn ActionCredentialInterface>,
pub(super) region: Arc<dyn RegionInterface>, pub(super) region: Arc<dyn RegionInterface>,
pub(super) tier_config: Arc<dyn TierConfigInterface>, pub(super) tier_config: Arc<dyn TierConfigInterface>,
pub(super) server_config: Arc<dyn ServerConfigInterface>, pub(super) server_config: Arc<dyn ServerConfigInterface>,
@@ -155,6 +164,7 @@ impl AppContext {
endpoints: interfaces.endpoints, endpoints: interfaces.endpoints,
lock_client: interfaces.lock_client, lock_client: interfaces.lock_client,
local_node_name: interfaces.local_node_name, local_node_name: interfaces.local_node_name,
action_credentials: interfaces.action_credentials,
region: interfaces.region, region: interfaces.region,
tier_config: interfaces.tier_config, tier_config: interfaces.tier_config,
server_config: interfaces.server_config, server_config: interfaces.server_config,
+18 -2
View File
@@ -17,14 +17,16 @@ use super::super::TierConfigMgr;
use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys}; use super::super::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys};
use super::super::{get_global_endpoints_opt, get_global_lock_client, get_global_region, get_global_tier_config_mgr}; use super::super::{get_global_endpoints_opt, get_global_lock_client, get_global_region, get_global_tier_config_mgr};
use super::interfaces::{ use super::interfaces::{
BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface, KmsRuntimeInterface, ActionCredentialInterface, BucketMetadataInterface, BufferConfigInterface, EndpointsInterface, IamInterface, KmsInterface,
LocalNodeNameInterface, LockClientInterface, NotifyInterface, RegionInterface, ServerConfigInterface, TierConfigInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, NotifyInterface, RegionInterface, ServerConfigInterface,
TierConfigInterface,
}; };
use crate::config::{RustFSBufferConfig, get_global_buffer_config}; use crate::config::{RustFSBufferConfig, get_global_buffer_config};
use async_trait::async_trait; use async_trait::async_trait;
use rustfs_common::get_global_local_node_name; use rustfs_common::get_global_local_node_name;
use rustfs_config::server_config::Config; use rustfs_config::server_config::Config;
use rustfs_config::server_config::get_global_server_config; use rustfs_config::server_config::get_global_server_config;
use rustfs_credentials::{Credentials, get_global_action_cred};
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager}; use rustfs_kms::{KmsServiceManager, get_global_kms_service_manager};
use rustfs_lock::LockClient; use rustfs_lock::LockClient;
@@ -148,6 +150,16 @@ impl LocalNodeNameInterface for LocalNodeNameHandle {
} }
} }
/// Default action credentials interface adapter.
#[derive(Default)]
pub struct ActionCredentialHandle;
impl ActionCredentialInterface for ActionCredentialHandle {
fn get(&self) -> Option<Credentials> {
get_global_action_cred()
}
}
/// Default region interface adapter. /// Default region interface adapter.
#[derive(Default)] #[derive(Default)]
pub struct RegionHandle; pub struct RegionHandle;
@@ -212,6 +224,10 @@ pub fn default_local_node_name_interface() -> Arc<dyn LocalNodeNameInterface> {
Arc::new(LocalNodeNameHandle) Arc::new(LocalNodeNameHandle)
} }
pub fn default_action_credential_interface() -> Arc<dyn ActionCredentialInterface> {
Arc::new(ActionCredentialHandle)
}
pub fn default_region_interface() -> Arc<dyn RegionInterface> { pub fn default_region_interface() -> Arc<dyn RegionInterface> {
Arc::new(RegionHandle) Arc::new(RegionHandle)
} }
+6
View File
@@ -18,6 +18,7 @@ use super::super::metadata_sys::BucketMetadataSys;
use crate::config::RustFSBufferConfig; use crate::config::RustFSBufferConfig;
use async_trait::async_trait; use async_trait::async_trait;
use rustfs_config::server_config::Config; use rustfs_config::server_config::Config;
use rustfs_credentials::Credentials;
use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_iam::{store::object::ObjectStore, sys::IamSys};
use rustfs_kms::KmsServiceManager; use rustfs_kms::KmsServiceManager;
use rustfs_lock::LockClient; use rustfs_lock::LockClient;
@@ -80,6 +81,11 @@ pub trait LocalNodeNameInterface: Send + Sync {
async fn get(&self) -> String; async fn get(&self) -> String;
} }
/// Action credentials interface for admin handler integration.
pub trait ActionCredentialInterface: Send + Sync {
fn get(&self) -> Option<Credentials>;
}
/// Region interface for application-layer use-cases. /// Region interface for application-layer use-cases.
pub trait RegionInterface: Send + Sync { pub trait RegionInterface: Send + Sync {
fn get(&self) -> Option<s3s::region::Region>; fn get(&self) -> Option<s3s::region::Region>;