From 9c62a24efcc6adc7dbe1ea29a23e4f0862a533b4 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Mon, 29 Jun 2026 12:56:34 +0800 Subject: [PATCH] refactor(runtime): wrap outbound tls globals (#4039) --- crates/common/src/globals.rs | 15 +++++++++++++++ crates/tls-runtime/src/outbound.rs | 10 +++++----- docs/architecture/global-state-inventory.md | 2 +- scripts/check_architecture_migration_rules.sh | 13 +++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/crates/common/src/globals.rs b/crates/common/src/globals.rs index 5600e806c..7e7ab311e 100644 --- a/crates/common/src/globals.rs +++ b/crates/common/src/globals.rs @@ -96,6 +96,16 @@ pub async fn set_global_root_cert(cert: Vec) { *GLOBAL_ROOT_CERT.write().await = Some(cert); } +/// Clear the global root CA certificate for outbound gRPC clients. +pub async fn clear_global_root_cert() { + *GLOBAL_ROOT_CERT.write().await = None; +} + +/// Get the global root CA certificate for outbound gRPC clients. +pub async fn get_global_root_cert() -> Option> { + GLOBAL_ROOT_CERT.read().await.clone() +} + /// Set the global mTLS identity (cert+key PEM) for outbound gRPC clients. /// When set, clients will present this identity to servers requesting/requiring mTLS. /// When None, clients proceed with standard server-authenticated TLS. @@ -106,6 +116,11 @@ pub async fn set_global_mtls_identity(identity: Option) { *GLOBAL_MTLS_IDENTITY.write().await = identity; } +/// Get the global mTLS identity for outbound gRPC clients. +pub async fn get_global_mtls_identity() -> Option { + GLOBAL_MTLS_IDENTITY.read().await.clone() +} + /// Set the global outbound TLS generation. pub fn set_global_outbound_tls_generation(generation: u64) { GLOBAL_OUTBOUND_TLS_GENERATION.store(generation, Ordering::Relaxed); diff --git a/crates/tls-runtime/src/outbound.rs b/crates/tls-runtime/src/outbound.rs index b1bc95f14..11c9c5916 100644 --- a/crates/tls-runtime/src/outbound.rs +++ b/crates/tls-runtime/src/outbound.rs @@ -16,8 +16,8 @@ use crate::material::OutboundTlsMaterial; use crate::metrics::record_outbound_tls_publication; use crate::state::TlsGeneration; use rustfs_common::{ - GLOBAL_MTLS_IDENTITY, GLOBAL_ROOT_CERT, MtlsIdentityPem, get_global_outbound_tls_generation, set_global_mtls_identity, - set_global_outbound_tls_generation, set_global_root_cert, + MtlsIdentityPem, clear_global_root_cert, get_global_mtls_identity, get_global_outbound_tls_generation, get_global_root_cert, + set_global_mtls_identity, set_global_outbound_tls_generation, set_global_root_cert, }; #[derive(Debug, Clone)] @@ -38,7 +38,7 @@ pub async fn publish_global_outbound_tls_state(generation: TlsGeneration, materi if !material.root_ca_pem.is_empty() { set_global_root_cert(material.root_ca_pem.clone()).await; } else { - *GLOBAL_ROOT_CERT.write().await = None; + clear_global_root_cert().await; } set_global_mtls_identity(material.mtls_identity.clone()).await; set_global_outbound_tls_generation(generation.0); @@ -48,8 +48,8 @@ pub async fn publish_global_outbound_tls_state(generation: TlsGeneration, materi pub async fn load_global_outbound_tls_state() -> GlobalPublishedOutboundTlsState { GlobalPublishedOutboundTlsState { generation: TlsGeneration(get_global_outbound_tls_generation()), - root_ca_pem: GLOBAL_ROOT_CERT.read().await.clone(), - mtls_identity: GLOBAL_MTLS_IDENTITY.read().await.clone(), + root_ca_pem: get_global_root_cert().await, + mtls_identity: get_global_mtls_identity().await, } } diff --git a/docs/architecture/global-state-inventory.md b/docs/architecture/global-state-inventory.md index 582210f17..498b12ce6 100644 --- a/docs/architecture/global-state-inventory.md +++ b/docs/architecture/global-state-inventory.md @@ -48,7 +48,7 @@ migration PR removes or replaces each item. | `GLOBAL_EventNotifier`, `GLOBAL_NotificationSys` | `crates/ecstore/src/services/*` | Runtime migration target | Preserve notification and audit side effects; move only through notify/runtime-source boundaries. | | `GLOBAL_BOOT_TIME`, `globalDeploymentIDPtr`, `GLOBAL_REGION`, `GLOBAL_RUSTFS_PORT`, `GLOBAL_LocalNodeName` | `crates/ecstore/src/runtime/global.rs` | Runtime migration target | Scalar handles may migrate in small PRs after call sites use AppContext or owner-local runtime-source readers. | | `GLOBAL_LOCAL_LOCK_CLIENT`, `GLOBAL_LOCK_CLIENTS`, `GLOBAL_LOCK_MANAGER` | `crates/ecstore/src/runtime/global.rs`, `crates/lock` | Runtime migration target / process-global split | Preserve lock quorum and lock client selection; keep process-level lock manager separate from ECStore endpoint-specific clients. | -| `GLOBAL_CONN_MAP`, `GLOBAL_RUSTFS_HOST`, `GLOBAL_RUSTFS_ADDR`, `GLOBAL_ROOT_CERT`, `GLOBAL_MTLS_IDENTITY`, `GLOBAL_OUTBOUND_TLS_GENERATION` | `crates/common`, `crates/tls-runtime`, `crates/ecstore/src/runtime/sources.rs` | Runtime migration target / process-global split | `GLOBAL_CONN_MAP` and RustFS host/address reads are now owned behind `rustfs_common` helpers; migrate the remaining transport and TLS state only after internode transport and outbound TLS ownership are explicit, without changing cached channel reuse or TLS reload semantics. | +| `GLOBAL_CONN_MAP`, `GLOBAL_RUSTFS_HOST`, `GLOBAL_RUSTFS_ADDR`, `GLOBAL_ROOT_CERT`, `GLOBAL_MTLS_IDENTITY`, `GLOBAL_OUTBOUND_TLS_GENERATION` | `crates/common`, `crates/tls-runtime`, `crates/ecstore/src/runtime/sources.rs` | Runtime migration target / process-global split | Internode connection cache, RustFS host/address reads, and outbound TLS material reads are now owned behind `rustfs_common` helpers; migrate the remaining transport and TLS state only after internode transport and outbound TLS ownership are explicit, without changing cached channel reuse or TLS reload semantics. | | `GLOBAL_HEAL_MANAGER`, `GLOBAL_HEAL_CHANNEL_PROCESSOR`, `GLOBAL_AHM_SERVICES_CANCEL_TOKEN` | `crates/heal` and `crates/common` | Runtime migration target | Needs heal runtime owner handles and queue tests; do not combine with ECStore disk-state movement. | | `AUDIT_SYSTEM`, `GLOBAL_CAPACITY_MANAGER`, `GLOBAL_BUCKET_TARGET_SYS`, `GLOBAL_PROCESSORS`, `INTERNODE_DATA_TRANSPORT`, `GLOBAL_KMS_SERVICE_MANAGER` | Owner crates | Runtime migration target / process-global split | Track as owner-specific follow-ups; each owner must decide whether AppContext, a runtime-source facade, or process-global state is the right final shape. | diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 645cc02fa..fda37b073 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -184,6 +184,7 @@ EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE="${TMP_DIR}/external_ecstore_api_boundar REPLICATION_FACADE_BYPASS_HITS_FILE="${TMP_DIR}/replication_facade_bypass_hits.txt" GLOBAL_CONN_MAP_BYPASS_HITS_FILE="${TMP_DIR}/global_conn_map_bypass_hits.txt" GLOBAL_RUSTFS_ADDR_BYPASS_HITS_FILE="${TMP_DIR}/global_rustfs_addr_bypass_hits.txt" +GLOBAL_OUTBOUND_TLS_BYPASS_HITS_FILE="${TMP_DIR}/global_outbound_tls_bypass_hits.txt" LEGACY_ECSTORE_CONFIG_MODEL_HITS_FILE="${TMP_DIR}/legacy_ecstore_config_model_hits.txt" ECSTORE_ROOT_STORE_SET_DISK_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_set_disk_module_hits.txt" ECSTORE_ROOT_STORE_SUPPORT_MODULE_HITS_FILE="${TMP_DIR}/ecstore_root_store_support_module_hits.txt" @@ -2316,6 +2317,18 @@ if [[ -s "$GLOBAL_RUSTFS_ADDR_BYPASS_HITS_FILE" ]]; then report_failure "GLOBAL_RUSTFS_HOST/ADDR access must stay behind rustfs_common runtime helpers: $(paste -sd '; ' "$GLOBAL_RUSTFS_ADDR_BYPASS_HITS_FILE")" fi +( + cd "$ROOT_DIR" + rg -n --with-filename '\bGLOBAL_(ROOT_CERT|MTLS_IDENTITY|OUTBOUND_TLS_GENERATION)\b' \ + crates rustfs fuzz \ + --glob '*.rs' | + rg -v '^crates/common/src/globals\.rs:' || true +) >"$GLOBAL_OUTBOUND_TLS_BYPASS_HITS_FILE" + +if [[ -s "$GLOBAL_OUTBOUND_TLS_BYPASS_HITS_FILE" ]]; then + report_failure "outbound TLS globals must stay behind rustfs_common runtime helpers: $(paste -sd '; ' "$GLOBAL_OUTBOUND_TLS_BYPASS_HITS_FILE")" +fi + ( cd "$ROOT_DIR" {