Commit Graph
59 Commits
Author SHA1 Message Date
Zhengchao AnandGitHub c7926a7956 test(e2e): admin IAM user/policy/service-account CRUD lifecycle (#4855)
First systematic HTTP e2e batch for the admin management surface
(backlog#1154 peri-2): full user -> canned-policy -> attach ->
service-account lifecycle with data-plane effect assertions (the
credential really gains and loses S3 access), plus a non-admin 403
probe per management endpoint targeting a different principal so
deny_only self-access semantics do not mask the gate. Wired into the
e2e-smoke nextest profile (ci-4 mechanism).
2026-07-15 09:37:54 +00:00
Zhengchao AnandGitHub cc0c9f6565 test(e2e): add console listener over-the-wire smoke net (#4851)
Pin the console listener's wire contract with a real binary on a random
port (backlog#1154 peri-4): unauthenticated version/license endpoints
answer complete JSON without credential material, the SPA prefix always
dispatches to the console static handler (never the S3 API), the admin
API and S3 root on the console listener stay 403 for anonymous callers,
and a console-disabled listener serves no console surface. Wired into
the e2e-smoke nextest profile (ci-4 mechanism).
2026-07-15 17:02:13 +08:00
Zhengchao AnandGitHub 602a742a1b test(e2e): TLS certificate hot-reload live-listener regression net (#4861)
Prove the swap-certificates-without-restart promise over real TLS
handshakes (backlog#1154 peri-5): new connections pick up the rotated
certificate within the reload interval, a session opened under the old
certificate survives the swap, and garbage material is fail-safe (the
old certificate keeps serving, the failure leaves a tls_reload_failed
log event, the process stays up). Wired into the e2e-smoke nextest
profile (ci-4 mechanism).
2026-07-15 08:05:06 +00:00
Zhengchao AnandGitHub 52ef30f167 test(e2e): add S3 event-notification webhook delivery regression net (#4821)
Cover the previously untested configure-target -> put-notification-config
-> object operation -> webhook delivery chain (backlog#1154 peri-1):
PUT/multipart-complete/DELETE event fields, prefix/suffix filter
negatives, and store-queue redelivery after target recovery. Wire both
tests into the e2e-smoke nextest profile (ci-4 mechanism).
2026-07-15 05:01:20 +00:00
53bd4bb300 test(e2e): pin GET codec-streaming body/header parity vs legacy duplex (backlog#1183) (#4745)
backlog#1183 tracks flipping the default GET data path from the legacy
tokio::io::duplex double-copy to the zero-duplex codec-streaming fast path.
That flip is gated behind RUSTFS_GET_CODEC_STREAMING_BODY_COMPAT_CONFIRMED /
..._HEADER_COMPAT_CONFIRMED, which need empirical evidence the two paths are
byte- and header-identical.

Add an e2e regression net that runs the same object matrix twice against the
same on-disk EC shards, changing only the codec-streaming env gates: phase A
(default) takes the legacy duplex path, phase B (gates opened) takes codec
streaming. It asserts byte-for-byte (sha256) and header-for-header equality
across inline / small / multi-block (1.5M/3M/5M+) / multipart objects, plus a
ranged GET (which falls back to legacy by gate design). Path confirmation is
not assumed: the legacy path logs "Created duplex pipe ..." per full GET, so
the test counts that marker per phase and asserts the codec phase created zero
duplex pipes, proving the fast path actually ran rather than silently falling
back to the path it is compared against.

To capture the child server's logs for that assertion, add an optional
RustFSTestEnvironment.capture_log_path (default None = inherit stdio,
backward compatible) that redirects the spawned server's stdout+stderr to a file.

Co-authored-by: heihutu <[email protected]>
2026-07-11 16:33:57 +00:00
Zhengchao AnandGitHub bec5227018 test(e2e): add negative presigned URL SigV4 coverage (#4714)
test(e2e): negative presigned-URL SigV4 suite (backlog#1151 sec-2)

Add crates/e2e_test/src/presigned_negative_test.rs, the query-string
SigV4 sibling of the header-SigV4 suite (sec-1, #4708). Presigned URLs
were only exercised on the happy path, so nothing pinned our end-to-end
enforcement of expiry or query-signature verification.

Against a live single-node RustFSTestEnvironment (random port, isolated
temp dir), the suite asserts HTTP status + S3 error <Code> for:

  - expired presigned GET -> 403 AccessDenied (Request has expired)
  - tampered X-Amz-Signature -> 403 SignatureDoesNotMatch
  - wrong secret key -> 403 SignatureDoesNotMatch
  - tampered target key (swapped after signing) -> 403 SignatureDoesNotMatch
  - tampered presigned PUT -> 403 SignatureDoesNotMatch + object not stored
  - positive controls: valid presigned GET (body match) and PUT (HEAD verify)

Expiry is controlled without real waiting via the AWS SDK presigner's
start_time (sign as of one hour ago with a 60s window). s3s checks
expiry before the signature, so the expired case surfaces AccessDenied.

Wired into the e2e-smoke nextest profile (fast, single-node, no external
deps) so it runs on every PR per the crates/e2e_test/README.md admission
criteria.

Refs rustfs/backlog#1151 (sec-2), rustfs/backlog#1155.
2026-07-11 16:07:41 +08:00
Zhengchao AnandGitHub d6e3aa9140 test(admin-auth): add unit and e2e coverage for the admin authorization gate (#4717)
test(admin-auth): unit + e2e coverage for the admin authorization gate

Adds the first tests for the central admin authorization gate
`rustfs/src/admin/auth.rs`, which previously had zero coverage
(backlog#1151 sec-4, master plan #1155).

Unit tests (rustfs/src/admin/auth.rs):
- Refactor the two `validate_admin_request*` entry points to share a
  single generic decision core `evaluate_admin_actions<S: Store>` /
  `check_admin_request_auth<S: Store>` (removes the duplicated
  action-loop and makes the gate testable without a running cluster).
- Cover: owner/root credential allowed; authenticated non-admin
  credential denied with AccessDenied; missing credential denied; and
  the multi-action loop grants on any permitted action, denies when
  none pass. Backed by an in-memory empty IamSys so the owner path
  short-circuits to allow and every other principal resolves to deny.

E2E (crates/e2e_test/src/admin_auth_test.rs, raw SigV4 over HTTP, no
awscurl dependency):
- non_admin_credential_denied_on_admin_api: a limited IAM user gets
  403 AccessDenied on GET /rustfs/admin/v3/info while root succeeds.
- root_credential_rotation_takes_effect: restart with rotated
  --access-key/--secret-key; new credential works and the stale one is
  rejected, on both the admin plane and the S3 data plane.
- default_credentials_emit_startup_warning: booting with the default
  rustfsadmin credentials emits the default-credentials warning.

Refs rustfs/backlog#1151 (sec-4), #1155.
2026-07-11 16:07:36 +08:00
Zhengchao AnandGitHub abe6c41227 test(e2e): negative header-SigV4 rejection suite (backlog#1151 sec-1) (#4708)
test(e2e): add negative header-SigV4 rejection suite (backlog#1151 sec-1)

RustFS delegates SigV4 verification to the s3s dependency, so nothing in
this repo pins OUR end-to-end wiring of it. Add negative_sigv4_test.rs
sending REJECTED header-SigV4 requests against a live RustFSTestEnvironment
and asserting the HTTP status plus the S3 error code XML:

- valid_header_sigv4_request_succeeds (positive control so the negatives
  cannot pass for the wrong reason)
- tampered_signature_returns_signature_does_not_match -> 403 SignatureDoesNotMatch
- wrong_secret_key_returns_signature_does_not_match -> 403 SignatureDoesNotMatch
- tampered_payload_is_rejected (body != signed x-amz-content-sha256) -> not 200
- skewed_date_returns_request_time_too_skewed (>15min) -> 403 RequestTimeTooSkewed
- malformed_authorization_header_returns_clean_4xx (present-not-missing) -> 4xx, never 5xx

Signatures are hand-built via rustfs_signer::request_signature_v4 primitives
(get_signing_key/get_signature/get_scope) so the test controls the timestamp,
secret, signed payload hash, and final signature bytes. Missing-credential
negatives are intentionally not duplicated (covered by multipart_auth_test /
anonymous_access_test).

Refs backlog#1151 (sec-1), master plan backlog#1155.
2026-07-11 03:28:56 +00:00
Zhengchao AnandGitHub ac646cfbe4 test(e2e): large-object degraded-read EOF truncation regression net (dist-13) (#4709)
Adds an S3-API-level e2e regression net proving that a large-object GET on a
degraded EC set never returns a silently truncated body under a full
Content-Length -- the historical "unexpected EOF" bug fixed on main by
rustfs#4594 (short-body GetObject stream -> UnexpectedEof), rustfs#4560
(in-place per-part legacy degradation for the lazy multipart reader), and
rustfs#4585 (DARE package-boundary truncation detection). Those fixes each
ship a *unit* regression; this covers the layer they do not -- the full HTTP
GET path streaming a real body reconstructed from real on-disk EC shards.

New file crates/e2e_test/src/degraded_read_eof_regression_test.rs, single-node
4-disk (EC 2+2) DiskFaultHarness, three scenarios:

  (a) one disk offline: a 6 MiB single object (>=2 EC stripes) and a 3x5 MiB
      multipart object GET back byte-identical with the correct Content-Length.
  (b) mid-stream bitrot within quorum: 2 of 4 shards corrupted mid-file on a
      large multipart object still reconstructs the full, hash-matching body.
  (c) beyond read quorum (the heart of the net): 3 of 4 shards corrupted
      mid-file -- the read MUST fail cleanly (non-2xx or a mid-stream body
      error), NEVER close with a truncated body under the full Content-Length.

The shared get_checked() helper panics on the forbidden outcome (a clean 2xx
whose collected body is shorter than the advertised Content-Length), so the
truncation bug can never be silently tolerated.

CI placement: these spawn a 4-disk server per test and are resource-heavy, so
they stay OUT of the fast PR e2e-smoke filter. A new e2e-reliability nextest
test-group (max-threads=1) serializes them (and the existing
reliability_disk_fault_test) across nextest's process boundary; ci-7's nightly
full-e2e run picks them up. Visible via `cargo nextest list -p e2e_test`.

Refs rustfs/backlog#1150 (dist-13), rustfs/backlog#1155, rustfs#4594,
rustfs#4560, rustfs#4585, rustfs#2955.
2026-07-11 02:49:48 +00:00
Zhengchao AnandGitHub 79d6de860c test(e2e): avoid console port 9001 clash and fail fast on dead server (#4603) 2026-07-09 12:07:15 +08:00
Zhengchao AnandGitHub dee8e4e639 test(e2e): make security boundary tests assert real outcomes (#4466)
* test(e2e): make security boundary tests assert real outcomes

* fix(e2e): use expect_err to satisfy clippy err_expect lint
2026-07-08 22:01:46 +08:00
Zhengchao AnandGitHub 511ad31ba0 fix(s3): normalize root double-slash ListBuckets requests (#4336)
test(s3): MinIO parity for double-slash ListBuckets, invalid copy-source date, region-aware CreateBucket

- Add DoubleSlashListBucketsCompatLayer: rewrite `GET //` to `GET /` so
  it routes to ListBuckets, matching MinIO browser-client behavior (#601)
- Add e2e regression coverage for invalid copy-source conditional date
  headers (#618) and region-aware MakeBucket(us-east-1) (#629)

Refs rustfs/backlog#601 #618 #629
2026-07-07 04:36:16 +08:00
Ramakrishna ChilakaandGitHub eb85607e37 fix(s3): allow CopyObject to restore a historical object version (#4250) 2026-07-04 10:36:42 +08:00
Zhengchao AnandGitHub ba1f162f0f fix(server): normalize leading and duplicate slashes in object keys (#4228) 2026-07-03 12:50:57 +08:00
7329816ed7 test(e2e): add disk fault injection harness and reliability tests (#4223)
Add crates/e2e_test/src/chaos.rs with in-process fault-injection
primitives for a single-node multi-disk RustFS server: take a disk
offline (rename to <dir>.offline), bring it back online, replace a
disk with a fresh empty directory, corrupt an object's erasure shard
(part.* byte flips, xl.meta untouched), and SIGKILL/restart the server
with the same volumes and port.

Add reliability tests on a 4-disk (EC 2+2) topology, verified via
sha256 manifests recorded at write time:

- degraded read/write with one disk offline (incl. multipart object)
- bitrot read-through with two corrupted shards per object
- fresh-disk replacement healed via admin deep heal after a SIGKILL
  restart

Also reuse the shared signed_admin_post helper from chaos.rs in the
heal regression suite instead of a duplicated local copy.

Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-03 11:37:32 +08:00
Zhengchao AnandGitHub e37e367390 refactor: route remaining external storage boundaries (#3889) 2026-06-26 06:22:51 +08:00
Zhengchao AnandGitHub 30559f7e1b refactor: collapse test fuzz ecstore thin bridges (#3765) 2026-06-23 07:04:51 +08:00
Zhengchao AnandGitHub 198fd4f150 refactor(runtime): route RustFS runtime consumers through storage owner (#3756) 2026-06-23 05:17:56 +08:00
Zhengchao AnandGitHub 539c68778d refactor: remove standalone compat bridge modules (#3740) 2026-06-22 17:35:58 +08:00
cxymdsandGitHub 2f25cf606e fix(storage): harden rebalance decommission state (#3515) 2026-06-22 12:03:13 +08:00
安正超andGitHub c098184c49 refactor: clean runtime and test storage boundaries (#3573)
* refactor: clean runtime observability select boundaries

* refactor: clean test harness fuzz storage boundaries
2026-06-18 18:09:25 +08:00
GatewayJandGitHub a30cafa73f fix(filemeta): detect physical data dirs for overwrite cleanup (#3510) 2026-06-18 11:58:12 +08:00
ddd35badad fix(ecstore): avoid offline disks on admin timeout (#3263)
* fix(ecstore): avoid offline disks on admin timeout

* fix(ecstore): handle poisoned admin cache locks

* fix(ecstore): recover poisoned admin cache on success

---------

Co-authored-by: houseme <[email protected]>
Co-authored-by: 安正超 <[email protected]>
2026-06-08 08:35:36 +00:00
b436272642 fix: tolerate stalled listing readers after quorum (#3110)
Co-authored-by: loverustfs <[email protected]>
2026-05-29 08:57:57 +08:00
d9c683decc fix: retry namespace lock quorum contention (#3098)
* fix: retry namespace lock quorum contention

* fix(lock): treat remote lock rpc failures as hard

* fix(lock): classify lock contention timeout and avoid hard rollback blocks

* fix(lock): handle namespace lock quorum timeouts

* fix(lock): refine quorum contention handling

* fix(lock): refine unrecoverable quorum handling logs

* fix: address namespace lock quorum review feedback

* test: stabilize batch quorum timing tests

* fix(lock): classify remote quorum failures

* fix: drop remote lock timeout grace period

* fix: satisfy clippy on lock quorum error

* fix: classify remote lock rpc timeouts as hard failures

* fix: fast fail impossible lock quorum attempts

* fix: retry on transient timeout with pending cleanup

* fix: evict remote lock timeout connections

* refactor: avoid duplicate timeout eviction warning

---------

Co-authored-by: houseme <[email protected]>
2026-05-28 01:35:00 +00:00
0875f09a39 fix: rebuild wiped disks during admin heal (#3084)
* fix: rebuild wiped disks during admin heal

* Preserve forceStart heal admission semantics

* Address heal regression test review comments

* fix(heal): address admin heal review comments

* fix(heal): fix force-start dedup and test polling

* fix(heal): address unresolved review comments

* fix(heal): simplify dedup key for clippy

---------

Co-authored-by: houseme <[email protected]>
2026-05-26 21:54:29 +08:00
housemeandGitHub 129cb0f920 fix: make HeadObject consistent after write completion (#2936) 2026-05-13 03:27:38 +00:00
6275918d92 fix: empty-body requests without content length (#2888)
Co-authored-by: houseme <[email protected]>
Co-authored-by: OmX <[email protected]>
2026-05-09 14:05:53 +00:00
50ddec3ffc fix: preserve data on self metadata copy (#2819)
Co-authored-by: cxymds <[email protected]>
2026-05-06 06:28:36 +00:00
安正超andGitHub 3208f930c5 fix(s3): advertise byte ranges on head object (#2802) 2026-05-05 04:29:25 +00:00
d949d4e794 fix: avoid sending HEAD bodies over TLS HTTP/2 (#2648)
Signed-off-by: 唐小鸭 <[email protected]>
Signed-off-by: houseme <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: houseme <[email protected]>
Co-authored-by: loverustfs <[email protected]>
2026-04-25 01:33:08 +00:00
安正超andGitHub 68d3dba9fc fix: revert standalone #2351 artifacts (phase 5) (#2535) 2026-04-14 22:35:05 +08:00
weisdandGitHub 0b99e02891 feat(ecstore): add stale multipart upload cleanup (#2416) 2026-04-07 18:57:07 +08:00
c9c2428373 fix(download): preserve archive download integrity (#2415)
Co-authored-by: heihutu <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: houseme <[email protected]>
2026-04-07 16:25:34 +08:00
32bf8f5bf3 feat(storage): add direct chunk GET fast path (#2351)
Signed-off-by: houseme <[email protected]>
Co-authored-by: heihutu <[email protected]>
Co-authored-by: cxymds <[email protected]>
2026-04-07 08:33:46 +08:00
weisdandGitHub 0fb070e912 feat(s3): support metadata extensions for bucket listings (#2344) 2026-03-30 22:03:13 +08:00
GatewayJGitHubCopilotGatewayJ <8352692332qq.com>
3366bd2464 feat(iam,admin): prepared IAM auth, ExistingObjectTag, admin permission checks (#2315)
Signed-off-by: GatewayJ <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: GatewayJ <8352692332qq.com>
2026-03-29 19:18:16 +08:00
安正超andGitHub f98664ea4a test(s3): complete snowball auto-extract coverage (#2313) 2026-03-28 22:56:42 +08:00
weisdandGitHub 28f57b228c feat(s3): advance parity coverage (#2278) 2026-03-24 17:29:33 +08:00
weisdandGitHub a42320848c fix(ecstore): invalidate xl.meta cache after writes and rename (#2255) 2026-03-22 11:30:29 +08:00
GatewayJGitHubGatewayJ <8352692332qq.com>
ba32fd9d96 fix(s3): allow anonymous access when PublicAccessBlock config is miss… (#2039)
Co-authored-by: GatewayJ <8352692332qq.com>
2026-03-02 11:37:00 +08:00
8f00d1fbb0 feat(admin): implement handler for delete group (#1901)
Signed-off-by: Niraj Yadav <[email protected]>
Signed-off-by: heihutu <[email protected]>
Co-authored-by: heihutu <[email protected]>
Co-authored-by: yxrxy <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: 安正超 <[email protected]>
2026-02-24 13:00:46 +08:00
loverustfsandGitHub 5d737eaeb7 fix(ecstore): invalidate GlobalFileCache after write_all_private to fix DeleteMarker visibility (#1890) 2026-02-20 22:47:45 +08:00
cf633569a2 fix: remove duplicate common prefixes for slash delimiter (#1797) (#1841)
Signed-off-by: houseme <[email protected]>
Co-authored-by: houseme <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: heihutu <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: houseme <[email protected]>
2026-02-17 21:36:31 +08:00
a2b88a79ec test(e2e_test): add automated cluster environment for conditional PUT race test (#1673)
Co-authored-by: houseme <[email protected]>
Co-authored-by: loverustfs <[email protected]>
2026-02-06 15:01:59 +08:00
90ed75a3dc refactor(utils/os): Optimize Windows OS utilities and add safety comments (#1671)
Co-authored-by: weisd <[email protected]>
2026-01-30 16:13:42 +08:00
安正超andGitHub 4890fb25c1 fix: listobjects v2 pagination (#1607) 2026-01-25 09:30:08 +08:00
GatewayJandGitHub 9285acba06 feat: object retention (#1589) 2026-01-24 22:12:45 +08:00
LeonWang0735andGitHub db5e72e475 Fix/correctly handle compression (#1594) 2026-01-24 10:55:10 +08:00
29d86036b1 feat: implement bucket quota system (#1461)
Signed-off-by: yxrxy <[email protected]>
Co-authored-by: loverustfs <[email protected]>
2026-01-12 11:42:07 +08:00