From c63fcebfe110ad9e7eeaa9213c42e14b1f36e32c Mon Sep 17 00:00:00 2001 From: yxrxy <1532529704@qq.com> Date: Wed, 31 Dec 2025 09:01:15 +0800 Subject: [PATCH] Feat/ftps&sftp (#1308) [feat] ftp / sftp --- Cargo.lock | 418 ++++++++++++++++++++++++++++++++++++- crates/e2e_test/Cargo.toml | 1 + rustfs/Cargo.toml | 2 + rustfs/src/config/mod.rs | 41 ++++ 4 files changed, 457 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e35aca78..f4a0179c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -554,6 +554,17 @@ dependencies = [ "xattr", ] +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + [[package]] name = "async-channel" version = "2.5.0" @@ -578,13 +589,60 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.3", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-lock" version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -600,6 +658,12 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.89" @@ -1208,6 +1272,17 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "bcrypt-pbkdf" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2" +dependencies = [ + "blowfish", + "pbkdf2 0.12.2", + "sha2 0.10.9", +] + [[package]] name = "bigdecimal" version = "0.4.10" @@ -3106,6 +3181,38 @@ dependencies = [ "cipher 0.5.0-rc.3", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.111", + "unicode-xid", +] + +[[package]] +name = "des" +version = "0.9.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512ca722eff02fa73c43e5136f440c46f861d41f9dd7761c1f2817a5ca5d9ad7" +dependencies = [ + "cipher 0.5.0-rc.2", +] + [[package]] name = "diff" version = "0.1.13" @@ -3216,6 +3323,7 @@ dependencies = [ "rustfs-common", "rustfs-ecstore", "rustfs-filemeta", + "rustfs-iam", "rustfs-lock", "rustfs-madmin", "rustfs-protos", @@ -3373,6 +3481,18 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "enumset" version = "1.1.10" @@ -3469,6 +3589,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "event-listener" version = "5.4.1" @@ -3486,7 +3612,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] @@ -3659,6 +3785,21 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -3879,6 +4020,16 @@ dependencies = [ "polyval 0.6.2", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval 0.6.2", +] + [[package]] name = "ghash" version = "0.6.0-rc.3" @@ -3900,6 +4051,18 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "google-cloud-auth" version = "1.4.0" @@ -5126,6 +5289,72 @@ dependencies = [ "rand 0.9.2", ] +[[package]] +name = "libcrux-intrinsics" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9ee7ef66569dd7516454fe26de4e401c0c62073929803486b96744594b9632" +dependencies = [ + "core-models", + "hax-lib", +] + +[[package]] +name = "libcrux-ml-kem" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6a88086bf11bd2ec90926c749c4a427f2e59841437dbdede8cde8a96334ab" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-secrets", + "libcrux-sha3", + "libcrux-traits", + "rand 0.9.2", + "tls_codec", +] + +[[package]] +name = "libcrux-platform" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db82d058aa76ea315a3b2092f69dfbd67ddb0e462038a206e1dcd73f058c0778" +dependencies = [ + "libc", +] + +[[package]] +name = "libcrux-secrets" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4dbbf6bc9f2bc0f20dc3bea3e5c99adff3bdccf6d2a40488963da69e2ec307" +dependencies = [ + "hax-lib", +] + +[[package]] +name = "libcrux-sha3" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2400bec764d1c75b8a496d5747cffe32f1fb864a12577f0aca2f55a92021c962" +dependencies = [ + "hax-lib", + "libcrux-intrinsics", + "libcrux-platform", + "libcrux-traits", +] + +[[package]] +name = "libcrux-traits" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9adfd58e79d860f6b9e40e35127bfae9e5bd3ade33201d1347459011a2add034" +dependencies = [ + "libcrux-secrets", + "rand 0.9.2", +] + [[package]] name = "libloading" version = "0.8.9" @@ -5183,6 +5412,20 @@ dependencies = [ "redox_syscall 0.7.0", ] +[[package]] +name = "libssh2-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + [[package]] name = "libsystemd" version = "0.7.2" @@ -5236,6 +5479,18 @@ dependencies = [ "x509-parser 0.17.0", ] +[[package]] +name = "libz-sys" +version = "1.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -5512,7 +5767,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "equivalent", - "event-listener", + "event-listener 5.4.1", "futures-util", "parking_lot", "portable-atomic", @@ -5527,6 +5782,23 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework 2.11.1", + "security-framework-sys", + "tempfile", +] + [[package]] name = "neli" version = "0.7.3" @@ -5930,6 +6202,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry" version = "0.31.0" @@ -6433,6 +6717,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.8.0-rc.4" @@ -6524,6 +6819,20 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + [[package]] name = "pollster" version = "0.4.0" @@ -7615,6 +7924,7 @@ dependencies = [ "moka", "pin-project-lite", "pprof", + "rand 0.8.5", "reqwest", "rmp-serde", "russh", @@ -7809,7 +8119,7 @@ dependencies = [ name = "rustfs-ecstore" version = "0.0.5" dependencies = [ - "async-channel", + "async-channel 2.5.0", "async-recursion", "async-trait", "aws-config", @@ -8377,7 +8687,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.5.1", ] [[package]] @@ -9244,6 +9554,92 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "aes 0.8.4", + "aes-gcm 0.10.3", + "cbc", + "chacha20 0.9.1", + "cipher 0.4.4", + "ctr 0.9.2", + "poly1305 0.8.0", + "ssh-encoding 0.2.0", + "subtle", +] + +[[package]] +name = "ssh-cipher" +version = "0.3.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361de425e489d5fe3f1ecfd91531c8fe91ededbbc567e24b77a560d503309bf9" +dependencies = [ + "aes 0.9.0-rc.2", + "aes-gcm 0.11.0-rc.2", + "chacha20 0.10.0-rc.5", + "cipher 0.5.0-rc.2", + "des", + "poly1305 0.9.0-rc.3", + "ssh-encoding 0.3.0-rc.3", + "zeroize", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "bytes", + "pem-rfc7468 0.7.0", + "sha2 0.10.9", +] + +[[package]] +name = "ssh-encoding" +version = "0.3.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ad6a09263583e83e934fcd436b7e3bb9d69602e2feef3787adb615c1fe3a343" +dependencies = [ + "base64ct", + "digest 0.11.0-rc.4", + "pem-rfc7468 1.0.0", + "subtle", + "zeroize", +] + +[[package]] +name = "ssh-key" +version = "0.7.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faefb89d4a5304e31238913d1f7f164e22494276ed58cd84d5058ba7b04911f" +dependencies = [ + "rand_core 0.10.0-rc-2", + "sec1 0.8.0-rc.10", + "sha2 0.11.0-rc.3", + "signature 3.0.0-rc.5", + "ssh-cipher 0.3.0-rc.4", + "ssh-encoding 0.3.0-rc.3", + "subtle", + "zeroize", +] + +[[package]] +name = "ssh2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f84d13b3b8a0d4e91a2629911e951db1bb8671512f5c09d7d4ba34500ba68c8" +dependencies = [ + "bitflags 2.10.0", + "libc", + "libssh2-sys", + "parking_lot", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -10277,6 +10673,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -10400,6 +10802,12 @@ dependencies = [ "url", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" diff --git a/crates/e2e_test/Cargo.toml b/crates/e2e_test/Cargo.toml index 8fa99d21..bbcde07f 100644 --- a/crates/e2e_test/Cargo.toml +++ b/crates/e2e_test/Cargo.toml @@ -26,6 +26,7 @@ workspace = true [dependencies] rustfs-ecstore.workspace = true rustfs-common.workspace = true +rustfs-iam.workspace = true flatbuffers.workspace = true futures.workspace = true rustfs-lock.workspace = true diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index df2f23d9..9c320935 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -115,6 +115,8 @@ md5.workspace = true mime_guess = { workspace = true } moka = { workspace = true } pin-project-lite.workspace = true +# rand = "0.8" is pinned due to dependency conflicts with workspace version +rand = "0.8" rust-embed = { workspace = true, features = ["interpolate-folder-path"] } s3s.workspace = true shadow-rs = { workspace = true, features = ["build", "metadata"] } diff --git a/rustfs/src/config/mod.rs b/rustfs/src/config/mod.rs index 87462eb2..576dc5ca 100644 --- a/rustfs/src/config/mod.rs +++ b/rustfs/src/config/mod.rs @@ -159,6 +159,47 @@ pub struct Opt { /// Options: GeneralPurpose, AiTraining, DataAnalytics, WebWorkload, IndustrialIoT, SecureStorage #[arg(long, default_value_t = String::from("GeneralPurpose"), env = "RUSTFS_BUFFER_PROFILE")] pub buffer_profile: String, + + /// Enable FTPS server + #[arg(long, default_value_t = false, env = "RUSTFS_FTPS_ENABLE")] + pub ftps_enable: bool, + + /// FTPS server bind address + #[arg(long, default_value_t = String::from("0.0.0.0:21"), env = "RUSTFS_FTPS_ADDRESS")] + pub ftps_address: String, + + /// FTPS server certificate file path + #[arg(long, env = "RUSTFS_FTPS_CERTS_FILE")] + pub ftps_certs_file: Option, + + /// FTPS server private key file path + #[arg(long, env = "RUSTFS_FTPS_KEY_FILE")] + pub ftps_key_file: Option, + + /// FTPS server passive ports range (e.g., "40000-50000") + #[arg(long, env = "RUSTFS_FTPS_PASSIVE_PORTS")] + pub ftps_passive_ports: Option, + + /// FTPS server external IP address for passive mode (auto-detected if not specified) + #[arg(long, env = "RUSTFS_FTPS_EXTERNAL_IP")] + pub ftps_external_ip: Option, + + /// Enable SFTP server + #[arg(long, default_value_t = false, env = "RUSTFS_SFTP_ENABLE")] + pub sftp_enable: bool, + + /// SFTP server bind address + #[arg(long, default_value_t = String::from("0.0.0.0:22"), env = "RUSTFS_SFTP_ADDRESS")] + pub sftp_address: String, + + /// SFTP server host key file path + #[arg(long, env = "RUSTFS_SFTP_HOST_KEY")] + pub sftp_host_key: Option, + + /// Path to authorized SSH public keys file for SFTP authentication + /// Each line should contain an OpenSSH public key: ssh-rsa AAAA... comment + #[arg(long, env = "RUSTFS_SFTP_AUTHORIZED_KEYS")] + pub sftp_authorized_keys: Option, } impl std::fmt::Debug for Opt {