Files
rustfs/crates/protocols/src/sftp/mod.rs
T
houseme 6185d38911 fix(protocols): add hot reload for WebDAV FTPS and SFTP (#2922)
Signed-off-by: houseme <housemecn@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-11 16:25:20 +00:00

128 lines
5.4 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.
//! SFTP protocol support for RustFS.
//!
//! Provides an SSH server with the SFTP file transfer subsystem enabled.
//! Each SFTP operation is translated into one or more S3 API calls against
//! the local RustFS object store via the StorageBackend trait.
//!
//! The module is feature-gated behind the sftp feature and is composed of
//! seven user-facing submodules:
//!
//! - config: configuration loading from environment variables, plus host
//! key discovery and validation.
//! - constants: protocol limits, timeouts, and other named numeric values
//! used by the server and driver.
//! - server: russh handler implementation, password authentication against
//! IAM, and subsystem dispatch onto the SFTP driver.
//! - driver: SFTP operation handlers that translate each request into one
//! or more S3 calls on the supplied storage backend.
//! - lifecycle: per-session activity record, the registry the accept loop
//! walks, and the kernel TCP-state probe used by the watchdog.
//! - wedge_watchdog: per-session liveness watchdog that observes both the
//! SFTP-handler activity stamp and the TCP socket state.
//! - read_cache: per-handle in-memory read-ahead cache with a process-wide
//! memory ceiling.
//!
//! Configuration contract. Thirteen RUSTFS_SFTP_* environment variables drive
//! the server: RUSTFS_SFTP_ENABLE, RUSTFS_SFTP_ADDRESS, RUSTFS_SFTP_HOST_KEY_DIR,
//! RUSTFS_SFTP_HOST_KEY_RELOAD_ENABLE, RUSTFS_SFTP_HOST_KEY_RELOAD_INTERVAL,
//! RUSTFS_SFTP_IDLE_TIMEOUT, RUSTFS_SFTP_PART_SIZE, RUSTFS_SFTP_READ_ONLY,
//! RUSTFS_SFTP_BANNER, RUSTFS_SFTP_HANDLES_PER_SESSION,
//! RUSTFS_SFTP_BACKEND_OP_TIMEOUT_SECS, RUSTFS_SFTP_READ_CACHE_WINDOW_BYTES,
//! RUSTFS_SFTP_READ_CACHE_TOTAL_MEM_BYTES. Defaults and validation bounds
//! live on the constants in the limits module.
//!
//! Architecture. Two cross-cutting subsystems backstop session reliability
//! and read throughput:
//!
//! - Session-liveness watchdog. Every accepted connection runs under a
//! per-session watchdog that observes the SFTP-handler activity stamp
//! and the kernel TCP state for the connection. Sessions that fall
//! silent at the SFTP layer while the kernel reports CLOSE_WAIT are
//! canceled on a bounded schedule. The watchdog backstops resource
//! accumulation regardless of which layer stalled. On Linux the
//! detection latency is on the order of 45 seconds; on non-Linux
//! targets the watchdog falls back to an inactivity ceiling on the
//! order of 30 minutes.
//!
//! - Per-handle read cache. Each open File handle holds an in-memory
//! buffer. On a cache miss the driver fetches a configurable byte
//! window from the backend, returns the requested portion, and stores
//! the rest. Subsequent reads inside that window are served from
//! memory. Total cache memory across every live handle is bounded by
//! a shared atomic accumulator enforced against the process-wide
//! ceiling. On ceiling breach the population is skipped and the read
//! serves correctly via a single backend call without storing the
//! bytes for re-use.
//!
//! Authentication mirrors the S3 baseline: identities are looked up through
//! rustfs_iam and the supplied secret is compared in constant time against
//! the stored secret. Failures are logged via tracing warn and return an SSH
//! authentication rejection.
//!
//! Public types: SftpServer is the entry point an embedder constructs and
//! drives. SftpConfig and SftpInitError are the configuration and error
//! types returned by configuration loading. SftpDriver is the per-session
//! handler dispatch type. SftpError is the error type returned by SFTP
//! operations.
//!
//! Platform support. Host-key permission enforcement uses Unix mode bits.
//! On non-Unix targets SftpConfig::load_host_keys returns
//! SftpInitError::UnsupportedPlatform and the SFTP listener does not start.
//!
//! Peer-initiated signal requests on an open SFTP channel are intercepted
//! by the russh::server::Handler::signal override on SshSessionHandler in
//! server.rs, which logs the probe and rejects without acting.
pub mod config;
pub(crate) mod constants;
pub mod server;
mod attrs;
mod dir;
mod driver;
mod errors;
mod lifecycle;
mod paths;
mod read;
mod read_cache;
mod state;
mod wedge_watchdog;
mod write;
#[cfg(test)]
mod test_support;
pub use config::{SftpConfig, SftpInitError};
pub use driver::SftpDriver;
pub use errors::SftpError;
pub use server::SftpServer;
#[cfg(test)]
mod tests {
use super::*;
use crate::common::session::Protocol;
// Compile-time check that Protocol::Sftp, SftpConfig, and SftpInitError
// remain exported. Renaming or removing any of these breaks the test.
#[test]
fn sftp_module_and_variant_exist() {
let _variant = Protocol::Sftp;
let _config_type_name = std::any::type_name::<SftpConfig>();
let _error_type_name = std::any::type_name::<SftpInitError>();
}
}