greentic_setup/admin/
tls.rs1use std::path::PathBuf;
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
27pub struct AdminTlsConfig {
28 pub server_cert: PathBuf,
30 pub server_key: PathBuf,
32 pub client_ca: PathBuf,
34 #[serde(default)]
38 pub allowed_clients: Vec<String>,
39 #[serde(default = "default_admin_port")]
41 pub port: u16,
42}
43
44fn default_admin_port() -> u16 {
45 8443
46}
47
48impl Default for AdminTlsConfig {
49 fn default() -> Self {
50 Self {
51 server_cert: PathBuf::from("admin/server.crt"),
52 server_key: PathBuf::from("admin/server.key"),
53 client_ca: PathBuf::from("admin/ca.crt"),
54 allowed_clients: Vec::new(),
55 port: default_admin_port(),
56 }
57 }
58}
59
60impl AdminTlsConfig {
61 pub fn validate(&self) -> anyhow::Result<()> {
63 for (label, path) in [
64 ("server_cert", &self.server_cert),
65 ("server_key", &self.server_key),
66 ("client_ca", &self.client_ca),
67 ] {
68 if !path.exists() {
69 return Err(anyhow::anyhow!(
70 "admin TLS {label} not found: {}",
71 path.display()
72 ));
73 }
74 }
75 Ok(())
76 }
77
78 pub fn is_client_allowed(&self, cn: &str) -> bool {
83 if self.allowed_clients.is_empty() {
84 return true;
85 }
86 self.allowed_clients
87 .iter()
88 .any(|pattern| pattern == cn || pattern == "*")
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn default_port_is_8443() {
98 let config = AdminTlsConfig::default();
99 assert_eq!(config.port, 8443);
100 }
101
102 #[test]
103 fn empty_allowed_clients_allows_anyone() {
104 let config = AdminTlsConfig::default();
105 assert!(config.is_client_allowed("anything"));
106 }
107
108 #[test]
109 fn rejects_unlisted_client() {
110 let config = AdminTlsConfig {
111 allowed_clients: vec!["CN=admin".into()],
112 ..Default::default()
113 };
114 assert!(config.is_client_allowed("CN=admin"));
115 assert!(!config.is_client_allowed("CN=hacker"));
116 }
117
118 #[test]
119 fn wildcard_allows_all() {
120 let config = AdminTlsConfig {
121 allowed_clients: vec!["*".into()],
122 ..Default::default()
123 };
124 assert!(config.is_client_allowed("anyone"));
125 }
126
127 #[test]
128 fn validate_fails_for_missing_certs() {
129 let config = AdminTlsConfig {
130 server_cert: "/nonexistent/server.crt".into(),
131 server_key: "/nonexistent/server.key".into(),
132 client_ca: "/nonexistent/ca.crt".into(),
133 ..Default::default()
134 };
135 assert!(config.validate().is_err());
136 }
137}