mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-11 23:56:53 +00:00
chore: replace native-tls with pure rustls for FTPS/SFTP e2e tests (#1334)
Signed-off-by: yxrxy <1532529704@qq.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+1
-2
@@ -115,8 +115,7 @@ 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"
|
||||
rand = { workspace = true }
|
||||
rust-embed = { workspace = true, features = ["interpolate-folder-path"] }
|
||||
s3s.workspace = true
|
||||
shadow-rs = { workspace = true, features = ["build", "metadata"] }
|
||||
|
||||
@@ -135,47 +135,6 @@ 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<String>,
|
||||
|
||||
/// FTPS server private key file path
|
||||
#[arg(long, env = "RUSTFS_FTPS_KEY_FILE")]
|
||||
pub ftps_key_file: Option<String>,
|
||||
|
||||
/// FTPS server passive ports range (e.g., "40000-50000")
|
||||
#[arg(long, env = "RUSTFS_FTPS_PASSIVE_PORTS")]
|
||||
pub ftps_passive_ports: Option<String>,
|
||||
|
||||
/// 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<String>,
|
||||
|
||||
/// 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<String>,
|
||||
|
||||
/// 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<String>,
|
||||
}
|
||||
|
||||
// lazy_static::lazy_static! {
|
||||
|
||||
+28
-18
@@ -320,32 +320,38 @@ pub(crate) fn init_buffer_profile_system(opt: &config::Opt) {
|
||||
/// as other services and MUST integrate with the global shutdown system.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn init_ftp_system(
|
||||
opt: &crate::config::Opt,
|
||||
shutdown_tx: tokio::sync::broadcast::Sender<()>,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
use crate::protocols::ftps::server::{FtpsConfig, FtpsServer};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
// Check if FTPS is enabled
|
||||
if !opt.ftps_enable {
|
||||
let ftps_enable = rustfs_utils::get_env_bool(rustfs_config::ENV_FTPS_ENABLE, false);
|
||||
if !ftps_enable {
|
||||
debug!("FTPS system is disabled");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Parse FTPS address
|
||||
let addr: SocketAddr = opt
|
||||
.ftps_address
|
||||
let ftps_address_str = rustfs_utils::get_env_str(rustfs_config::ENV_FTPS_ADDRESS, rustfs_config::DEFAULT_FTPS_ADDRESS);
|
||||
let addr: SocketAddr = ftps_address_str
|
||||
.parse()
|
||||
.map_err(|e| format!("Invalid FTPS address '{}': {}", opt.ftps_address, e))?;
|
||||
.map_err(|e| format!("Invalid FTPS address '{}': {}", ftps_address_str, e))?;
|
||||
|
||||
// Get FTPS configuration from environment variables
|
||||
let cert_file = rustfs_utils::get_env_opt_str(rustfs_config::ENV_FTPS_CERTS_FILE);
|
||||
let key_file = rustfs_utils::get_env_opt_str(rustfs_config::ENV_FTPS_KEY_FILE);
|
||||
let passive_ports = rustfs_utils::get_env_opt_str(rustfs_config::ENV_FTPS_PASSIVE_PORTS);
|
||||
let external_ip = rustfs_utils::get_env_opt_str(rustfs_config::ENV_FTPS_EXTERNAL_IP);
|
||||
|
||||
// Create FTPS configuration
|
||||
let config = FtpsConfig {
|
||||
bind_addr: addr,
|
||||
passive_ports: opt.ftps_passive_ports.clone(),
|
||||
external_ip: opt.ftps_external_ip.clone(),
|
||||
passive_ports,
|
||||
external_ip,
|
||||
ftps_required: true,
|
||||
cert_file: opt.ftps_certs_file.clone(),
|
||||
key_file: opt.ftps_key_file.clone(),
|
||||
cert_file,
|
||||
key_file,
|
||||
};
|
||||
|
||||
// Create FTPS server
|
||||
@@ -380,31 +386,35 @@ pub async fn init_ftp_system(
|
||||
/// as other services and MUST integrate with the global shutdown system.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn init_sftp_system(
|
||||
opt: &config::Opt,
|
||||
shutdown_tx: tokio::sync::broadcast::Sender<()>,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
use crate::protocols::sftp::server::{SftpConfig, SftpServer};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
// Check if SFTP is enabled
|
||||
if !opt.sftp_enable {
|
||||
let sftp_enable = rustfs_utils::get_env_bool(rustfs_config::ENV_SFTP_ENABLE, false);
|
||||
if !sftp_enable {
|
||||
debug!("SFTP system is disabled");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Parse SFTP address
|
||||
let addr: SocketAddr = opt
|
||||
.sftp_address
|
||||
let sftp_address_str = rustfs_utils::get_env_str(rustfs_config::ENV_SFTP_ADDRESS, rustfs_config::DEFAULT_SFTP_ADDRESS);
|
||||
let addr: SocketAddr = sftp_address_str
|
||||
.parse()
|
||||
.map_err(|e| format!("Invalid SFTP address '{}': {}", opt.sftp_address, e))?;
|
||||
.map_err(|e| format!("Invalid SFTP address '{}': {}", sftp_address_str, e))?;
|
||||
|
||||
// Get SFTP configuration from environment variables
|
||||
let host_key = rustfs_utils::get_env_opt_str(rustfs_config::ENV_SFTP_HOST_KEY);
|
||||
let authorized_keys = rustfs_utils::get_env_opt_str(rustfs_config::ENV_SFTP_AUTHORIZED_KEYS);
|
||||
|
||||
// Create SFTP configuration
|
||||
let config = SftpConfig {
|
||||
bind_addr: addr,
|
||||
require_key_auth: false, // TODO: Add key auth configuration
|
||||
cert_file: None, // CA certificates for client certificate authentication
|
||||
key_file: opt.sftp_host_key.clone(), // SFTP server host key
|
||||
authorized_keys_file: opt.sftp_authorized_keys.clone(), // Pre-loaded authorized SSH public keys
|
||||
require_key_auth: false, // TODO: Add key auth configuration
|
||||
cert_file: None, // CA certificates for client certificate authentication
|
||||
key_file: host_key, // SFTP server host key
|
||||
authorized_keys_file: authorized_keys, // Pre-loaded authorized SSH public keys
|
||||
};
|
||||
|
||||
// Create SFTP server
|
||||
|
||||
+2
-6
@@ -272,14 +272,10 @@ async fn run(opt: config::Opt) -> Result<()> {
|
||||
let (ftp_sftp_shutdown_tx, _) = tokio::sync::broadcast::channel(1);
|
||||
|
||||
// Initialize FTP system if enabled
|
||||
init_ftp_system(&opt, ftp_sftp_shutdown_tx.clone())
|
||||
.await
|
||||
.map_err(Error::other)?;
|
||||
init_ftp_system(ftp_sftp_shutdown_tx.clone()).await.map_err(Error::other)?;
|
||||
|
||||
// Initialize SFTP system if enabled
|
||||
init_sftp_system(&opt, ftp_sftp_shutdown_tx.clone())
|
||||
.await
|
||||
.map_err(Error::other)?;
|
||||
init_sftp_system(ftp_sftp_shutdown_tx.clone()).await.map_err(Error::other)?;
|
||||
|
||||
// Initialize buffer profiling system
|
||||
init_buffer_profile_system(&opt);
|
||||
|
||||
@@ -10,27 +10,23 @@ RustFS provides multiple protocol interfaces for accessing object storage, inclu
|
||||
### Enable Protocols on Startup
|
||||
|
||||
```bash
|
||||
# Start RustFS with all protocols enabled
|
||||
rustfs \
|
||||
--address 0.0.0.0:9000 \
|
||||
--access-key rustfsadmin \
|
||||
--secret-key rustfsadmin \
|
||||
--ftps-enable \
|
||||
--ftps-address 0.0.0.0:21 \
|
||||
--ftps-certs-file /path/to/cert.pem \
|
||||
--ftps-key-file /path/to/key.pem \
|
||||
--ftps-passive-ports "40000-41000" \
|
||||
--sftp-enable \
|
||||
--sftp-address 0.0.0.0:22 \
|
||||
--sftp-host-key /path/to/host_key \
|
||||
--sftp-authorized-keys /path/to/authorized_keys \
|
||||
/data
|
||||
# Start RustFS with FTPS enabled
|
||||
export RUSTFS_FTPS_ENABLE=true
|
||||
export RUSTFS_FTPS_CERTS_FILE=/path/to/cert.pem
|
||||
export RUSTFS_FTPS_KEY_FILE=/path/to/key.pem
|
||||
rustfs --address 0.0.0.0:9000 --access-key rustfsadmin --secret-key rustfsadmin /data
|
||||
|
||||
# Start RustFS with SFTP enabled
|
||||
export RUSTFS_SFTP_ENABLE=true
|
||||
export RUSTFS_SFTP_HOST_KEY=/path/to/host_key
|
||||
export RUSTFS_SFTP_AUTHORIZED_KEYS=/path/to/authorized_keys
|
||||
rustfs --address 0.0.0.0:9000 --access-key rustfsadmin --secret-key rustfsadmin /data
|
||||
```
|
||||
|
||||
## Protocol Details
|
||||
|
||||
### FTPS
|
||||
- **Port**: 21
|
||||
- **Port**: 8021 (default)
|
||||
- **Protocol**: FTP over TLS (FTPS)
|
||||
- **Authentication**: Access Key / Secret Key (same as S3)
|
||||
- **Features**:
|
||||
@@ -44,7 +40,7 @@ rustfs \
|
||||
- No multipart upload
|
||||
|
||||
### SFTP
|
||||
- **Port**: 22
|
||||
- **Port**: 8022 (default)
|
||||
- **Protocol**: SSH File Transfer Protocol
|
||||
- **Authentication**:
|
||||
- Password (Access Key / Secret Key)
|
||||
@@ -133,23 +129,23 @@ ssh-keygen -l -f /path/to/host_key
|
||||
|
||||
### FTPS Configuration
|
||||
|
||||
| Option | Environment Variable | Description | Default |
|
||||
|--------|---------------------|-------------|---------|
|
||||
| `--ftps-enable` | `RUSTFS_FTPS_ENABLE` | Enable FTPS server | `false` |
|
||||
| `--ftps-address` | `RUSTFS_FTPS_ADDRESS` | FTPS bind address | `0.0.0.0:21` |
|
||||
| `--ftps-certs-file` | `RUSTFS_FTPS_CERTS_FILE` | TLS certificate file | - |
|
||||
| `--ftps-key-file` | `RUSTFS_FTPS_KEY_FILE` | TLS private key file | - |
|
||||
| `--ftps-passive-ports` | `RUSTFS_FTPS_PASSIVE_PORTS` | Passive port range | - |
|
||||
| `--ftps-external-ip` | `RUSTFS_FTPS_EXTERNAL_IP` | External IP for NAT | - |
|
||||
| Environment Variable | Description | Default |
|
||||
|---------------------|-------------|---------|
|
||||
| `RUSTFS_FTPS_ENABLE` | Enable FTPS server | `false` |
|
||||
| `RUSTFS_FTPS_ADDRESS` | FTPS bind address | `0.0.0.0:8021` |
|
||||
| `RUSTFS_FTPS_CERTS_FILE` | TLS certificate file | - |
|
||||
| `RUSTFS_FTPS_KEY_FILE` | TLS private key file | - |
|
||||
| `RUSTFS_FTPS_PASSIVE_PORTS` | Passive port range | - |
|
||||
| `RUSTFS_FTPS_EXTERNAL_IP` | External IP for NAT | - |
|
||||
|
||||
### SFTP Configuration
|
||||
|
||||
| Option | Environment Variable | Description | Default |
|
||||
|--------|---------------------|-------------|---------|
|
||||
| `--sftp-enable` | `RUSTFS_SFTP_ENABLE` | Enable SFTP server | `false` |
|
||||
| `--sftp-address` | `RUSTFS_SFTP_ADDRESS` | SFTP bind address | `0.0.0.0:22` |
|
||||
| `--sftp-host-key` | `RUSTFS_SFTP_HOST_KEY` | SSH host key file | - |
|
||||
| `--sftp-authorized-keys` | `RUSTFS_SFTP_AUTHORIZED_KEYS` | Authorized keys file | - |
|
||||
| Environment Variable | Description | Default |
|
||||
|---------------------|-------------|---------|
|
||||
| `RUSTFS_SFTP_ENABLE` | Enable SFTP server | `false` |
|
||||
| `RUSTFS_SFTP_ADDRESS` | SFTP bind address | `0.0.0.0:8022` |
|
||||
| `RUSTFS_SFTP_HOST_KEY` | SSH host key file | - |
|
||||
| `RUSTFS_SFTP_AUTHORIZED_KEYS` | Authorized keys file | - |
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ use crate::protocols::session::context::Protocol;
|
||||
pub fn is_operation_supported(protocol: Protocol, action: &S3Action) -> bool {
|
||||
match protocol {
|
||||
Protocol::Ftps => match action {
|
||||
// Bucket operations: FTPS cannot create buckets via protocol commands
|
||||
S3Action::CreateBucket => false,
|
||||
S3Action::DeleteBucket => false,
|
||||
// Bucket operations: FTPS has no native bucket commands, but gateway allows create/delete
|
||||
S3Action::CreateBucket => true,
|
||||
S3Action::DeleteBucket => true,
|
||||
|
||||
// Object operations: All file operations supported
|
||||
S3Action::GetObject => true, // RETR command
|
||||
|
||||
@@ -69,7 +69,8 @@ impl SftpServer {
|
||||
russh::keys::load_secret_key(path, None)?
|
||||
} else {
|
||||
warn!("No host key provided, generating random key (not recommended for production).");
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
use russh::keys::signature::rand_core::OsRng;
|
||||
let mut rng = OsRng;
|
||||
PrivateKey::random(&mut rng, Algorithm::Ed25519)?
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user