diff --git a/rustfs/src/admin/handlers/site_replication.rs b/rustfs/src/admin/handlers/site_replication.rs index ca43c475a..7c9b7bfb7 100644 --- a/rustfs/src/admin/handlers/site_replication.rs +++ b/rustfs/src/admin/handlers/site_replication.rs @@ -32,7 +32,7 @@ use crate::admin::site_replication_identity::{ }; use crate::admin::utils::{encode_compatible_admin_payload, read_compatible_admin_body}; use crate::app::context::{ - resolve_deployment_id, resolve_endpoints_handle, resolve_iam_handle, resolve_object_store_handle, + resolve_deployment_id, resolve_endpoints_handle, resolve_iam_handle, resolve_object_store_handle, resolve_oidc_handle, resolve_outbound_tls_generation, resolve_outbound_tls_state, resolve_region, resolve_replication_pool_handle, resolve_replication_stats_handle, resolve_runtime_port, resolve_server_config, }; @@ -52,7 +52,6 @@ use rustfs_config::{ MAX_ADMIN_REQUEST_BODY_SIZE, }; use rustfs_iam::error::is_err_no_such_service_account; -use rustfs_iam::get_oidc; use rustfs_iam::store::{MappedPolicy, UserType}; use rustfs_iam::sys::{ NewServiceAccountOpts, SITE_REPLICATOR_SERVICE_ACCOUNT, UpdateServiceAccountOpts, get_claims_from_token_with_secret, @@ -4229,7 +4228,7 @@ impl Operation for SRPeerGetIDPSettingsHandler { validate_site_replication_admin_request(&req, AdminAction::SiteReplicationAddAction).await?; let mut settings = IDPSettings::default(); - if let Some(oidc) = get_oidc() { + if let Some(oidc) = resolve_oidc_handle() { let providers = oidc.list_providers(); settings.open_id.enabled = !providers.is_empty(); settings.open_id.region = resolve_region().map(|region| region.to_string()).unwrap_or_default(); diff --git a/rustfs/src/app/context.rs b/rustfs/src/app/context.rs index 304ce8d53..ffdc92c15 100644 --- a/rustfs/src/app/context.rs +++ b/rustfs/src/app/context.rs @@ -37,6 +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::oidc::OidcSys; 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}; @@ -84,6 +85,11 @@ pub fn resolve_iam_handle() -> Option>> { resolve_iam_handle_with(get_global_app_context(), rustfs_iam::get_global_iam_sys) } +/// Resolve OIDC handle using AppContext-first precedence. +pub fn resolve_oidc_handle() -> Option> { + resolve_oidc_handle_with(get_global_app_context(), rustfs_iam::get_oidc) +} + /// Resolve a ready IAM system handle using AppContext-first precedence. pub fn resolve_ready_iam_handle() -> rustfs_iam::error::Result>> { resolve_ready_iam_handle_with(get_global_app_context(), rustfs_iam::get) @@ -295,6 +301,13 @@ fn resolve_iam_handle_with( context.map(|context| context.iam().handle()).or_else(fallback) } +fn resolve_oidc_handle_with( + context: Option>, + fallback: impl FnOnce() -> Option>, +) -> Option> { + context.and_then(|context| context.oidc().handle()).or_else(fallback) +} + fn resolve_ready_iam_handle_with( context: Option>, fallback: impl FnOnce() -> rustfs_iam::error::Result>>, @@ -527,9 +540,9 @@ mod tests { use crate::app::context::interfaces::{ ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BufferConfigInterface, DeploymentIdInterface, EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, - LockClientInterface, LockClientsInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, - ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, ServerConfigInterface, - StorageClassInterface, TierConfigInterface, TierStatsInterface, + LockClientInterface, LockClientsInterface, OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, + RegionInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, + ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, }; use crate::config::{RustFSBufferConfig, WorkloadProfile}; use async_trait::async_trait; @@ -561,6 +574,14 @@ mod tests { } } + struct TestOidcInterface; + + impl OidcInterface for TestOidcInterface { + fn handle(&self) -> Option> { + None + } + } + struct TestKmsInterface { kms: Arc, } @@ -969,6 +990,7 @@ mod tests { object_store.clone(), AppContextTestInterfaces { iam: Arc::new(TestIamInterface { ready: true }), + oidc: Arc::new(TestOidcInterface), kms: Arc::new(TestKmsInterface { kms: context_kms.clone(), }), diff --git a/rustfs/src/app/context/global.rs b/rustfs/src/app/context/global.rs index 031276282..f4efe5296 100644 --- a/rustfs/src/app/context/global.rs +++ b/rustfs/src/app/context/global.rs @@ -18,17 +18,17 @@ use super::handles::{ default_bucket_monitor_interface, default_buffer_config_interface, default_deployment_id_interface, default_endpoints_interface, default_internode_metrics_interface, default_kms_runtime_interface, default_local_node_name_interface, default_lock_client_interface, default_lock_clients_interface, - default_notification_system_interface, default_notify_interface, default_outbound_tls_runtime_interface, - default_performance_metrics_interface, default_region_interface, default_replication_pool_interface, - default_replication_stats_interface, default_runtime_port_interface, default_s3select_db_interface, - default_scanner_metrics_interface, default_server_config_interface, default_storage_class_interface, - default_tier_config_interface, default_tier_stats_interface, + default_notification_system_interface, default_notify_interface, default_oidc_interface, + default_outbound_tls_runtime_interface, default_performance_metrics_interface, default_region_interface, + default_replication_pool_interface, default_replication_stats_interface, default_runtime_port_interface, + default_s3select_db_interface, default_scanner_metrics_interface, default_server_config_interface, + default_storage_class_interface, default_tier_config_interface, default_tier_stats_interface, }; use super::interfaces::{ ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, DeploymentIdInterface, EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface, NotifyInterface, - OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface, + OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, }; @@ -41,6 +41,7 @@ use std::sync::{Arc, OnceLock}; pub struct AppContext { object_store: Arc, iam: Arc, + oidc: Arc, #[allow(dead_code)] kms: Arc, kms_runtime: Arc, @@ -76,6 +77,7 @@ impl AppContext { Self { object_store, iam, + oidc: default_oidc_interface(), kms, kms_runtime: default_kms_runtime_interface(), outbound_tls_runtime: default_outbound_tls_runtime_interface(), @@ -122,6 +124,10 @@ impl AppContext { self.iam.clone() } + pub fn oidc(&self) -> Arc { + self.oidc.clone() + } + #[allow(dead_code)] pub fn kms(&self) -> Arc { self.kms.clone() @@ -235,6 +241,7 @@ impl AppContext { #[cfg(test)] pub(super) struct AppContextTestInterfaces { pub(super) iam: Arc, + pub(super) oidc: Arc, pub(super) kms: Arc, pub(super) kms_runtime: Arc, pub(super) outbound_tls_runtime: Arc, @@ -270,6 +277,7 @@ impl AppContext { Self { object_store, iam: interfaces.iam, + oidc: interfaces.oidc, kms: interfaces.kms, kms_runtime: interfaces.kms_runtime, outbound_tls_runtime: interfaces.outbound_tls_runtime, diff --git a/rustfs/src/app/context/handles.rs b/rustfs/src/app/context/handles.rs index 6abd48008..6e3d81452 100644 --- a/rustfs/src/app/context/handles.rs +++ b/rustfs/src/app/context/handles.rs @@ -26,7 +26,7 @@ use super::interfaces::{ ActionCredentialInterface, BootTimeInterface, BucketMetadataInterface, BucketMonitorInterface, BufferConfigInterface, DeploymentIdInterface, EndpointsInterface, IamInterface, InternodeMetricsInterface, KmsInterface, KmsRuntimeInterface, LocalNodeNameInterface, LockClientInterface, LockClientsInterface, NotificationSystemInterface, NotifyInterface, - OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface, + OidcInterface, OutboundTlsRuntimeInterface, PerformanceMetricsInterface, RegionInterface, ReplicationPoolInterface, ReplicationStatsInterface, RuntimePortInterface, S3SelectDbInterface, ScannerMetricsInterface, ServerConfigInterface, StorageClassInterface, TierConfigInterface, TierStatsInterface, }; @@ -36,7 +36,7 @@ use rustfs_common::get_global_local_node_name; use rustfs_config::server_config::Config; use rustfs_config::server_config::{get_global_server_config, set_global_server_config}; use rustfs_credentials::{Credentials, get_global_action_cred}; -use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; +use rustfs_iam::{get_oidc, oidc::OidcSys, store::object::ObjectStore, sys::IamSys}; use rustfs_io_metrics::{ PerformanceMetrics, global_metrics::get_global_metrics, @@ -76,6 +76,16 @@ impl IamInterface for IamHandle { } } +/// Default OIDC interface adapter. +#[derive(Default)] +pub struct OidcHandle; + +impl OidcInterface for OidcHandle { + fn handle(&self) -> Option> { + get_oidc() + } +} + /// Default KMS interface adapter. #[allow(dead_code)] pub struct KmsHandle { @@ -468,6 +478,10 @@ pub fn default_action_credential_interface() -> Arc Arc { + Arc::new(OidcHandle) +} + pub fn default_region_interface() -> Arc { Arc::new(RegionHandle) } diff --git a/rustfs/src/app/context/interfaces.rs b/rustfs/src/app/context/interfaces.rs index 6c6f12f27..207576e3e 100644 --- a/rustfs/src/app/context/interfaces.rs +++ b/rustfs/src/app/context/interfaces.rs @@ -23,6 +23,7 @@ use crate::config::RustFSBufferConfig; use async_trait::async_trait; use rustfs_config::server_config::Config; use rustfs_credentials::Credentials; +use rustfs_iam::oidc::OidcSys; use rustfs_iam::{store::object::ObjectStore, sys::IamSys}; use rustfs_io_metrics::{PerformanceMetrics, internode_metrics::InternodeMetrics}; use rustfs_kms::KmsServiceManager; @@ -42,6 +43,11 @@ pub trait IamInterface: Send + Sync { fn is_ready(&self) -> bool; } +/// OIDC interface for admin and runtime consumers. +pub trait OidcInterface: Send + Sync { + fn handle(&self) -> Option>; +} + /// KMS interface for application-layer use-cases. #[allow(dead_code)] pub trait KmsInterface: Send + Sync {