Commit Graph

71 Commits

Author SHA1 Message Date
唐小鸭 ae9fe62fb1 fix(sse): resolve 1.0.0 SSE/KMS blockers and P1 findings (#7511)
* fix(sse): resolve bucket default encryption per request

PUT and the POST-object/extract path resolved a bucket's default
encryption with a hard-coded "no explicit SSE-C" flag, so the default was
layered onto a request that already carried an SSE-C header triple and
then tripped that request's own mutual-exclusion check. Every bucket with
default encryption refused SSE-C single PUTs with 400 InvalidArgument,
while CreateMultipartUpload on the same bucket succeeded because it
resolves SSE elsewhere. Both call sites now derive the flag from the
request headers, as COPY already did.

The bucket default's KMS key id was also inherited independently of the
effective algorithm, so an explicit AES256 request against an aws:kms
default bucket produced a self-contradictory algorithm/key-id pair and
was rejected. The key id is now inherited only when the effective
algorithm is aws:kms, matching the storage-layer resolver.

Refs backlog#2368 B1, B2.

* fix(sse): refuse SSE-KMS without a running KMS service

A write requesting aws:kms on a node with no KMS service fell back to the
node-local SSE-S3 provider: the data key was wrapped with
RUSTFS_SSE_S3_MASTER_KEY while the object metadata still recorded
aws:kms and the requested KMS key id. The stored object claimed a KMS
protection it never had, under a key that was never consulted, and no
signal distinguished it from a genuine SSE-KMS object.

The managed-encryption path now asks the resolved DEK provider whether it
wraps with a node-local master key and refuses SSE-KMS in that case:
InvalidRequest when KMS was never configured, ServiceUnavailable when a
configured service is not running. The check sits after the per-key
authorization gate so an unauthorized caller still receives AccessDenied
whatever the KMS runtime state is, and asks the provider rather than a
parallel availability signal because the provider is what actually wraps
the key. A missing master key no longer answers an SSE-KMS request with
an SSE-S3-worded configuration error.

The SSE-S3 local fallback is unchanged.

Refs backlog#2368 B4.

* fix(ecstore): restore and archive tiers in stored coordinates

Multipart restore addressed the remote tier in plaintext coordinates
while the copy-back reads the stored representation. Each part received a
misaligned slice of the remote object whose length still satisfied the
range, the hash reader and the completion size check, so the restore
reported success and silently replaced the object's bytes. Encrypted and
compressed multipart objects were both affected. Restore now accumulates
stored part sizes, passes the stored length to the hash reader alongside
the plaintext length, and validates against the stored size.

The copy-back digests stored bytes, so its computed MD5 is not the
object's public ETag. Restore now preserves the object ETag on both the
single-part and multipart paths, and gives each restored part its own
recorded part ETag rather than the object-level value.

Transition also handed the tier the object's SSE headers and its
RustFS-wrapped data key as request headers. Any S3 target rejected an
SSE-C archive outright, an SSE-KMS archive asked the target to encrypt a
second time under a key id it does not own, and the wrapped DEK left the
cluster. The archive request now strips every SSE header and encryption
marker with the predicate the replication path already uses; the local
xl.meta keeps all of it, so read-through and restore are unaffected.

Objects restored by an affected release are not detected or repaired
retroactively and must be re-restored from the tier.

Refs backlog#2368 B3, B5; backlog#2369 P7.1.

* fix(rio): lock the v1 nonce layout within a segment

Decrypting a v1 segment tried three historical nonce layouts per frame,
independently for every frame. The last of them exists for streams
written before 1.0.0-alpha.91, which reused a segment's part nonce for
every block in it; because block zero's derived nonce equals that base
nonce, a frame encrypted at index zero authenticated at any position. An
attacker able to rewrite the underlying shards could replay it and have
the forged plaintext returned with 200 and an unchanged length. Shard
integrity uses a keyed-hash-free checksum, which such an attacker can
recompute, so it is not a barrier.

A segment now locks onto whichever layout decoded its first non-zero-index
frame and rejects any later frame needing a different one. That leaves one
residual shape: a stream built purely from repeats of frame zero has no
later frame to disagree. New RUSTFS_ENCRYPTION_LEGACY_NONCE_FALLBACK
(default true, so pre-alpha.91 objects keep decrypting) drops the third
layout entirely when set to false, which closes it. Turning it off refuses
pre-alpha.91 objects, so migrate them first by rewriting in place.

Refs backlog#2369 P2.

* fix(kms): reload a service that failed to start

POST /rustfs/admin/v3/kms/reload short-circuited whenever the persisted
configuration matched the in-memory one byte for byte. A node whose KMS
failed to start keeps that configuration and sits in Error, so the
documented recovery call returned "reloaded successfully" while leaving
the node down. Peers reached the same path through the reload broadcast,
so a cluster that lost Vault during a rolling restart had no working
recovery route other than the node-local start endpoint. Reload now
short-circuits only for a service that is actually running, and otherwise
reconfigures, which starts a service that is not running.

The AWS backend also advertised key-version enumeration through
kms/status, which its own documentation says it cannot do; the capability
and its golden snapshot now say false.

Refs backlog#2369 P1, P7.3.

* docs: record the SSE and KMS changes for 1.0.0

The Unreleased changelog section carried no entry for any encryption work
merged since 1.0.0-rc.5, including three items with operational impact:
the config-secret variable whose absence persists secrets in cleartext
with only a warning, the v2 frame write switch and its rolling-upgrade
constraint, and per-key authorization making a public bucket incompatible
with SSE-KMS objects. Adds those plus this batch, including the SSE-KMS
refusal as a breaking change with both routes out.

Also corrects four places where documentation contradicted the code: the
cleanup register still called encrypted range seek opt-in after its
default flipped, the Helm README claimed vault_mount_path only applies to
Transit while the template also feeds the KV2 mount, the disaster-recovery
drill listed bundle contents for backends whose export is refused with
501, and the Chinese README capability table predated most of the feature
set. Documents the SSE-S3 local master key as a first-class operational
mode with its rotation dead end, and what the v1 frame layout does and
does not authenticate.

Refs backlog#2369 P5.

* fix(kms): classify data-path KMS failures by what the caller can do

Only "key not found" and a backend outage were classified; every other
KMS failure that reached the S3 data path fell through to
500 InternalError with a generic message. A disabled or pending-deletion
key, a denied KMS grant, an encryption-context mismatch, an unsupported
algorithm, a credential or timeout failure, and a capability the
configured backend does not have all looked identical to a server fault.
SDKs therefore applied exponential backoff to configuration errors no
retry can fix, and monitoring counted every one of them against the
server's own error rate.

Unusable-key and request-side failures now answer 400, a denied grant
403, transient backend failures 503, and a missing backend capability
501. Damaged, unreadable, or unknown-format key material keeps its 500:
it is a server-side integrity fault, and existing tests pin it.

The classifier is deliberately separate from the admin lifecycle
mapping, which answers 404 for a missing key because there a key id is
the resource being addressed; on the data path it arrives inside a
request header or a bucket default. Messages either name what the caller
asked for or stay generic, with deployment-side detail left on the error
source the way the storage-IO mapping already does.

Refs backlog#2368 B6.

* fix(kms): track and renew static Vault tokens

Token authentication hard-coded "this token carries no lease", so the
renewal task never started, the remaining-TTL gauge was never published,
and nothing looked wrong. `vault token create` grants a 768-hour TTL by
default, so a cluster that had been healthy for a month turned every KMS
call into a 403 and could not recover without a restart or a
reconfigure. Production configuration validation only rejects the
literal dev-token, so an ordinary expiring token reaches a whole cluster.

The source now reads `auth/token/lookup-self` at login and adopts what
Vault reports. A token with no expiry behaves exactly as before. An
expiring renewable one is picked up by the existing renewal loop and
renewed at half TTL like every other auth method. An expiring
non-renewable one warns with its remaining lifetime and publishes the
gauge, so the fail-closed window is visible before it arrives.

The probe never fails the login: a policy that omits lookup-self, or a
Vault that is briefly unreachable, warns and falls back to exactly the
previous behaviour rather than taking down a deployment that works
today. The scripted Vault test double answers the lookup out of band so
existing scripts keep describing only the protocol under test.

Refs backlog#2369 P3.

* feat(sse): report SSE-C requests that arrive without TLS

An SSE-C request carries the customer's AES key in a request header, so
AWS S3 and MinIO both refuse one that did not arrive over TLS. RustFS
accepted them on any transport: a plaintext hop hands the key to anyone
on the path, and since the object cannot be read without that same key,
the exposure lasts as long as the object does.

Refusing outright is the correct end state but not a safe default to
adopt inside a release window, because the project's own s3-tests and
e2e lanes and most staging deployments speak plain HTTP. This release
reports instead: each such request increments
rustfs_ssec_plaintext_requests_total and logs one warning per process, so
an operator can confirm nothing would break before the default flips.
RUSTFS_SSE_C_REQUIRE_TLS=true opts into the AWS 400 now.

The verdict is per connection rather than per deployment: the layer is
built with whether this listener terminated TLS, and additionally accepts
an https protocol forwarded by a proxy the trusted-proxy configuration
already vetted. It sits beside the rate limiter, after the layer that
makes a forwarded protocol trustworthy and after the request context, so
a rejection can echo the request id.

Refs backlog#2369 P7.2.

* fix(kms): say what a node-local backend means for a cluster

The Local backend keeps key material on each node's own disk and
generates its Argon2id salt per node, so two nodes derive different keys
from the same master_key and an object encrypted on one node cannot be
decrypted on another. Behind a load balancer that surfaces as
intermittent 500s on reads that succeeded moments earlier, with nothing
tying the symptom to the cause: the only signal was a generic
"development, testing and demos only" positioning warning that says
nothing about what actually breaks.

Configuring or reconfiguring Local while the deployment is distributed
now logs a dedicated event and appends the consequence to the configure
response, so the operator who made the change sees it. The product
decision to warn rather than refuse is unchanged.

Refs backlog#2369 P7.4.

* docs: record the remaining SSE and KMS changes for 1.0.0

Adds changelog entries for the KMS data-path status classification, the
Vault static-token lease probe, the SSE-C plaintext-transport report and
its switch, and the node-local backend warning.

Documents two things the backend security guide never stated: that SSE-C
belongs on a secure transport, with the counter and switch to plan the
change around, and that the Local backend cannot be shared by a
multi-node deployment because each node derives different keys from the
same master key.

Refs backlog#2368 B6; backlog#2369 P3, P5, P7.2, P7.4.

* fix(kms): report an unreadable key store as an outage on the S3 path

A backend now distinguishes a key store it could not read from a key
that is genuinely absent, but the S3 boundary collapsed the first one
back onto 500 InternalError through the fallthrough for integrity
faults. The distinction was therefore invisible to the client: a
temporary key-directory outage looked exactly like a permanently damaged
key record, and neither the status nor the metric said the request was
worth retrying.

An unreadable key store joins the retryable class and answers 503, next
to a backend error and a credential failure. Damaged, unreadable or
unknown-format key material keeps its 500.

Refs backlog#2368 B6; builds on rustfs/rustfs#7470.
2026-09-08 22:37:53 +08:00
cxymds 37bda24e1c fix: reject unsupported pool expansion with actionable errors (#7360)
* fix: reject unsupported pool expansion with actionable errors

Report singleton-pool and persisted-topology constraints before misleading startup retries. Preserve single-node multi-drive admission and existing parity policies, and cover format preservation plus operator recovery guidance for issue #6186.

* fix: keep pool layout errors typed

Preserve actionable pool layout diagnostics without adding generic formatted errors. Tighten the shrink-only baseline and assert that both typed payloads survive the I/O boundary.

---------

Co-authored-by: houseme <housemecn@gmail.com>
2026-09-07 11:07:42 +00:00
Zhengchao An e3ca1ca54c chore(release): prepare 1.0.0-rc.5 (#6968) 2026-08-31 23:54:35 +08:00
houseme 759e1041bd feat(nix): add NixOS service module and client package (#6856)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-08-29 16:14:44 +00:00
Halil Teyfik 488af5984c docs: fix Getting Started links (#6782) 2026-08-28 12:42:50 +08:00
Zhengchao An a169dd01a6 chore(release): prepare 1.0.0-rc.4
* chore(release): prepare 1.0.0-rc.4

* chore(release): align release assets for 1.0.0-rc.4
2026-08-27 07:16:52 +08:00
RustFS 1fb5d5a19d docs: remove ROSS Index badge from README (#6514)
Drop the expired Q4 2025 Runa Capital badge from the English and Chinese project READMEs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 18:04:46 +08:00
Zhengchao An d65fba9142 chore(release): prepare 1.0.0-rc.3 2026-08-20 21:50:34 +08:00
Zhengchao An e9f5318027 chore(release): prepare 1.0.0-rc.2 2026-08-15 01:29:08 +08:00
Zhengchao An 778f1dfa21 chore(release): bump version to 1.0.0-rc.1 (#5834)
* chore(release): prepare 1.0.0-rc.1

* chore(release): align release assets for 1.0.0-rc.1
2026-08-08 15:04:11 +08:00
Zhengchao An 2e5cef513f chore(release): prepare 1.0.0-beta.12 (#5461)
* chore(release): prepare 1.0.0-beta.12

* chore(release): align release assets for 1.0.0-beta.12

* chore(deps): refresh release dependencies

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

---------

Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-30 01:31:28 +00:00
Zhengchao An 05886a2c3c docs: fix dead TLS configuration doc links (#5242)
docs.rustfs.com dropped the .html suffix from page URLs, so
https://docs.rustfs.com/integration/tls-configured.html now returns 404.
Point both READMEs at the live canonical URL instead.

Supersedes #5154, which replaced the links with Wayback Machine
snapshots even though the docs site is alive and the page still exists.
2026-07-26 04:56:43 +08:00
Zhengchao An ffcdab900a chore(release): prepare 1.0.0-beta.11 (#5146)
Bump workspace version and release assets to 1.0.0-beta.11.
2026-07-23 01:09:29 +00:00
Zhengchao An 53728a03d3 chore: self-host contributor wall (#5006) 2026-07-18 09:48:36 +00:00
Zhengchao An 825bf0e2d8 ci: self-host star history chart (#5001)
* ci: self-host star history chart

* ci: use animated gradient star chart
2026-07-18 14:33:45 +08:00
Zhengchao An f67e8a6cdc chore(release): prepare 1.0.0-beta.10 (#4946) 2026-07-17 10:57:58 +08:00
houseme 75c3403dcc chore(release): prepare 1.0.0-beta.10-preview.4 (#4908)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-16 14:08:34 +00:00
houseme 07e643cac2 chore(release): prepare 1.0.0-beta.10-preview.1 (#4898)
Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-16 15:24:30 +08:00
houseme 83fe12d6aa chore(release): prepare 1.0.0-beta.9 (#4807)
* chore(release): prepare 1.0.0-beta.9

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

* chore(release): align release assets for 1.0.0-beta.9

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

---------

Co-authored-by: heihutu <heihutu@gmail.com>
2026-07-15 09:03:21 +08:00
majinghe a2ec13ab04 fix(otel): fix container unhealty issue caused by healthy check (#4145)
* fix: fix container unhealty issue caused by healthy check

* update readme file

---------

Co-authored-by: houseme <housemecn@gmail.com>
2026-07-01 21:56:26 +08:00
Zhengchao An 7ae9697d42 docs: close final architecture audit gaps (#3966) 2026-06-28 00:07:42 +08:00
houseme 68400933b5 chore(release): prepare 1.0.0-beta.8 (#3317)
* chore(release): prepare 1.0.0-beta.8

* chore(release): align release assets for 1.0.0-beta.8
2026-06-10 04:34:39 +00:00
cxymds dd5e2c8ae9 docs(docker): clarify bind mount permission setup (#3248)
Co-authored-by: houseme <housemecn@gmail.com>
2026-06-07 09:33:24 +08:00
houseme 66b8699927 chore(release): prepare 1.0.0-beta.7 (#3184)
* chore(release): prepare 1.0.0-beta.7

* chore(release): align release assets for 1.0.0-beta.7
2026-06-03 04:18:50 +00:00
houseme 28bac7fbd6 chore(release): prepare 1.0.0-beta.6 (#3104)
* chore(release): prepare 1.0.0-beta.6

* ci(nix): harden flaky crate fetch handling

* ci(nix): drop magic cache and force fallback

* ci(nix): set explicit user-agent for crate fetch

* ci(nix): adopt determinate nix workflow stack

* ci(nix): add nix user-agent suffix for fetches

* ci(nix): add flakehub cache and align determinate actions

* ci(nix): pin determinate actions to release tags

* ci(nix): disable flakehub auth path in CI cache

* ci(nix): restore stable magic cache baseline

* ci(nix): trust local magic cache substituter

* ci(nix): stop forcing Node24 for JS actions

* ci(nix): drop manual localhost cache config

* ci(nix): adopt latest determinate flakehub stack

* ci(nix): record latest determinate workflow state
2026-05-28 09:21:16 +00:00
houseme b2dfdf85de chore(release): prepare 1.0.0-beta.4 (#3032)
* chore(release): prepare 1.0.0-beta.4

* docs(skill): refine rustfs spec changelog rule

* docs(skill): optimize rustfs release bump workflow
2026-05-20 13:56:43 +00:00
yihong 824c4f7673 docs: fix some dead links (#2975)
Signed-off-by: yihong0618 <zouzou0208@gmail.com>
Co-authored-by: houseme <housemecn@gmail.com>
2026-05-16 10:06:53 +08:00
houseme bdb98598d2 chore(release): prepare 1.0.0-beta.3 (#2957) 2026-05-14 04:27:26 +00:00
majinghe d447da75c1 chore: update version from alpha to beta (#2720)
Co-authored-by: houseme <housemecn@gmail.com>
2026-04-28 23:08:10 +00:00
Henry Guo 2bf4b14394 docs(readme): fix inconsistent startup instructions (#2465)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:28:01 +08:00
无心戈 57138fa660 docs: Update RustFS console access URL to port 9001 (#2442)
Signed-off-by: 无心戈 <wanxger@egeeke.com>
Co-authored-by: 安正超 <anzhengchao@gmail.com>
2026-04-09 21:46:31 +08:00
lunrenyi 6bf0c542a1 docs: add x-cmd and nix installation options (#2306)
Co-authored-by: 安正超 <anzhengchao@gmail.com>
Co-authored-by: houseme <housemecn@gmail.com>
2026-03-30 22:05:46 +08:00
bcdax110 82d9452736 docs: fix incorrect UID in Docker Quick Start of README_ZH (#2149)
Signed-off-by: bcdax110 <1711382287@qq.com>
Co-authored-by: houseme <housemecn@gmail.com>
2026-03-14 09:26:07 +08:00
loverustfs a81bbed551 Fix align 2026-01-28 22:03:42 +08:00
安正超 1db7bac2dc fix: readme list. (#1608) 2026-01-25 09:35:12 +08:00
安正超 fd08be7be2 chore: update README. (#1586) 2026-01-22 22:44:28 +08:00
loverustfs e614e530cf Modify ahead images url 2026-01-10 16:12:40 +08:00
loverustfs 00119548d2 Ahead 2026-01-10 16:11:11 +08:00
loverustfs a5b3522880 Add trendshift 2025-12-30 13:03:15 +08:00
loverustfs e31b4303ed fix link error 2025-12-04 08:26:41 +08:00
loverustfs a2e3a719d3 Improve reading experience 2025-11-28 16:03:41 +08:00
loverustfs 76efee37fa fix error 2025-11-28 15:23:26 +08:00
loverustfs fd7c0964a0 Modify Readme 2025-11-28 15:16:59 +08:00
安正超 8a020ec4d9 wip (#830) 2025-11-11 09:34:58 +08:00
majinghe 64ba52bc1e add rustfs helm chart files (#747)
* add rustfs helm chart files

* update readme file with helm chart

* delete helm chart license file

* fix typo in readme file
2025-10-29 12:23:21 +08:00
DamonXue b47765b4c0 docs: add Star History section to README files (#696)
Co-authored-by: 0xdx2 <xuedamon2@gmail.com>
Co-authored-by: loverustfs <155562731+loverustfs@users.noreply.github.com>
2025-10-24 08:58:58 +08:00
houseme 4168e6c180 chore(docs): move root examples to docs/examples/docker and update README (#663)
* chore(docs): move root `examples` to `docs/examples/docker` and update README

- Move root `examples/` contents into `docs/examples/docker/`.
- Update `docs/examples/README.md` to add migration note, new `docker/` entry and usage examples.
- Replace references from `examples/` to `docs/examples/docker/` where applicable.
- Reminder: verify CI and external links still point to the correct paths.

* fix
2025-10-17 17:17:36 +08:00
loverustfs 9e1739ed8d chore(docs): update README and README_ZH (#649) 2025-10-13 18:49:34 +08:00
majinghe 65dd947350 add tls support for docker compose (#553)
* add tls support for docker compose

* update docker compose file with comment
2025-09-17 22:45:23 +08:00
majinghe ebf30b0db5 update docker compose usage guidence in READEME file (#526) 2025-09-13 16:24:36 +08:00