From 793efe3eb43c6e73778f3c5c846f5c6df91eb593 Mon Sep 17 00:00:00 2001 From: Yujong Lee Date: Mon, 21 Sep 2026 21:15:42 +0000 Subject: [PATCH] fix(rust): restore hot-path opt levels and validate s3 binding destination Keep sigv4 signing, eventstream decoding, smithy runtime api and types at opt-level 3 since they serve Bedrock request and streaming hot paths, and make the S3 facade binding reject region and endpoint mismatches between the projected configuration and the native handle Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm-rust/Cargo.toml | 8 --- litellm-rust/crates/cache-s3/src/cache.rs | 19 +++++- .../crates/python-bridge/src/cache/config.rs | 58 +++++++++++++++++++ .../crates/python-bridge/src/cache/native.rs | 14 +++++ 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/litellm-rust/Cargo.toml b/litellm-rust/Cargo.toml index 9cded32b7e0..5a72437d767 100644 --- a/litellm-rust/Cargo.toml +++ b/litellm-rust/Cargo.toml @@ -103,8 +103,6 @@ opt-level = "s" [profile.release.package."aws-sdk-sts"] opt-level = "s" -[profile.release.package."aws-sigv4"] -opt-level = "s" [profile.release.package."aws-smithy-async"] opt-level = "s" @@ -112,8 +110,6 @@ opt-level = "s" [profile.release.package."aws-smithy-checksums"] opt-level = "s" -[profile.release.package."aws-smithy-eventstream"] -opt-level = "s" [profile.release.package."aws-smithy-http"] opt-level = "s" @@ -133,8 +129,6 @@ opt-level = "s" [profile.release.package."aws-smithy-runtime"] opt-level = "s" -[profile.release.package."aws-smithy-runtime-api"] -opt-level = "s" [profile.release.package."aws-smithy-runtime-api-macros"] opt-level = "s" @@ -142,8 +136,6 @@ opt-level = "s" [profile.release.package."aws-smithy-schema"] opt-level = "s" -[profile.release.package."aws-smithy-types"] -opt-level = "s" [profile.release.package."aws-smithy-xml"] opt-level = "s" diff --git a/litellm-rust/crates/cache-s3/src/cache.rs b/litellm-rust/crates/cache-s3/src/cache.rs index a2ea33c33e4..88575f36fce 100644 --- a/litellm-rust/crates/cache-s3/src/cache.rs +++ b/litellm-rust/crates/cache-s3/src/cache.rs @@ -36,18 +36,21 @@ pub struct S3Cache { runtime: Handle, bucket: Arc, key_prefix: Arc, + region: Arc, + endpoint: Option>, } impl S3Cache { pub fn new(config: S3CacheConfig, codec: C, runtime: Handle) -> Self { let mut builder = aws_sdk_s3::Config::builder() .behavior_version(BehaviorVersion::latest()) - .region(Region::new(config.region)) + .region(Region::new(config.region.clone())) .credentials_provider(Credentials::new(config.auth)) .request_checksum_calculation(RequestChecksumCalculation::WhenRequired) .response_checksum_validation(ResponseChecksumValidation::WhenRequired); - if let Some(endpoint) = config.endpoint { - builder = builder.endpoint_url(endpoint.url).force_path_style(true); + let endpoint_url: Option = config.endpoint.map(|endpoint| endpoint.url); + if let Some(url) = &endpoint_url { + builder = builder.endpoint_url(url).force_path_style(true); } Self { client: aws_sdk_s3::Client::from_conf(builder.build()), @@ -55,6 +58,8 @@ impl S3Cache { runtime, bucket: config.bucket.into(), key_prefix: config.key_prefix.into(), + region: config.region.into(), + endpoint: endpoint_url.map(Into::into), } } @@ -66,6 +71,14 @@ impl S3Cache { &self.key_prefix } + pub fn region(&self) -> &str { + &self.region + } + + pub fn endpoint(&self) -> Option<&str> { + self.endpoint.as_deref() + } + pub fn to_s3_key(&self, key: &str) -> String { format!("{}{}", self.key_prefix, key.replace(':', "/")) } diff --git a/litellm-rust/crates/python-bridge/src/cache/config.rs b/litellm-rust/crates/python-bridge/src/cache/config.rs index 5d37ed27083..003a2687e88 100644 --- a/litellm-rust/crates/python-bridge/src/cache/config.rs +++ b/litellm-rust/crates/python-bridge/src/cache/config.rs @@ -212,6 +212,18 @@ impl NativeCacheConfig { { Some("facade and native backend key prefixes must match") } + CacheBackendConfig::S3(config) if service.region() != Some(config.region.as_str()) => { + Some("facade and native backend regions must match") + } + CacheBackendConfig::S3(config) + if service.endpoint() + != config + .endpoint + .as_ref() + .map(|endpoint| endpoint.url.as_str()) => + { + Some("facade and native backend endpoints must match") + } CacheBackendConfig::S3(_) => None, } } @@ -593,6 +605,10 @@ mod tests { use pyo3::{prelude::*, types::PyDict}; + use litellm_auth_aws::AwsAuthConfig; + use litellm_cache_s3::{S3CacheConfig, S3Endpoint}; + use litellm_host_python::run_sync_value; + use super::{ CacheBackendConfig, CacheConfigProjection, CertificateRequirement, NativeCacheConfig, RedisProtocol, @@ -858,4 +874,46 @@ mod tests { assert_eq!(s3.auth.region_name.as_deref(), Some("us-east-1")); }); } + + fn s3_service(py: Python<'_>, region: &str, endpoint: Option<&str>) -> NativeResponseCache { + let config = S3CacheConfig { + bucket: "bucket".to_string(), + key_prefix: "team/".to_string(), + region: region.to_string(), + endpoint: endpoint.map(|url| S3Endpoint { + url: url.to_string(), + }), + auth: AwsAuthConfig::default(), + }; + run_sync_value(py, async move { Ok(NativeResponseCache::s3(config).await) }).unwrap() + } + + #[test] + fn s3_binding_rejects_region_and_endpoint_mismatches() { + Python::initialize(); + Python::attach(|py| { + let facade = s3_facade(py, ""); + let CacheConfigProjection::Native(config) = + NativeCacheConfig::project(&facade).unwrap() + else { + panic!("S3 cache should be supported"); + }; + assert_eq!( + config.service_mismatch(&s3_service(py, "us-east-1", Some("https://example.test"))), + None + ); + assert_eq!( + config.service_mismatch(&s3_service(py, "us-west-2", Some("https://example.test"))), + Some("facade and native backend regions must match") + ); + assert_eq!( + config.service_mismatch(&s3_service(py, "us-east-1", Some("https://other.test"))), + Some("facade and native backend endpoints must match") + ); + assert_eq!( + config.service_mismatch(&s3_service(py, "us-east-1", None)), + Some("facade and native backend endpoints must match") + ); + }); + } } diff --git a/litellm-rust/crates/python-bridge/src/cache/native.rs b/litellm-rust/crates/python-bridge/src/cache/native.rs index b9ea443119b..a6eef420ace 100644 --- a/litellm-rust/crates/python-bridge/src/cache/native.rs +++ b/litellm-rust/crates/python-bridge/src/cache/native.rs @@ -87,6 +87,20 @@ impl NativeResponseCache { } } + pub fn region(&self) -> Option<&str> { + match self { + Self::S3(cache) => Some(cache.backend().region()), + _ => None, + } + } + + pub fn endpoint(&self) -> Option<&str> { + match self { + Self::S3(cache) => cache.backend().endpoint(), + _ => None, + } + } + pub fn namespace(&self) -> Option<&str> { match self { Self::Memory(_) => None,