mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-28 17:18:58 +00:00
c82ee6be58
feat(api): wire opt-in per-client S3 API rate limiting (backlog#1191) RustFS shipped three rate-limiter implementations and none was wired to any request path: the tower layer never returned 429 (its over-limit branch passed requests through) and was never instantiated, the console env switches only logged, and the Swift token bucket was never called. Replace them with one working, default-off implementation: - Rewrite rustfs/src/server/rate_limit.rs as a sharded per-client-IP token-bucket limiter (32 mutex shards instead of one global RwLock write per request), bounded at 100k tracked IPs with lossless refilled-idle sweeps, returning 429 + Retry-After + x-ratelimit-* headers and an S3-style XML body. - Key on trusted-proxy-validated ClientInfo.real_ip, else the socket peer address; never read spoofable X-Forwarded-For/X-Real-IP headers. Requests without a resolvable identity fail open. The echoed request id is charset-gated to prevent reflected XML injection. - Wire the layer once at startup via option_layer between CatchPanicLayer and ReadinessGateLayer (external stack only), gated by new RUSTFS_API_RATE_LIMIT_ENABLE/_RPM/_BURST constants; health and profiling probes, internode RPC/gRPC, and the console are exempt. - Make RUSTFS_CONSOLE_RATE_LIMIT_ENABLE/_RPM actually enforce by reusing the same limiter core through an axum middleware. - Delete the dead Swift ratelimit module, its isolated tests, and the stale logging-guardrail entry; keep the live SwiftError 429 mapping. - Add unit tests (exhaustion/recovery with injected time, concurrency, cap eviction, spoofed-header and fail-open behavior, env matrix) and e2e tests proving 429 + Retry-After on the real server and zero behavior change with default configuration.
251 lines
6.6 KiB
Rust
251 lines
6.6 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
mod reliant;
|
|
mod storage_api;
|
|
|
|
// Common utilities for all E2E tests
|
|
#[cfg(test)]
|
|
pub mod common;
|
|
|
|
// In-process fault-injection primitives (disk offline/replacement, shard corruption)
|
|
#[cfg(test)]
|
|
pub mod chaos;
|
|
|
|
// Reliability tests built on the fault-injection harness
|
|
#[cfg(test)]
|
|
mod reliability_disk_fault_test;
|
|
|
|
// dist-13 (backlog#1150/#1155): e2e regression net proving a large-object
|
|
// degraded EC read never returns a silently truncated body (rustfs#4594/#4560/#4585).
|
|
#[cfg(test)]
|
|
mod degraded_read_eof_regression_test;
|
|
|
|
// backlog#1183: GET codec-streaming fast path must be byte/header identical to
|
|
// the legacy duplex path before its rollout gates can be flipped on by default.
|
|
#[cfg(test)]
|
|
mod get_codec_streaming_compat_test;
|
|
|
|
#[cfg(test)]
|
|
mod version_id_regression_test;
|
|
|
|
// Data usage regression tests
|
|
#[cfg(test)]
|
|
mod data_usage_test;
|
|
|
|
// KMS-specific test modules
|
|
#[cfg(test)]
|
|
mod kms;
|
|
|
|
// Regression test for issue #1797
|
|
#[cfg(test)]
|
|
mod list_objects_duplicates_test;
|
|
|
|
// Quota tests
|
|
#[cfg(test)]
|
|
mod quota_test;
|
|
|
|
// Harness regression tests: console port isolation + fail-fast startup
|
|
#[cfg(test)]
|
|
mod server_startup_failfast_test;
|
|
|
|
#[cfg(test)]
|
|
mod bucket_policy_check_test;
|
|
|
|
// Security boundary tests: DoS limits, SSRF prevention, concurrent-write integrity
|
|
#[cfg(test)]
|
|
mod security_boundary_test;
|
|
|
|
// Opt-in per-client S3 API rate limiting (backlog#1191)
|
|
#[cfg(test)]
|
|
mod api_rate_limit_test;
|
|
|
|
// Admin authorization gate: non-admin denial + root-credential lifecycle (backlog#1151 sec-4)
|
|
#[cfg(test)]
|
|
mod admin_auth_test;
|
|
|
|
/// IAM / bucket / STS session policy with `s3:ExistingObjectTag` conditions (E2E).
|
|
#[cfg(test)]
|
|
mod existing_object_tag_policy_test;
|
|
|
|
// Regression tests for Issue #2036: anonymous access with PublicAccessBlock
|
|
#[cfg(test)]
|
|
mod anonymous_access_test;
|
|
|
|
// Special characters in path test modules
|
|
#[cfg(test)]
|
|
mod special_chars_test;
|
|
|
|
// Leading/duplicate slash key normalization tests (Issue #2427)
|
|
#[cfg(test)]
|
|
mod leading_slash_key_test;
|
|
|
|
// Content-Encoding header preservation test
|
|
#[cfg(test)]
|
|
mod content_encoding_test;
|
|
|
|
#[cfg(test)]
|
|
mod archive_download_integrity_test;
|
|
|
|
// ListObjectsV2 pagination test (Issue #1596)
|
|
#[cfg(test)]
|
|
mod list_objects_v2_pagination_test;
|
|
|
|
// Regression test for Issue #3107: mc mirror small-bucket listing must not time out.
|
|
#[cfg(test)]
|
|
mod mc_mirror_small_bucket_test;
|
|
|
|
// Policy variables tests
|
|
#[cfg(test)]
|
|
mod policy;
|
|
|
|
#[cfg(test)]
|
|
mod compression_test;
|
|
|
|
// Regression test for Issue #1878: DeleteMarkers not visible immediately after delete_objects
|
|
#[cfg(test)]
|
|
mod delete_objects_versioning_test;
|
|
|
|
// Regression test for signed DELETE Object?versionId requests without Content-Length.
|
|
#[cfg(test)]
|
|
mod delete_object_no_content_length_test;
|
|
|
|
// Delete-marker visibility baseline for data-movement migration proof.
|
|
#[cfg(test)]
|
|
mod delete_marker_migration_semantics_test;
|
|
|
|
// Regression test for Issue #2252: ListObjectVersions misses newest version after put -> delete -> put
|
|
#[cfg(test)]
|
|
mod list_object_versions_regression_test;
|
|
|
|
// versions&metadata=true extension regression test
|
|
#[cfg(test)]
|
|
mod list_object_versions_metadata_extension_test;
|
|
|
|
// list-type=2&metadata=true extension regression test
|
|
#[cfg(test)]
|
|
mod list_objects_v2_metadata_extension_test;
|
|
|
|
#[cfg(test)]
|
|
mod protocols;
|
|
|
|
// Object Lock tests
|
|
#[cfg(test)]
|
|
mod object_lock;
|
|
|
|
#[cfg(test)]
|
|
mod cluster_concurrency_test;
|
|
|
|
// PutObject / MultipartUpload with checksum (Content-MD5, x-amz-checksum-*)
|
|
#[cfg(test)]
|
|
mod checksum_upload_test;
|
|
|
|
// Group deletion tests
|
|
#[cfg(test)]
|
|
mod group_delete_test;
|
|
|
|
#[cfg(test)]
|
|
mod head_object_range_test;
|
|
|
|
#[cfg(test)]
|
|
mod head_object_consistency_test;
|
|
|
|
#[cfg(test)]
|
|
mod heal_erasure_disk_rebuild_test;
|
|
|
|
#[cfg(test)]
|
|
mod copy_object_metadata_test;
|
|
|
|
#[cfg(test)]
|
|
mod copy_object_version_restore_test;
|
|
|
|
// S3 dummy-compat bucket API tests
|
|
#[cfg(test)]
|
|
mod bucket_logging_test;
|
|
|
|
// Multipart control API auth regression tests
|
|
#[cfg(test)]
|
|
mod multipart_auth_test;
|
|
|
|
// Negative presigned-URL (query-string SigV4) regression suite (backlog#1151
|
|
// sec-2): expired, tampered signature, wrong secret, tampered target.
|
|
#[cfg(test)]
|
|
mod presigned_negative_test;
|
|
|
|
// Negative header-SigV4 regression suite (backlog#1151 sec-1): tampered
|
|
// signature, wrong secret, skewed date, malformed Authorization.
|
|
#[cfg(test)]
|
|
mod negative_sigv4_test;
|
|
|
|
#[cfg(test)]
|
|
mod stale_multipart_cleanup_cluster_test;
|
|
|
|
// Object lambda end-to-end regression tests
|
|
#[cfg(test)]
|
|
mod object_lambda_test;
|
|
|
|
// S3 event-notification webhook delivery end-to-end (backlog#1154 peri-1):
|
|
// configure webhook target -> PutBucketNotificationConfiguration -> object
|
|
// operation -> event delivered, plus filter negatives and store-queue redelivery.
|
|
#[cfg(test)]
|
|
mod notification_webhook_test;
|
|
|
|
// TLS certificate hot-reload live-listener e2e (backlog#1154 peri-5): swap
|
|
// certificates without a restart, existing sessions survive, bad material is
|
|
// fail-safe (old certificate keeps serving, failure is logged).
|
|
#[cfg(test)]
|
|
mod tls_hot_reload_test;
|
|
|
|
// Console listener over-the-wire smoke (backlog#1154 peri-4): public console
|
|
// endpoints answer without credentials or leaks, the SPA prefix never falls
|
|
// through to the S3 API, and the protected surface stays authenticated.
|
|
#[cfg(test)]
|
|
mod console_smoke_test;
|
|
|
|
// Admin IAM management CRUD e2e (backlog#1154 peri-2): user / canned-policy /
|
|
// service-account lifecycle over signed HTTP with data-plane effect assertions,
|
|
// plus non-admin 403 probes per endpoint (sec-4 pattern).
|
|
#[cfg(test)]
|
|
mod admin_iam_crud_test;
|
|
|
|
// Replication extension end-to-end regression tests
|
|
#[cfg(test)]
|
|
mod replication_extension_test;
|
|
|
|
#[cfg(test)]
|
|
mod snowball_auto_extract_test;
|
|
|
|
#[cfg(test)]
|
|
mod namespace_lock_quorum_test;
|
|
|
|
#[cfg(test)]
|
|
mod admin_timeout_regression_test;
|
|
|
|
#[cfg(test)]
|
|
mod overwrite_cleanup_regression_test;
|
|
|
|
// Regression test for backlog#601: `GET //` ListBuckets browser compatibility.
|
|
#[cfg(test)]
|
|
mod list_buckets_double_slash_test;
|
|
|
|
// Regression test for backlog#629(b): region-aware CreateBucket SigV4.
|
|
#[cfg(test)]
|
|
mod create_bucket_region_test;
|
|
|
|
// Regression coverage for backlog#618 item 8: copy-source invalid-date header.
|
|
#[cfg(test)]
|
|
mod copy_source_invalid_date_test;
|
|
|
|
pub mod tls_gen;
|