Add SMB Configuration Templates (Phase 6)
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

This commit is contained in:
Warren
2026-06-22 05:22:14 +08:00
parent 054bf55490
commit 52c38b1919
2 changed files with 340 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ pub mod s3_config;
pub mod s3_policy;
pub mod s3_xml;
pub mod scan;
pub mod smb_config;
pub mod server;
pub mod ssh_server;
pub mod sync;

View File

@@ -0,0 +1,339 @@
//! SMB Server Configuration Templates
//! Provides preset configurations for common deployment scenarios
use std::path::PathBuf;
/// SMB Server Configuration
#[derive(Clone, Debug)]
pub struct SmbConfig {
pub port: u16,
pub root: PathBuf,
pub share_name: String,
pub read_only: bool,
pub users: Vec<(String, String)>,
pub backend: SmbBackend,
pub ldap: Option<LdapConfig>,
pub cache: CacheConfig,
pub encryption: EncryptionConfig,
}
#[derive(Clone, Debug)]
pub enum SmbBackend {
LocalFs,
S3 {
endpoint: String,
bucket: String,
access_key: String,
secret_key: String,
region: String,
},
}
#[derive(Clone, Debug)]
pub struct LdapConfig {
pub url: String,
pub base_dn: String,
pub bind_dn: String,
pub bind_password: String,
pub user_search_base: String,
pub group_search_base: String,
pub user_id_attr: String,
pub user_filter: String,
pub group_filter: String,
pub home_dir_attr: String,
pub home_dir_prefix: String,
pub user_groups_attr: String,
}
#[derive(Clone, Debug)]
pub struct CacheConfig {
pub read_cache_size_mb: usize,
pub write_cache_size_mb: usize,
pub cache_ttl_secs: u64,
}
#[derive(Clone, Debug)]
pub enum EncryptionConfig {
Disabled,
Aes128Ctr,
Aes256Gcm,
}
impl Default for SmbConfig {
fn default() -> Self {
Self {
port: 4445,
root: PathBuf::from("/data/smb"),
share_name: "share".to_string(),
read_only: false,
users: vec![("demo".to_string(), "demo123".to_string())],
backend: SmbBackend::LocalFs,
ldap: None,
cache: CacheConfig::default(),
encryption: EncryptionConfig::Aes128Ctr,
}
}
}
impl Default for LdapConfig {
fn default() -> Self {
Self {
url: "ldap://localhost:389".to_string(),
base_dn: "dc=example,dc=com".to_string(),
bind_dn: "cn=admin,dc=example,dc=com".to_string(),
bind_password: "".to_string(),
user_search_base: "ou=users,dc=example,dc=com".to_string(),
group_search_base: "ou=groups,dc=example,dc=com".to_string(),
user_id_attr: "uid".to_string(),
user_filter: "(objectClass=person)".to_string(),
group_filter: "(objectClass=group)".to_string(),
home_dir_attr: "homeDirectory".to_string(),
home_dir_prefix: "/home".to_string(),
user_groups_attr: "memberOf".to_string(),
}
}
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
read_cache_size_mb: 64,
write_cache_size_mb: 32,
cache_ttl_secs: 300,
}
}
}
impl SmbConfig {
/// Generate TOML configuration template
pub fn generate_template() -> String {
let config = Self::default();
format!(
"# === SMB Server Configuration ===
# MarkBase SMB2/3 File Server
[smb]
# === Network Settings ===
port = {} # SMB server port (default: 4445)
share_name = \"{}\" # Share name visible to clients
read_only = {} # Read-only mode (default: false)
# === Storage Backend ===
# Options: localfs, s3
backend = \"localfs\" # Default: local filesystem
root = \"{}\" # Local filesystem root path
# === User Authentication ===
# Format: [[smb.users]]
# name = \"username\"
# password = \"password\" (bcrypt hashed in production)
[[smb.users]]
name = \"{}\"
password = \"{}\" # ⚠️ Use bcrypt hash in production
# === LDAP Integration (Optional) ===
# Uncomment to enable LDAP authentication
# [smb.ldap]
# url = \"ldap://localhost:389\" # LDAP server URL
# base_dn = \"dc=example,dc=com\" # Base DN
# bind_dn = \"cn=admin,dc=example,dc=com\" # Bind DN for search
# bind_password = \"admin_password\" # Bind password
# user_search_base = \"ou=users,dc=example,dc=com\"
# group_search_base = \"ou=groups,dc=example,dc=com\"
# user_id_attr = \"uid\" # User ID attribute
# user_filter = \"(objectClass=person)\" # User object filter
# group_filter = \"(objectClass=group)\" # Group object filter
# home_dir_attr = \"homeDirectory\" # Home directory attribute
# home_dir_prefix = \"/home\" # Home directory prefix
# user_groups_attr = \"memberOf\" # Group membership attribute
# === Performance Settings ===
[smb.cache]
read_cache_size_mb = {} # Read cache size (default: 64MB)
write_cache_size_mb = {} # Write cache size (default: 32MB)
cache_ttl_secs = {} # Cache TTL (default: 300s)
# === Security Settings ===
[smb.encryption]
# Options: disabled, aes128-ctr, aes256-gcm
mode = \"aes128-ctr\" # SMB3 encryption mode (default: AES-128-CTR)
# === S3 Backend (Optional) ===
# Uncomment to use S3 backend instead of local filesystem
# [smb.s3]
# endpoint = \"https://s3.amazonaws.com\"
# bucket = \"my-bucket\"
# access_key = \"AKIAIOSFODNN7EXAMPLE\"
# secret_key = \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\"
# region = \"us-east-1\"
",
config.port,
config.share_name,
config.read_only,
config.root.display(),
config.users[0].0,
config.users[0].1,
config.cache.read_cache_size_mb,
config.cache.write_cache_size_mb,
config.cache.cache_ttl_secs,
)
}
/// Preset: Local File Server (simple deployment)
pub fn preset_local_file_server() -> Self {
Self {
port: 4445,
root: PathBuf::from("/data/smb"),
share_name: "files".to_string(),
read_only: false,
users: vec![
("alice".to_string(), "alice123".to_string()),
("bob".to_string(), "bob123".to_string()),
],
backend: SmbBackend::LocalFs,
ldap: None,
cache: CacheConfig {
read_cache_size_mb: 64,
write_cache_size_mb: 32,
cache_ttl_secs: 300,
},
encryption: EncryptionConfig::Aes128Ctr,
}
}
/// Preset: S3 Backend (cloud storage)
pub fn preset_s3_backend() -> Self {
Self {
port: 4445,
root: PathBuf::from("demo/"),
share_name: "s3share".to_string(),
read_only: false,
users: vec![("demo".to_string(), "demo123".to_string())],
backend: SmbBackend::S3 {
endpoint: "https://s3.amazonaws.com".to_string(),
bucket: "my-bucket".to_string(),
access_key: "AKIAIOSFODNN7EXAMPLE".to_string(),
secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY".to_string(),
region: "us-east-1".to_string(),
},
ldap: None,
cache: CacheConfig {
read_cache_size_mb: 128,
write_cache_size_mb: 64,
cache_ttl_secs: 600,
},
encryption: EncryptionConfig::Aes256Gcm,
}
}
/// Preset: LDAP Enterprise (Active Directory integration)
pub fn preset_ldap_enterprise() -> Self {
Self {
port: 4445,
root: PathBuf::from("/data/smb"),
share_name: "enterprise".to_string(),
read_only: false,
users: vec![], // LDAP handles authentication
backend: SmbBackend::LocalFs,
ldap: Some(LdapConfig {
url: "ldap://ad.example.com:389".to_string(),
base_dn: "dc=example,dc=com".to_string(),
bind_dn: "cn=admin,cn=users,dc=example,dc=com".to_string(),
bind_password: "admin_password".to_string(),
user_search_base: "cn=users,dc=example,dc=com".to_string(),
group_search_base: "cn=groups,dc=example,dc=com".to_string(),
user_id_attr: "sAMAccountName".to_string(),
user_filter: "(objectClass=user)".to_string(),
group_filter: "(objectClass=group)".to_string(),
home_dir_attr: "homeDirectory".to_string(),
home_dir_prefix: "/home".to_string(),
user_groups_attr: "memberOf".to_string(),
}),
cache: CacheConfig {
read_cache_size_mb: 128,
write_cache_size_mb: 64,
cache_ttl_secs: 300,
},
encryption: EncryptionConfig::Aes256Gcm,
}
}
/// Preset: Read-Only Archive (public documents)
pub fn preset_read_only_archive() -> Self {
Self {
port: 4445,
root: PathBuf::from("/data/archive"),
share_name: "archive".to_string(),
read_only: true,
users: vec![("public".to_string(), "".to_string())],
backend: SmbBackend::LocalFs,
ldap: None,
cache: CacheConfig {
read_cache_size_mb: 256,
write_cache_size_mb: 0,
cache_ttl_secs: 3600,
},
encryption: EncryptionConfig::Disabled,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = SmbConfig::default();
assert_eq!(config.port, 4445);
assert_eq!(config.share_name, "share");
assert!(!config.read_only);
assert_eq!(config.users.len(), 1);
}
#[test]
fn test_generate_template() {
let template = SmbConfig::generate_template();
assert!(template.contains("port = 4445"));
assert!(template.contains("share_name = \"share\""));
assert!(template.contains("backend = \"localfs\""));
assert!(template.contains("[smb.users]"));
assert!(template.contains("[smb.cache]"));
assert!(template.contains("[smb.encryption]"));
}
#[test]
fn test_preset_local_file_server() {
let config = SmbConfig::preset_local_file_server();
assert_eq!(config.port, 4445);
assert_eq!(config.share_name, "files");
assert_eq!(config.users.len(), 2);
assert!(config.ldap.is_none());
}
#[test]
fn test_preset_s3_backend() {
let config = SmbConfig::preset_s3_backend();
assert_eq!(config.share_name, "s3share");
assert!(matches!(config.backend, SmbBackend::S3 { .. }));
assert!(matches!(config.encryption, EncryptionConfig::Aes256Gcm));
}
#[test]
fn test_preset_ldap_enterprise() {
let config = SmbConfig::preset_ldap_enterprise();
assert_eq!(config.share_name, "enterprise");
assert!(config.ldap.is_some());
assert_eq!(config.users.len(), 0);
}
#[test]
fn test_preset_read_only_archive() {
let config = SmbConfig::preset_read_only_archive();
assert!(config.read_only);
assert_eq!(config.share_name, "archive");
assert!(matches!(config.encryption, EncryptionConfig::Disabled));
}
}