manta_shared/common/config/
types.rs1use std::collections::HashMap;
9
10use crate::common::audit::Auditor;
11
12use manta_backend_dispatcher::types::K8sDetails;
13use serde::{Deserialize, Serialize};
14
15#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
17#[serde(rename_all = "lowercase")]
18pub enum BackendTechnology {
19 Csm,
21 Ochami,
23}
24
25impl BackendTechnology {
26 pub fn as_str(&self) -> &'static str {
28 match self {
29 Self::Csm => "csm",
30 Self::Ochami => "ochami",
31 }
32 }
33}
34
35#[derive(Serialize, Deserialize, Debug)]
36pub struct Site {
44 pub backend: BackendTechnology,
46 pub socks5_proxy: Option<String>,
49 pub shasta_base_url: String,
51 pub k8s: Option<K8sDetails>,
54 pub root_ca_cert_file: String,
57}
58
59#[derive(Serialize, Deserialize, Debug)]
65pub struct CliConfiguration {
66 pub log: String,
69 pub audit_file: String,
71 pub site: String,
76 pub parent_hsm_group: String,
79 pub manta_server_url: String,
83 pub socks5_proxy: Option<String>,
86 pub auditor: Option<Auditor>,
89}
90
91#[derive(Serialize, Deserialize, Debug)]
94pub struct ServerSettings {
95 pub listen_address: String,
97 pub port: u16,
99 pub cert: Option<String>,
101 pub key: Option<String>,
103 pub console_inactivity_timeout_secs: u64,
106 pub auth_rate_limit_per_minute: Option<u32>,
110}
111
112#[derive(Serialize, Deserialize, Debug)]
117pub struct ServerConfiguration {
118 pub log: String,
120 pub audit_file: String,
122 pub server: ServerSettings,
124 pub sites: HashMap<String, Site>,
127 pub auditor: Option<Auditor>,
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn site_deserialize_missing_backend_fails() {
138 let bad_toml = r#"
139 shasta_base_url = "https://api.example.com"
140 root_ca_cert_file = "cert.pem"
141 # missing backend
142 "#;
143 let result = toml::from_str::<Site>(bad_toml);
144 assert!(result.is_err());
145 }
146
147 #[test]
148 fn backend_technology_as_str() {
149 assert_eq!(BackendTechnology::Csm.as_str(), "csm");
150 assert_eq!(BackendTechnology::Ochami.as_str(), "ochami");
151 }
152
153 #[test]
154 fn backend_technology_roundtrip_toml() {
155 #[derive(Serialize, Deserialize)]
157 struct Wrapper {
158 backend: BackendTechnology,
159 }
160 let w = Wrapper {
161 backend: BackendTechnology::Csm,
162 };
163 let s = toml::to_string(&w).unwrap();
164 assert!(s.contains("\"csm\"") || s.contains("csm"));
165 let parsed: Wrapper = toml::from_str(&s).unwrap();
166 assert_eq!(parsed.backend, BackendTechnology::Csm);
167 }
168
169 fn make_minimal_site() -> Site {
170 Site {
171 backend: BackendTechnology::Csm,
172 socks5_proxy: None,
173 shasta_base_url: "https://api.example.com".to_string(),
174 k8s: None,
175 root_ca_cert_file: "cert.pem".to_string(),
176 }
177 }
178
179 #[test]
180 fn cli_configuration_roundtrip_toml_minimal() {
181 let cfg = CliConfiguration {
182 log: "info".to_string(),
183 audit_file: "/tmp/cli-audit.log".to_string(),
184 site: "alps".to_string(),
185 parent_hsm_group: "nodes_free".to_string(),
186 manta_server_url: "https://manta-server.cscs.ch:8443".to_string(),
187 socks5_proxy: Some("socks5h://127.0.0.1:1080".to_string()),
188 auditor: None,
189 };
190 let toml_str = toml::to_string(&cfg).unwrap();
191 let parsed: CliConfiguration = toml::from_str(&toml_str).unwrap();
192 assert_eq!(parsed.site, "alps");
193 assert_eq!(parsed.parent_hsm_group, "nodes_free");
194 assert_eq!(parsed.manta_server_url, "https://manta-server.cscs.ch:8443");
195 assert_eq!(
196 parsed.socks5_proxy.as_deref(),
197 Some("socks5h://127.0.0.1:1080")
198 );
199 }
200
201 #[test]
202 fn cli_configuration_socks5_proxy_optional() {
203 let toml_str = r#"
204 log = "info"
205 audit_file = "/tmp/cli-audit.log"
206 site = "alps"
207 parent_hsm_group = ""
208 manta_server_url = "https://manta-server.cscs.ch:8443"
209 "#;
210 let parsed: CliConfiguration = toml::from_str(toml_str).unwrap();
211 assert!(parsed.socks5_proxy.is_none());
212 }
213
214 #[test]
215 fn cli_configuration_missing_manta_server_url_fails() {
216 let bad_toml = r#"
217 log = "info"
218 audit_file = "/tmp/cli-audit.log"
219 site = "alps"
220 parent_hsm_group = ""
221 # missing manta_server_url
222 "#;
223 let result = toml::from_str::<CliConfiguration>(bad_toml);
224 assert!(result.is_err());
225 }
226
227 #[test]
228 fn server_configuration_roundtrip_toml_minimal() {
229 let mut sites = HashMap::new();
230 sites.insert("alps".to_string(), make_minimal_site());
231 let cfg = ServerConfiguration {
232 log: "info".to_string(),
233 audit_file: "/var/log/manta/server-audit.log".to_string(),
234 server: ServerSettings {
235 listen_address: "0.0.0.0".to_string(),
236 port: 8443,
237 cert: Some("/etc/manta/tls/server.crt".to_string()),
238 key: Some("/etc/manta/tls/server.key".to_string()),
239 console_inactivity_timeout_secs: 1800,
240 auth_rate_limit_per_minute: Some(60),
241 },
242 sites,
243 auditor: None,
244 };
245 let toml_str = toml::to_string(&cfg).unwrap();
246 let parsed: ServerConfiguration = toml::from_str(&toml_str).unwrap();
247 assert_eq!(parsed.server.port, 8443);
248 assert_eq!(parsed.server.listen_address, "0.0.0.0");
249 assert_eq!(parsed.server.console_inactivity_timeout_secs, 1800);
250 assert_eq!(
251 parsed.server.cert.as_deref(),
252 Some("/etc/manta/tls/server.crt")
253 );
254 }
255
256 #[test]
257 fn server_configuration_deserialize_missing_server_section_fails() {
258 let bad_toml = r#"
259 log = "info"
260 audit_file = "/tmp/server.log"
261 [sites]
262 "#;
263 let result = toml::from_str::<ServerConfiguration>(bad_toml);
264 assert!(result.is_err());
265 }
266
267 #[test]
268 fn server_settings_optional_tls_paths() {
269 let toml_str = r#"
272 listen_address = "0.0.0.0"
273 port = 8443
274 console_inactivity_timeout_secs = 1800
275 "#;
276 let parsed: ServerSettings = toml::from_str(toml_str).unwrap();
277 assert!(parsed.cert.is_none());
278 assert!(parsed.key.is_none());
279 }
280}