chore(deps): refresh s3s and dependencies (#6665)

* chore(deps): refresh s3s and related dependencies

Update the RustFS s3s git dependency to the requested f4dedc905 revision and keep the resolved dependency refresh from Cargo.

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(api): adapt s3s upload stream error mapping

Detect the s3s upload stream SHA256 mismatch through the error chain without relying on the removed crate-root re-export.

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix(auth): preserve SigV2 S3 compatibility

Keep RustFS S3 service configuration explicit after the s3s default disables SigV2.

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
houseme
2026-08-26 21:25:16 +08:00
committed by GitHub
parent 62a767a52d
commit ba15588ce8
5 changed files with 120 additions and 66 deletions
Generated
+45 -45
View File
@@ -766,9 +766,9 @@ dependencies = [
[[package]]
name = "async-rs"
version = "0.8.11"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cd5147201b63ba6883ffabca3a153822f71541748d7108e3e799beaeb283131"
checksum = "c5f55b2bcef73a79a2feb5496478693077b60b7337896f0b72431cd5311d988a"
dependencies = [
"async-compat",
"async-global-executor",
@@ -971,9 +971,9 @@ dependencies = [
[[package]]
name = "aws-sdk-kms"
version = "1.116.0"
version = "1.117.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "484ecdbea2a1cfc0e6eea69ce0a665f93913671b303ba40b2361b1d826544e7e"
checksum = "83b602641be84ebe5f96606cfefe4b96efaae1fd947c1b34ea8513b8ac0d2d8d"
dependencies = [
"arc-swap",
"aws-credential-types",
@@ -997,9 +997,9 @@ dependencies = [
[[package]]
name = "aws-sdk-s3"
version = "1.143.0"
version = "1.144.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0ade5433c9561daac7c0c6bc910f1240b4f8ec0d6148b0b463aac0691d747c9"
checksum = "30dc8bf6baaf7d46336a0ca2c69f223d9b90d7a801fb3e28f7ea17b00dc6b1de"
dependencies = [
"arc-swap",
"aws-credential-types",
@@ -1024,7 +1024,7 @@ dependencies = [
"http 0.2.12",
"http 1.5.0",
"http-body 1.1.0",
"lru 0.16.4",
"lru 0.18.2",
"percent-encoding",
"regex-lite",
"sha2 0.11.0",
@@ -1034,9 +1034,9 @@ dependencies = [
[[package]]
name = "aws-sdk-sso"
version = "1.107.0"
version = "1.108.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "769b0abd0f89cfe11da5099986dd493e4f94347ce9a4562cb86ddecfe926b6c0"
checksum = "c15301b04372832947916607983b114b3374b9db0be058a00fb7513800de1f05"
dependencies = [
"arc-swap",
"aws-credential-types",
@@ -1060,9 +1060,9 @@ dependencies = [
[[package]]
name = "aws-sdk-ssooidc"
version = "1.109.0"
version = "1.110.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4075b8a2c8cda4076a3dcc43b9d6dabd93e0c2502abeaaf7e14aaead9bb312b"
checksum = "72cc2c205cb27108183cf1856333f7d584c2ba0f505421b4209ca5828f9ea899"
dependencies = [
"arc-swap",
"aws-credential-types",
@@ -1086,9 +1086,9 @@ dependencies = [
[[package]]
name = "aws-sdk-sts"
version = "1.112.0"
version = "1.113.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f582002918346a3e685be1b391c7bea155073088cea6bd4e4b7663df9e43b6c"
checksum = "68182ecb449f7537db0f4d5d25917789cf41e32074a9fe47b6a0b847fe1d2032"
dependencies = [
"arc-swap",
"aws-credential-types",
@@ -1629,7 +1629,7 @@ version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array 0.14.9",
"generic-array 0.14.7",
]
[[package]]
@@ -1648,7 +1648,7 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
dependencies = [
"generic-array 0.14.9",
"generic-array 0.14.7",
]
[[package]]
@@ -2003,7 +2003,7 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common 0.1.6",
"crypto-common 0.1.7",
"inout 0.1.4",
]
@@ -2094,9 +2094,9 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "combine"
version = "4.6.7"
version = "4.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e"
dependencies = [
"bytes",
"futures-core",
@@ -2463,7 +2463,7 @@ version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
dependencies = [
"generic-array 0.14.9",
"generic-array 0.14.7",
"rand_core 0.6.4",
"subtle",
"zeroize",
@@ -2488,11 +2488,11 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array 0.14.9",
"generic-array 0.14.7",
"typenum",
]
@@ -3758,7 +3758,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"const-oid 0.9.6",
"crypto-common 0.1.6",
"crypto-common 0.1.7",
"subtle",
]
@@ -4021,7 +4021,7 @@ dependencies = [
"crypto-bigint 0.5.5",
"digest 0.10.7",
"ff 0.13.1",
"generic-array 0.14.9",
"generic-array 0.14.7",
"group 0.13.0",
"hkdf 0.12.4",
"pem-rfc7468 0.7.0",
@@ -4466,9 +4466,9 @@ dependencies = [
[[package]]
name = "generic-array"
version = "0.14.9"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -4481,7 +4481,7 @@ version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "337d46834ee672ab3e48caca2cb0c78cc174fb12b3a68d0d88f99a0519a5e36e"
dependencies = [
"generic-array 0.14.9",
"generic-array 0.14.7",
"rustversion",
"typenum",
]
@@ -5516,7 +5516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
"block-padding 0.3.3",
"generic-array 0.14.9",
"generic-array 0.14.7",
]
[[package]]
@@ -6762,7 +6762,7 @@ dependencies = [
"ed25519-dalek 2.2.0",
"getrandom 0.2.17",
"log",
"rand 0.8.7",
"rand 0.8.8",
"signatory",
]
@@ -6818,7 +6818,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc895af95856f929163a0aa20c26a78d26bfdc839f51b9d5aa7a5b79e52b7e83"
dependencies = [
"rand 0.8.7",
"rand 0.8.8",
]
[[package]]
@@ -6853,7 +6853,7 @@ dependencies = [
"num-integer",
"num-iter",
"num-traits",
"rand 0.8.7",
"rand 0.8.8",
"smallvec",
"zeroize",
]
@@ -6971,7 +6971,7 @@ dependencies = [
"chrono",
"getrandom 0.2.17",
"http 1.5.0",
"rand 0.8.7",
"rand 0.8.8",
"serde",
"serde_json",
"serde_path_to_error",
@@ -7149,7 +7149,7 @@ dependencies = [
"oauth2",
"p256 0.13.2",
"p384 0.13.1",
"rand 0.8.7",
"rand 0.8.8",
"rsa 0.9.10",
"serde",
"serde-value",
@@ -8144,8 +8144,8 @@ version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
dependencies = [
"heck 0.4.1",
"itertools 0.10.5",
"heck 0.5.0",
"itertools 0.14.0",
"log",
"multimap",
"once_cell",
@@ -8164,8 +8164,8 @@ version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042"
dependencies = [
"heck 0.4.1",
"itertools 0.10.5",
"heck 0.5.0",
"itertools 0.14.0",
"log",
"multimap",
"petgraph 0.8.3",
@@ -8186,7 +8186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools 0.10.5",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.119",
@@ -8199,7 +8199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
dependencies = [
"anyhow",
"itertools 0.10.5",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.119",
@@ -8283,7 +8283,7 @@ dependencies = [
"prost 0.13.5",
"prost-build 0.13.5",
"prost-derive 0.13.5",
"rand 0.8.7",
"rand 0.8.8",
"regex",
"rustls",
"tokio",
@@ -8560,9 +8560,9 @@ dependencies = [
[[package]]
name = "rand"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -10993,7 +10993,7 @@ checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "s3s"
version = "0.15.0"
source = "git+https://github.com/rustfs/s3s.git?rev=5f22e8d0a37e83f531f653024aac11c72586479a#5f22e8d0a37e83f531f653024aac11c72586479a"
source = "git+https://github.com/rustfs/s3s.git?rev=f4dedc905ec621fa85a4686df6304190b55375f6#f4dedc905ec621fa85a4686df6304190b55375f6"
dependencies = [
"arc-swap",
"arrayvec",
@@ -11147,7 +11147,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
dependencies = [
"base16ct 0.2.0",
"der 0.7.10",
"generic-array 0.14.9",
"generic-array 0.14.7",
"pkcs8 0.10.2",
"subtle",
"zeroize",
@@ -12473,7 +12473,7 @@ dependencies = [
"futures-sink",
"http 1.5.0",
"httparse",
"rand 0.8.7",
"rand 0.8.8",
"rustls-pki-types",
"tokio",
"tokio-rustls",
+4 -4
View File
@@ -237,9 +237,9 @@ atoi = "3.1.0"
atomic_enum = "0.3.0"
aws-config = { version = "1.11.0" }
aws-credential-types = { version = "1.3.0" }
aws-sdk-kms = { default-features = false, version = "1.116.0" }
aws-sdk-s3 = { default-features = false, version = "1.143.0" }
aws-sdk-sts = { default-features = false, version = "1.112.0" }
aws-sdk-kms = { default-features = false, version = "1.117.0" }
aws-sdk-s3 = { default-features = false, version = "1.144.0" }
aws-sdk-sts = { default-features = false, version = "1.113.0" }
aws-smithy-http-client = { default-features = false, version = "1.4.0" }
aws-smithy-runtime-api = { version = "1.15.0" }
aws-smithy-types = { version = "1.6.2" }
@@ -306,7 +306,7 @@ rustify = { version = "0.7", default-features = false }
rustix = { version = "1.1.4" }
rust-embed = { version = "8.12.0" }
rustc-hash = { version = "2.1.3" }
s3s = { git = "https://github.com/rustfs/s3s.git", rev = "5f22e8d0a37e83f531f653024aac11c72586479a", version = "0.15.0", features = ["minio"] }
s3s = { git = "https://github.com/rustfs/s3s.git", rev = "f4dedc905ec621fa85a4686df6304190b55375f6", version = "0.15.0", features = ["minio"] }
serial_test = "4.0.1"
shadow-rs = { default-features = false, version = "2.0.0" }
siphasher = "1.0.3"
+16 -5
View File
@@ -10373,6 +10373,17 @@ mod tests {
use tokio::io::{AsyncRead, ReadBuf};
use tokio_tar::{Builder, EntryType, Header};
#[derive(Debug)]
struct MockUploadStreamSha256Mismatch;
impl std::fmt::Display for MockUploadStreamSha256Mismatch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("UploadStreamError: Sha256Mismatch")
}
}
impl std::error::Error for MockUploadStreamSha256Mismatch {}
#[tokio::test]
async fn cancelled_eager_put_commit_owner_reaps_stalled_storage_task() {
let health = Arc::new(ObjectTrafficHealth::enabled_for_test(Duration::ZERO));
@@ -16386,20 +16397,20 @@ mod tests {
#[test]
fn s3s_body_error_to_io_preserves_upload_stream_error_source() {
let error = s3s_body_error_to_io(Box::new(s3s::UploadStreamError::Sha256Mismatch));
let error = s3s_body_error_to_io(Box::new(MockUploadStreamSha256Mismatch));
assert!(matches!(
error
.get_ref()
.and_then(|source| source.downcast_ref::<s3s::UploadStreamError>()),
Some(s3s::UploadStreamError::Sha256Mismatch)
.and_then(|source| source.downcast_ref::<MockUploadStreamSha256Mismatch>()),
Some(MockUploadStreamSha256Mismatch)
));
}
#[tokio::test]
async fn read_small_put_body_maps_upload_stream_sha256_mismatch_to_bad_digest() {
let body = StreamReader::new(futures::stream::iter(vec![Err::<Bytes, std::io::Error>(s3s_body_error_to_io(Box::new(
s3s::UploadStreamError::Sha256Mismatch,
MockUploadStreamSha256Mismatch,
)))]));
let error = read_small_put_body_exact_direct(body, 1)
@@ -16411,7 +16422,7 @@ mod tests {
#[tokio::test]
async fn read_zero_copy_put_body_maps_upload_stream_sha256_mismatch_to_bad_digest() {
let body = futures::stream::iter(vec![Err::<Bytes, s3s::UploadStreamError>(s3s::UploadStreamError::Sha256Mismatch)]);
let body = futures::stream::iter(vec![Err::<Bytes, MockUploadStreamSha256Mismatch>(MockUploadStreamSha256Mismatch)]);
let error = match read_zero_copy_put_body_exact(body, 1).await {
Ok(_) => panic!("SHA256 mismatch should reject the zero-copy PUT body"),
+38 -10
View File
@@ -226,7 +226,7 @@ where
}
fn error_chain_has_upload_stream_sha256_mismatch(err: &(dyn std::error::Error + 'static)) -> bool {
if matches!(err.downcast_ref::<s3s::UploadStreamError>(), Some(s3s::UploadStreamError::Sha256Mismatch)) {
if err.to_string() == "UploadStreamError: Sha256Mismatch" {
return true;
}
@@ -239,7 +239,7 @@ fn error_chain_has_upload_stream_sha256_mismatch(err: &(dyn std::error::Error +
let mut current = err.source();
while let Some(err) = current {
if matches!(err.downcast_ref::<s3s::UploadStreamError>(), Some(s3s::UploadStreamError::Sha256Mismatch)) {
if err.to_string() == "UploadStreamError: Sha256Mismatch" {
return true;
}
current = err.source();
@@ -452,6 +452,34 @@ mod tests {
use s3s::{S3Error, S3ErrorCode};
use std::io::{Error as IoError, ErrorKind};
#[derive(Debug)]
enum MockUploadStreamError {
Underlying(IoError),
Sha256Mismatch,
LengthMismatch,
Incomplete,
}
impl std::fmt::Display for MockUploadStreamError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Underlying(err) => write!(f, "UploadStreamError: Underlying: {err}"),
Self::Sha256Mismatch => f.write_str("UploadStreamError: Sha256Mismatch"),
Self::LengthMismatch => f.write_str("UploadStreamError: LengthMismatch"),
Self::Incomplete => f.write_str("UploadStreamError: Incomplete"),
}
}
}
impl std::error::Error for MockUploadStreamError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Underlying(err) => Some(err),
Self::Sha256Mismatch | Self::LengthMismatch | Self::Incomplete => None,
}
}
}
#[test]
fn test_api_error_from_io_error() {
let io_error = IoError::new(ErrorKind::PermissionDenied, "permission denied");
@@ -515,11 +543,11 @@ mod tests {
#[test]
fn upload_stream_sha256_mismatch_maps_to_bad_digest() {
let api_error = ApiError::from(IoError::other(s3s::UploadStreamError::Sha256Mismatch));
let api_error = ApiError::from(IoError::other(MockUploadStreamError::Sha256Mismatch));
assert_eq!(api_error.code, S3ErrorCode::BadDigest);
assert_eq!(api_error.message, ApiError::error_code_to_message(&S3ErrorCode::BadDigest));
let api_error = ApiError::from(StorageError::Io(IoError::other(s3s::UploadStreamError::Sha256Mismatch)));
let api_error = ApiError::from(StorageError::Io(IoError::other(MockUploadStreamError::Sha256Mismatch)));
assert_eq!(api_error.code, S3ErrorCode::BadDigest);
assert_eq!(api_error.message, ApiError::error_code_to_message(&S3ErrorCode::BadDigest));
}
@@ -527,9 +555,9 @@ mod tests {
#[test]
fn other_upload_stream_errors_do_not_map_to_bad_digest() {
let errors = [
s3s::UploadStreamError::Underlying(Box::new(IoError::other("underlying body error"))),
s3s::UploadStreamError::LengthMismatch,
s3s::UploadStreamError::Incomplete,
MockUploadStreamError::Underlying(IoError::other("underlying body error")),
MockUploadStreamError::LengthMismatch,
MockUploadStreamError::Incomplete,
];
for error in errors {
@@ -538,9 +566,9 @@ mod tests {
}
let errors = [
s3s::UploadStreamError::Underlying(Box::new(IoError::other("underlying body error"))),
s3s::UploadStreamError::LengthMismatch,
s3s::UploadStreamError::Incomplete,
MockUploadStreamError::Underlying(IoError::other("underlying body error")),
MockUploadStreamError::LengthMismatch,
MockUploadStreamError::Incomplete,
];
for error in errors {
+17 -2
View File
@@ -151,6 +151,14 @@ static HTTP_STATUS_CLASS_METRICS: std::sync::LazyLock<[HttpStatusClassMetrics; 6
std::sync::LazyLock::new(|| HTTP_STATUS_CLASS_LABELS.map(HttpStatusClassMetrics::new));
static HTTP_TRANSPORT_FAILURES_COUNTER: std::sync::LazyLock<metrics::Counter> =
std::sync::LazyLock::new(|| counter!(METRIC_HTTP_SERVER_FAILURES_TOTAL, LABEL_HTTP_STATUS_CLASS => "transport"));
fn rustfs_s3_config() -> S3Config {
let mut s3_config = S3Config::default();
s3_config.normalize_forward_slash_path = true;
s3_config.enable_sig_v2 = true;
s3_config
}
const LOG_COMPONENT_SERVER: &str = "server";
const LOG_SUBSYSTEM_HTTP: &str = "http";
const LOG_SUBSYSTEM_TRANSPORT: &str = "transport";
@@ -922,8 +930,7 @@ pub async fn start_http_server(
// `PUT /bucket//foo/bar` are rejected downstream with InvalidArgument
// (ObjectNamePrefixAsSlash, issue #2427). MinIO collapses these slashes instead of preserving them,
// so `//foo/bar` is stored and served as `foo/bar`.
let mut s3_config = S3Config::default();
s3_config.normalize_forward_slash_path = true;
let s3_config = rustfs_s3_config();
b.set_config(Arc::new(StaticConfigProvider::new(Arc::new(s3_config))));
// Virtual-hosted-style requests are only set up for S3 API when server domains are configured and console is disabled
@@ -2257,6 +2264,14 @@ mod tests {
assert_eq!(HTTP_STATUS_CLASS_LABELS[HTTP_STATUS_UNKNOWN_INDEX], "unknown");
}
#[test]
fn rustfs_s3_config_preserves_compatibility_over_s3s_defaults() {
let s3_config = rustfs_s3_config();
assert!(s3_config.normalize_forward_slash_path);
assert!(s3_config.enable_sig_v2);
}
#[test]
#[serial_test::serial]
fn cached_http_metric_handles_preserve_metric_labels() {