use std::collections::HashMap;
use crate::common::audit::Auditor;
use manta_backend_dispatcher::types::K8sDetails;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum BackendTechnology {
Csm,
Ochami,
}
impl BackendTechnology {
pub fn as_str(&self) -> &'static str {
match self {
Self::Csm => "csm",
Self::Ochami => "ochami",
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Site {
pub backend: BackendTechnology,
pub socks5_proxy: Option<String>,
pub shasta_base_url: String,
pub k8s: Option<K8sDetails>,
pub root_ca_cert_file: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CliConfiguration {
pub log: String,
pub audit_file: String,
pub site: String,
pub parent_hsm_group: String,
pub manta_server_url: String,
pub socks5_proxy: Option<String>,
pub auditor: Option<Auditor>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ServerSettings {
pub listen_address: String,
pub port: u16,
pub cert: Option<String>,
pub key: Option<String>,
pub console_inactivity_timeout_secs: u64,
pub auth_rate_limit_per_minute: Option<u32>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ServerConfiguration {
pub log: String,
pub audit_file: String,
pub server: ServerSettings,
pub sites: HashMap<String, Site>,
pub auditor: Option<Auditor>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn site_deserialize_missing_backend_fails() {
let bad_toml = r#"
shasta_base_url = "https://api.example.com"
root_ca_cert_file = "cert.pem"
# missing backend
"#;
let result = toml::from_str::<Site>(bad_toml);
assert!(result.is_err());
}
#[test]
fn backend_technology_as_str() {
assert_eq!(BackendTechnology::Csm.as_str(), "csm");
assert_eq!(BackendTechnology::Ochami.as_str(), "ochami");
}
#[test]
fn backend_technology_roundtrip_toml() {
#[derive(Serialize, Deserialize)]
struct Wrapper {
backend: BackendTechnology,
}
let w = Wrapper {
backend: BackendTechnology::Csm,
};
let s = toml::to_string(&w).unwrap();
assert!(s.contains("\"csm\"") || s.contains("csm"));
let parsed: Wrapper = toml::from_str(&s).unwrap();
assert_eq!(parsed.backend, BackendTechnology::Csm);
}
fn make_minimal_site() -> Site {
Site {
backend: BackendTechnology::Csm,
socks5_proxy: None,
shasta_base_url: "https://api.example.com".to_string(),
k8s: None,
root_ca_cert_file: "cert.pem".to_string(),
}
}
#[test]
fn cli_configuration_roundtrip_toml_minimal() {
let cfg = CliConfiguration {
log: "info".to_string(),
audit_file: "/tmp/cli-audit.log".to_string(),
site: "alps".to_string(),
parent_hsm_group: "nodes_free".to_string(),
manta_server_url: "https://manta-server.cscs.ch:8443".to_string(),
socks5_proxy: Some("socks5h://127.0.0.1:1080".to_string()),
auditor: None,
};
let toml_str = toml::to_string(&cfg).unwrap();
let parsed: CliConfiguration = toml::from_str(&toml_str).unwrap();
assert_eq!(parsed.site, "alps");
assert_eq!(parsed.parent_hsm_group, "nodes_free");
assert_eq!(parsed.manta_server_url, "https://manta-server.cscs.ch:8443");
assert_eq!(
parsed.socks5_proxy.as_deref(),
Some("socks5h://127.0.0.1:1080")
);
}
#[test]
fn cli_configuration_socks5_proxy_optional() {
let toml_str = r#"
log = "info"
audit_file = "/tmp/cli-audit.log"
site = "alps"
parent_hsm_group = ""
manta_server_url = "https://manta-server.cscs.ch:8443"
"#;
let parsed: CliConfiguration = toml::from_str(toml_str).unwrap();
assert!(parsed.socks5_proxy.is_none());
}
#[test]
fn cli_configuration_missing_manta_server_url_fails() {
let bad_toml = r#"
log = "info"
audit_file = "/tmp/cli-audit.log"
site = "alps"
parent_hsm_group = ""
# missing manta_server_url
"#;
let result = toml::from_str::<CliConfiguration>(bad_toml);
assert!(result.is_err());
}
#[test]
fn server_configuration_roundtrip_toml_minimal() {
let mut sites = HashMap::new();
sites.insert("alps".to_string(), make_minimal_site());
let cfg = ServerConfiguration {
log: "info".to_string(),
audit_file: "/var/log/manta/server-audit.log".to_string(),
server: ServerSettings {
listen_address: "0.0.0.0".to_string(),
port: 8443,
cert: Some("/etc/manta/tls/server.crt".to_string()),
key: Some("/etc/manta/tls/server.key".to_string()),
console_inactivity_timeout_secs: 1800,
auth_rate_limit_per_minute: Some(60),
},
sites,
auditor: None,
};
let toml_str = toml::to_string(&cfg).unwrap();
let parsed: ServerConfiguration = toml::from_str(&toml_str).unwrap();
assert_eq!(parsed.server.port, 8443);
assert_eq!(parsed.server.listen_address, "0.0.0.0");
assert_eq!(parsed.server.console_inactivity_timeout_secs, 1800);
assert_eq!(
parsed.server.cert.as_deref(),
Some("/etc/manta/tls/server.crt")
);
}
#[test]
fn server_configuration_deserialize_missing_server_section_fails() {
let bad_toml = r#"
log = "info"
audit_file = "/tmp/server.log"
[sites]
"#;
let result = toml::from_str::<ServerConfiguration>(bad_toml);
assert!(result.is_err());
}
#[test]
fn server_settings_optional_tls_paths() {
let toml_str = r#"
listen_address = "0.0.0.0"
port = 8443
console_inactivity_timeout_secs = 1800
"#;
let parsed: ServerSettings = toml::from_str(toml_str).unwrap();
assert!(parsed.cert.is_none());
assert!(parsed.key.is_none());
}
}