You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added full SFTPv3 functionality. Added SFTP subsystem to the protocols crate, gated behind the new sftp cargo feature. The driver translates each SFTPv3 packet into an S3 call against the existing StorageBackend, so SFTP shares the same bucket layout, IAM, and lifecycle rules as the existing FTPS, WebDAV, and Swift drivers. SSH username maps to the IAM access key and SSH password to the secret key.
Added russh 0.60 and russh-sftp 2.1 as workspace dependencies. A temporary [patch.crates-io] entry pins russh to a fork branch carrying the upstream fix at Eugeny/russh#702. The patch resolves an rsa 0.10.0-rc.18 vs pkcs5 prerelease conflict that no released russh version handles. It is removed once the russh PR merges and a release ships.
Added 33 SFTPv3 compliance test cases (test_sftp_compliance_suite shared-session, test_sftp_compliance_readonly, test_sftp_compliance_standalone one-spawn-per-case) plus four regression-prevention layers guarding against silent feature deletion: compile-time module assertion, module-presence unit test, cross-module Protocol enum assertion, and end-to-end SSH banner test against the running binary.
Refs rustfs#2478.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+82-1Lines changed: 82 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,11 +22,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
22
22
- XML-formatted error responses compatible with S3 API
23
23
- Comprehensive integration documentation with manual testing guide
24
24
-**32 unit and integration tests** covering middleware, auth handlers, task-local storage, and role detection
25
+
-**SFTPv3 Protocol Support**: SSH-hosted SFTPv3 subsystem that translates each file operation into S3 calls against the local object store. Authentication uses IAM credentials (SSH username = access key, SSH password = secret key).
26
+
- Full SFTPv3 packet coverage: open, read, write, stat, lstat, fstat, mkdir, rmdir, rename, remove, opendir, readdir, realpath, close, plus the rest of the 21-packet specification
27
+
- Streaming multipart write up to S3's 5 TiB per-file ceiling
28
+
- Per-handle read-ahead cache with configurable window size and process-wide memory ceiling
29
+
- Per-session liveness watchdog: Linux probes `/proc/net/tcp` and cancels wedged sessions on the order of 45 seconds; non-Linux falls back to an inactivity ceiling on the order of 30 minutes
- 33 SFTPv3 compliance test cases under `crates/e2e_test/src/protocols/sftp_compliance.rs` spread across three entry points: `test_sftp_compliance_suite` (shared session), `test_sftp_compliance_readonly` (read-only mode), and `test_sftp_compliance_standalone` (one rustfs spawn per case)
32
+
- Four-layer regression-prevention tests guard against silent feature deletion: compile-time module assertion, module-presence unit test, cross-module `Protocol` enum assertion, end-to-end SSH banner test against the running binary
25
33
26
34
### Changed
27
35
-**HTTP Server Stack**: Integrated `KeystoneAuthLayer` middleware from `rustfs-keystone` crate into service stack (positioned after ReadinessGateLayer)
28
36
-**IAMAuth**: Enhanced `get_secret_key()` to return empty secret for Keystone credentials (bypasses signature validation)
29
37
-**Auth Module**: Modified `check_key_valid()` to retrieve Keystone credentials from task-local storage and determine admin status
38
+
-**`StorageBackend` trait**: extended with multipart upload methods (`create_multipart_upload`, `upload_part`, `complete_multipart_upload`, `abort_multipart_upload`) plus `upload_part_copy`. Streaming-upload code path is now available to FTPS, WebDAV, and Swift drivers as well.
39
+
-**`Protocol` enum**: new `Protocol::Sftp` variant with corresponding `S3Action` mappings. Every match arm on `Protocol` updated to handle the new variant exhaustively.
30
40
31
41
### Technical Details
32
42
- Middleware is self-contained in `rustfs-keystone` crate following the trusted-proxies pattern for integration-specific middleware
@@ -35,12 +45,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
35
45
- Integration preserves existing S3 authentication flow while adding Keystone support
36
46
- Zero breaking changes to existing functionality
37
47
- No new top-level directories in main binary crate (middleware lives in integration crate)
48
+
- SSH/SFTP wire handling via the `russh` and `russh-sftp` crates. SFTPv3 framing is implemented by `russh-sftp`; the rustfs-side `SftpDriver` implements `russh_sftp::server::Handler` and dispatches to the storage backend
49
+
- Drop-time abort for in-flight multipart uploads honours IAM Deny on `AbortMultipartUpload`. `start_multipart_upload` caches the authorisation decision so the synchronous `Drop` path can honour Allow / Deny policies without re-querying IAM
50
+
- Per-handle read cache uses an `Arc<AtomicU64>` shared across every `SftpDriver` instance to enforce a process-wide memory ceiling. On ceiling breach the populate is skipped and the read serves correctly via a single-call backend fetch
51
+
- Per-session liveness watchdog runs as a tokio task per accepted connection. Reads `/proc/net/tcp` and `/proc/net/tcp6` to look up the (local, peer) tuple's TCP state and cancels via `tokio_util::sync::CancellationToken` when wedge conditions are confirmed across two consecutive ticks
52
+
- Path canonicalisation rejects paths containing `\0`, `\r`, or `\n` and resolves traversal via `path::clean()` before any backend dispatch
53
+
- Cipher / KEX / MAC / host-key algorithm allowlists are hardcoded with no environment override. Strict-KEX (CVE-2023-48795 / Terrapin) marker presence asserted by unit test
54
+
- Per-session handle cap (default 64, configurable 8 to 1024) with UUID-generated handle ids
55
+
- Crate-level `#![deny(unsafe_code)]` is in force across `crates/protocols`. Socket fd duplication for the watchdog uses the safe `AsFd::try_clone_to_owned` path (Linux/Unix); non-Unix falls back to the inactivity ceiling
56
+
-`cfg(unix)` gating around platform-specific imports (`std::os::fd::AsFd`, `std::os::unix::fs::PermissionsExt`); non-Unix targets fail SFTP at config-load with `SftpInitError::UnsupportedPlatform`
38
57
39
58
### Documentation
40
59
- Updated `crates/keystone/README.md` with complete integration architecture and workflow
41
60
- Added detailed manual testing guide with 10 test scenarios
42
61
- Updated main `README.md` to list Keystone authentication as available feature
43
62
- Added troubleshooting section for common integration issues
63
+
- Module-level rustdoc on `crates/protocols/src/sftp/mod.rs` describing the public API surface, configuration contract, and the architecture of the read cache and the wedge watchdog
-`crates/protocols/src/sftp/driver.rs` - `SftpDriver` per-session SFTPv3 handler dispatching each operation onto the `StorageBackend`
95
+
-`crates/protocols/src/sftp/state.rs` - `HandleState` variants for read, write-buffering, write-streaming, write-failed handles
96
+
-`crates/protocols/src/sftp/lifecycle.rs` - Per-session activity stamp, weak-ref registry, `/proc/net/tcp` probe for the wedge watchdog
97
+
-`crates/protocols/src/sftp/wedge_watchdog.rs` - Per-session liveness watchdog cancelling sessions silent at the SFTP layer while the kernel reports CLOSE_WAIT
98
+
-`crates/protocols/src/sftp/read_cache.rs` - Per-handle in-memory read-ahead cache with shared atomic accumulator for the process-wide memory ceiling
99
+
-`crates/protocols/src/sftp/attrs.rs` - SFTPv3 `FileAttributes` mapping for objects and directories, longname formatting, mtime clamping
100
+
-`crates/protocols/src/sftp/dir.rs` - OPENDIR / READDIR pagination, root-bucket listing, sub-directory listing under a prefix
101
+
-`crates/protocols/src/sftp/errors.rs` - `SftpError` thiserror enum and S3-error classification into SFTPv3 status codes
-`crates/protocols/src/sftp/read.rs` - READ packet handler, EOF semantics, `MAX_READ_LEN` bound, integration with the read cache
104
+
-`crates/protocols/src/sftp/write.rs` - WRITE packet handler, in-memory buffering up to part size, transition to streaming multipart, CLOSE finalisation
105
+
-`crates/protocols/src/sftp/test_support.rs` - Test fixtures and helper builders for SFTP unit tests
106
+
-`crates/protocols/src/common/dummy_storage.rs` - In-memory `StorageBackend` test backend covering every method, used by SFTP unit tests and the FTPS / Swift / WebDAV test suites
107
+
-`crates/e2e_test/src/protocols/sftp_core.rs` - End-to-end regressions for the handshake deadline, idle-timeout disconnect, and the wedge watchdog
108
+
-`crates/e2e_test/src/protocols/sftp_compliance.rs` - SFTPv3 compliance suite entry points (`test_sftp_compliance_suite`, `test_sftp_compliance_readonly`, `test_sftp_compliance_standalone`)
-`README.md` - Added Keystone as available feature
120
+
-`Cargo.toml` - Added the `sftp` feature alongside the existing protocol features
121
+
-`Cargo.lock` - Updated to include the new `russh`, `russh-sftp`, `socket2`, `tokio-util`, `subtle`, `uuid` dependencies and their transitive crates
122
+
-`crates/protocols/Cargo.toml` - Declared `russh`, `russh-sftp`, `socket2`, `tokio-util`, `subtle`, `uuid` under the `sftp` feature flag
123
+
-`crates/protocols/src/lib.rs` - Added `pub mod sftp` behind `#[cfg(feature = "sftp")]` plus the crate-level `#![deny(unsafe_code)]` lint
124
+
-`crates/protocols/src/common/client/s3.rs` - Extended the `StorageBackend` trait with `create_multipart_upload`, `upload_part`, `complete_multipart_upload`, `abort_multipart_upload`, and `upload_part_copy`
125
+
-`crates/protocols/src/common/session.rs` - Added the `Protocol::Sftp` variant and its `S3Action` mappings
126
+
-`crates/protocols/src/common/gateway.rs` - Handles the new `Protocol::Sftp` variant exhaustively
127
+
-`crates/protocols/src/common/mod.rs` - Exposed the new `dummy_storage` module
128
+
-`crates/protocols/src/constants.rs` - Added shared POSIX mode-bit constants used by SFTP and other protocols
129
+
-`crates/config/src/constants/protocols.rs` - `RUSTFS_SFTP_*` environment variable names and defaults
130
+
-`crates/utils/src/retry.rs` - Added the generic exponential-backoff retry helper used by the SFTP write path
131
+
-`crates/e2e_test/Cargo.toml` - Added the e2e test dependencies for SFTP (paramiko fixture, SSH keypair generation)
132
+
-`crates/e2e_test/src/protocols/mod.rs` - Registered the new `sftp_core`, `sftp_compliance`, `sftp_compliance_tests`, and `sftp_helpers` modules
133
+
-`crates/e2e_test/src/protocols/README.md` - Documented the SFTP test entry points and case index
134
+
-`crates/e2e_test/src/protocols/test_env.rs` - Added SFTP host-key directory provisioning to the shared protocol test environment
135
+
-`crates/e2e_test/src/protocols/test_runner.rs` - Wired the SFTP entry points into the runner
136
+
-`rustfs/Cargo.toml` - Added the `sftp` feature flag
137
+
-`rustfs/src/lib.rs` - One-line addition exporting the SFTP wiring
138
+
-`rustfs/src/init.rs` - Build and start the `SftpServer` when `RUSTFS_SFTP_ENABLE` is true
139
+
-`rustfs/src/main.rs` - Routed shutdown signals to the SFTP server alongside the other protocols
140
+
-`rustfs/src/protocols/client.rs` - Client-builder support for the new `Protocol::Sftp` variant
66
141
67
142
### Testing
68
143
- 16 unit tests in rustfs-keystone crate (config, auth, middleware, identity)
- 6 auth unit tests in rustfs crate (role detection, task-local storage, Keystone credential handling)
71
146
-**Total: 32 tests** passing with zero compilation errors
72
147
- Manual testing guide provided for end-to-end validation
73
-
- All tests passing with `cargo test --all --exclude e2e_test`
148
+
- All Keystone tests passing with `cargo test --all --exclude e2e_test`
149
+
- 33 SFTPv3 compliance test cases (CMPTST-01..33) split across three entry points: `test_sftp_compliance_suite` (shared session, cases 01-14), `test_sftp_compliance_readonly` (read-only mode, cases 15-23), `test_sftp_compliance_standalone` (one rustfs spawn per case, cases 24-33)
150
+
- Regression-prevention tests at four layers: compile-time module assertion in `crates/protocols/src/lib.rs`, module-presence unit test in `crates/protocols/src/sftp/mod.rs`, cross-module `Protocol` enum assertion, and end-to-end SSH banner test against the running binary
151
+
- Standalone end-to-end regressions for the SSH handshake deadline, the idle-timeout disconnect path, and the wedge watchdog (Linux fast-kill and the cross-platform fallback path)
152
+
- Inline unit tests in every SFTP source file covering pure helpers (path canonicalisation, attribute mapping, S3-error classification, env-var bound resolvers)
153
+
- Strict-KEX (CVE-2023-48795) marker presence assertion as a unit test in `crates/protocols/src/sftp/server.rs`
154
+
- All tests passing with `cargo test --all --features sftp` against a 64-bit Linux target
0 commit comments