cdk_mintd/env_vars/
management_rpc.rs1use std::env;
4
5use crate::config::MintManagementRpc;
6
7pub const ENV_MINT_MANAGEMENT_ENABLED: &str = "CDK_MINTD_MANAGEMENT_ENABLED";
9pub const ENV_MINT_MANAGEMENT_ENABLED_LEGACY: &str = "CDK_MINTD_MINT_MANAGEMENT_ENABLED";
10pub const ENV_MINT_MANAGEMENT_ADDRESS: &str = "CDK_MINTD_MANAGEMENT_ADDRESS";
11pub const ENV_MINT_MANAGEMENT_PORT: &str = "CDK_MINTD_MANAGEMENT_PORT";
12pub const ENV_MINT_MANAGEMENT_TLS_DIR: &str = "CDK_MINTD_MANAGEMENT_TLS_DIR";
13pub const ENV_MINT_MANAGEMENT_ALLOW_INSECURE: &str = "CDK_MINTD_MANAGEMENT_ALLOW_INSECURE";
14pub const ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE: &str =
15 "CDK_MINTD_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE";
16
17impl MintManagementRpc {
18 pub fn from_env(mut self) -> Self {
19 if let Some(enabled) = super::bool_override(ENV_MINT_MANAGEMENT_ENABLED)
20 .or_else(|| super::bool_override(ENV_MINT_MANAGEMENT_ENABLED_LEGACY))
21 {
22 self.enabled = enabled;
23 }
24
25 if let Ok(address) = env::var(ENV_MINT_MANAGEMENT_ADDRESS) {
26 self.address = Some(address);
27 }
28
29 if let Ok(port) = env::var(ENV_MINT_MANAGEMENT_PORT) {
30 if let Ok(port) = port.parse::<u16>() {
31 self.port = Some(port);
32 }
33 }
34
35 if let Ok(tls_dir) = env::var(ENV_MINT_MANAGEMENT_TLS_DIR) {
36 self.tls_dir = Some(tls_dir.into());
37 }
38
39 if let Some(allow_insecure) = super::bool_override(ENV_MINT_MANAGEMENT_ALLOW_INSECURE) {
40 self.allow_insecure = allow_insecure;
41 }
42
43 if let Ok(allow_override) = env::var(ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE)
44 {
45 self.allow_mint_quote_payment_override = allow_override.parse().unwrap_or(false);
46 }
47
48 self
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use std::collections::BTreeSet;
55 use std::path::PathBuf;
56
57 use super::*;
58
59 fn env_lock() -> std::sync::MutexGuard<'static, ()> {
60 crate::test_utils::env_lock()
61 }
62
63 fn clear_env_vars() {
64 env::remove_var(ENV_MINT_MANAGEMENT_ENABLED);
65 env::remove_var(ENV_MINT_MANAGEMENT_ENABLED_LEGACY);
66 env::remove_var(ENV_MINT_MANAGEMENT_ADDRESS);
67 env::remove_var(ENV_MINT_MANAGEMENT_PORT);
68 env::remove_var(ENV_MINT_MANAGEMENT_TLS_DIR);
69 env::remove_var(ENV_MINT_MANAGEMENT_ALLOW_INSECURE);
70 env::remove_var(ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE);
71 }
72
73 #[test]
74 fn management_env_var_names_share_consistent_prefix() {
75 let names = [
76 ENV_MINT_MANAGEMENT_ENABLED,
77 ENV_MINT_MANAGEMENT_ADDRESS,
78 ENV_MINT_MANAGEMENT_PORT,
79 ENV_MINT_MANAGEMENT_TLS_DIR,
80 ENV_MINT_MANAGEMENT_ALLOW_INSECURE,
81 ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE,
82 ];
83
84 let prefixes: BTreeSet<&str> = names
85 .iter()
86 .map(|name| {
87 let idx = name
88 .find("MANAGEMENT")
89 .expect("management env var name should contain MANAGEMENT");
90 &name[..idx]
91 })
92 .collect();
93
94 assert_eq!(
95 prefixes.len(),
96 1,
97 "inconsistent management RPC env var prefixes: {prefixes:?}"
98 );
99 }
100
101 #[test]
102 fn management_rpc_from_env_reads_canonical_env_vars() {
103 let _guard = env_lock();
104 clear_env_vars();
105
106 env::set_var(ENV_MINT_MANAGEMENT_ENABLED, "true");
107 env::set_var(ENV_MINT_MANAGEMENT_ADDRESS, "0.0.0.0");
108 env::set_var(ENV_MINT_MANAGEMENT_PORT, "10000");
109 env::set_var(ENV_MINT_MANAGEMENT_TLS_DIR, "/var/lib/cdk/tls");
110 env::set_var(ENV_MINT_MANAGEMENT_ALLOW_INSECURE, "true");
111 env::set_var(
112 ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE,
113 "true",
114 );
115
116 let management_rpc = MintManagementRpc::default().from_env();
117
118 assert!(management_rpc.enabled);
119 assert_eq!(management_rpc.address.as_deref(), Some("0.0.0.0"));
120 assert_eq!(management_rpc.port, Some(10000));
121 assert_eq!(
122 management_rpc.tls_dir,
123 Some(PathBuf::from("/var/lib/cdk/tls"))
124 );
125 assert!(management_rpc.allow_insecure);
126 assert!(management_rpc.allow_mint_quote_payment_override);
127
128 clear_env_vars();
129 }
130
131 #[test]
132 fn management_rpc_from_env_still_reads_legacy_enabled_env_var() {
133 let _guard = env_lock();
134 clear_env_vars();
135
136 env::set_var(ENV_MINT_MANAGEMENT_ENABLED_LEGACY, "true");
137
138 let management_rpc = MintManagementRpc::default().from_env();
139
140 assert!(management_rpc.enabled);
141
142 clear_env_vars();
143 }
144
145 #[test]
146 fn management_rpc_from_env_allows_no_tls_configuration() {
147 let _guard = env_lock();
148 clear_env_vars();
149
150 env::set_var(ENV_MINT_MANAGEMENT_ENABLED, "true");
151
152 let management_rpc = MintManagementRpc::default().from_env();
153
154 assert!(management_rpc.enabled);
155 assert_eq!(management_rpc.tls_dir, None);
156 assert!(!management_rpc.allow_insecure);
157 assert!(!management_rpc.allow_mint_quote_payment_override);
158
159 clear_env_vars();
160 }
161
162 #[test]
163 fn management_rpc_security_overrides_fail_closed() {
164 let _guard = env_lock();
165 clear_env_vars();
166 for name in [
167 ENV_MINT_MANAGEMENT_ENABLED,
168 ENV_MINT_MANAGEMENT_ENABLED_LEGACY,
169 ENV_MINT_MANAGEMENT_ALLOW_INSECURE,
170 ] {
171 for value in ["false", "not-a-boolean"] {
172 env::set_var(name, value);
173 let config = MintManagementRpc {
174 enabled: true,
175 allow_insecure: true,
176 ..Default::default()
177 }
178 .from_env();
179 let actual = if name == ENV_MINT_MANAGEMENT_ALLOW_INSECURE {
180 config.allow_insecure
181 } else {
182 config.enabled
183 };
184 assert!(!actual, "{name}={value}");
185 }
186 env::remove_var(name);
187 }
188 let configured = MintManagementRpc {
189 enabled: true,
190 allow_insecure: true,
191 ..Default::default()
192 }
193 .from_env();
194 assert!(configured.enabled);
195 assert!(configured.allow_insecure);
196
197 env::set_var(ENV_MINT_MANAGEMENT_ENABLED_LEGACY, "true");
198 for value in ["false", "invalid"] {
199 env::set_var(ENV_MINT_MANAGEMENT_ENABLED, value);
200 assert!(!MintManagementRpc::default().from_env().enabled);
201 }
202 clear_env_vars();
203 }
204
205 #[cfg(unix)]
206 #[test]
207 fn management_rpc_non_unicode_overrides_fail_closed() {
208 use std::os::unix::ffi::OsStringExt;
209
210 let _guard = env_lock();
211 clear_env_vars();
212 env::set_var(ENV_MINT_MANAGEMENT_ENABLED_LEGACY, "true");
213 for name in [
214 ENV_MINT_MANAGEMENT_ENABLED,
215 ENV_MINT_MANAGEMENT_ALLOW_INSECURE,
216 ] {
217 env::set_var(name, std::ffi::OsString::from_vec(vec![0xff]));
218 }
219 let config = MintManagementRpc {
220 enabled: true,
221 allow_insecure: true,
222 ..Default::default()
223 }
224 .from_env();
225 assert!(!config.enabled);
226 assert!(!config.allow_insecure);
227 clear_env_vars();
228 }
229
230 #[test]
231 fn management_rpc_payment_override_env_fails_closed() {
232 let _guard = env_lock();
233 clear_env_vars();
234 let management_rpc = MintManagementRpc {
235 allow_mint_quote_payment_override: true,
236 ..Default::default()
237 };
238
239 env::set_var(
240 ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE,
241 "false",
242 );
243 assert!(
244 !management_rpc
245 .clone()
246 .from_env()
247 .allow_mint_quote_payment_override
248 );
249
250 env::set_var(
251 ENV_MINT_MANAGEMENT_ALLOW_MINT_QUOTE_PAYMENT_OVERRIDE,
252 "not-a-boolean",
253 );
254 assert!(!management_rpc.from_env().allow_mint_quote_payment_override);
255
256 clear_env_vars();
257 }
258}