microsandbox_network/
builder.rs1use std::net::IpAddr;
6use std::path::PathBuf;
7
8use crate::config::{InterfaceOverrides, NetworkConfig, PortProtocol, PublishedPort};
9use crate::policy::NetworkPolicy;
10use crate::secrets::config::{HostPattern, SecretEntry, SecretInjection, ViolationAction};
11use crate::tls::TlsConfig;
12
13pub struct NetworkBuilder {
19 config: NetworkConfig,
20}
21
22pub struct TlsBuilder {
24 config: TlsConfig,
25}
26
27pub struct SecretBuilder {
37 env_var: Option<String>,
38 value: Option<String>,
39 placeholder: Option<String>,
40 allowed_hosts: Vec<HostPattern>,
41 injection: SecretInjection,
42 require_tls_identity: bool,
43}
44
45impl NetworkBuilder {
50 pub fn new() -> Self {
52 Self {
53 config: NetworkConfig::default(),
54 }
55 }
56
57 pub fn from_config(config: NetworkConfig) -> Self {
59 Self { config }
60 }
61
62 pub fn enabled(mut self, enabled: bool) -> Self {
64 self.config.enabled = enabled;
65 self
66 }
67
68 pub fn port(self, host_port: u16, guest_port: u16) -> Self {
70 self.add_port(host_port, guest_port, PortProtocol::Tcp)
71 }
72
73 pub fn port_udp(self, host_port: u16, guest_port: u16) -> Self {
75 self.add_port(host_port, guest_port, PortProtocol::Udp)
76 }
77
78 fn add_port(mut self, host_port: u16, guest_port: u16, protocol: PortProtocol) -> Self {
79 self.config.ports.push(PublishedPort {
80 host_port,
81 guest_port,
82 protocol,
83 host_bind: IpAddr::V4(std::net::Ipv4Addr::LOCALHOST),
84 });
85 self
86 }
87
88 pub fn policy(mut self, policy: NetworkPolicy) -> Self {
90 self.config.policy = policy;
91 self
92 }
93
94 pub fn block_domain(mut self, domain: impl Into<String>) -> Self {
96 self.config.dns.blocked_domains.push(domain.into());
97 self
98 }
99
100 pub fn block_domain_suffix(mut self, suffix: impl Into<String>) -> Self {
102 self.config.dns.blocked_suffixes.push(suffix.into());
103 self
104 }
105
106 pub fn dns_rebind_protection(mut self, enabled: bool) -> Self {
108 self.config.dns.rebind_protection = enabled;
109 self
110 }
111
112 pub fn tls(mut self, f: impl FnOnce(TlsBuilder) -> TlsBuilder) -> Self {
114 self.config.tls = f(TlsBuilder::new()).build();
115 self
116 }
117
118 pub fn secret(mut self, f: impl FnOnce(SecretBuilder) -> SecretBuilder) -> Self {
128 self.config
129 .secrets
130 .secrets
131 .push(f(SecretBuilder::new()).build());
132 self
133 }
134
135 pub fn secret_env(
137 mut self,
138 env_var: impl Into<String>,
139 value: impl Into<String>,
140 placeholder: impl Into<String>,
141 allowed_host: impl Into<String>,
142 ) -> Self {
143 self.config.secrets.secrets.push(SecretEntry {
144 env_var: env_var.into(),
145 value: value.into(),
146 placeholder: placeholder.into(),
147 allowed_hosts: vec![HostPattern::Exact(allowed_host.into())],
148 injection: SecretInjection::default(),
149 require_tls_identity: true,
150 });
151 self
152 }
153
154 pub fn on_secret_violation(mut self, action: ViolationAction) -> Self {
156 self.config.secrets.on_violation = action;
157 self
158 }
159
160 pub fn max_connections(mut self, max: usize) -> Self {
162 self.config.max_connections = Some(max);
163 self
164 }
165
166 pub fn interface(mut self, overrides: InterfaceOverrides) -> Self {
168 self.config.interface = overrides;
169 self
170 }
171
172 pub fn build(self) -> NetworkConfig {
174 self.config
175 }
176}
177
178impl TlsBuilder {
179 pub fn new() -> Self {
181 Self {
182 config: TlsConfig {
183 enabled: true,
184 ..TlsConfig::default()
185 },
186 }
187 }
188
189 pub fn bypass(mut self, pattern: impl Into<String>) -> Self {
191 self.config.bypass.push(pattern.into());
192 self
193 }
194
195 pub fn verify_upstream(mut self, verify: bool) -> Self {
197 self.config.verify_upstream = verify;
198 self
199 }
200
201 pub fn intercepted_ports(mut self, ports: Vec<u16>) -> Self {
203 self.config.intercepted_ports = ports;
204 self
205 }
206
207 pub fn block_quic(mut self, block: bool) -> Self {
209 self.config.block_quic_on_intercept = block;
210 self
211 }
212
213 pub fn ca_cert(mut self, path: impl Into<PathBuf>) -> Self {
215 self.config.ca.cert_path = Some(path.into());
216 self
217 }
218
219 pub fn ca_key(mut self, path: impl Into<PathBuf>) -> Self {
221 self.config.ca.key_path = Some(path.into());
222 self
223 }
224
225 pub fn build(self) -> TlsConfig {
227 self.config
228 }
229}
230
231impl SecretBuilder {
232 pub fn new() -> Self {
234 Self {
235 env_var: None,
236 value: None,
237 placeholder: None,
238 allowed_hosts: Vec::new(),
239 injection: SecretInjection::default(),
240 require_tls_identity: true,
241 }
242 }
243
244 pub fn env(mut self, var: impl Into<String>) -> Self {
246 self.env_var = Some(var.into());
247 self
248 }
249
250 pub fn value(mut self, value: impl Into<String>) -> Self {
252 self.value = Some(value.into());
253 self
254 }
255
256 pub fn placeholder(mut self, placeholder: impl Into<String>) -> Self {
259 self.placeholder = Some(placeholder.into());
260 self
261 }
262
263 pub fn allow_host(mut self, host: impl Into<String>) -> Self {
265 self.allowed_hosts.push(HostPattern::Exact(host.into()));
266 self
267 }
268
269 pub fn allow_host_pattern(mut self, pattern: impl Into<String>) -> Self {
271 self.allowed_hosts
272 .push(HostPattern::Wildcard(pattern.into()));
273 self
274 }
275
276 pub fn allow_any_host_dangerous(mut self, i_understand_the_risk: bool) -> Self {
279 if i_understand_the_risk {
280 self.allowed_hosts.push(HostPattern::Any);
281 }
282 self
283 }
284
285 pub fn require_tls_identity(mut self, enabled: bool) -> Self {
287 self.require_tls_identity = enabled;
288 self
289 }
290
291 pub fn inject_headers(mut self, enabled: bool) -> Self {
293 self.injection.headers = enabled;
294 self
295 }
296
297 pub fn inject_basic_auth(mut self, enabled: bool) -> Self {
299 self.injection.basic_auth = enabled;
300 self
301 }
302
303 pub fn inject_query(mut self, enabled: bool) -> Self {
305 self.injection.query_params = enabled;
306 self
307 }
308
309 pub fn inject_body(mut self, enabled: bool) -> Self {
311 self.injection.body = enabled;
312 self
313 }
314
315 pub fn build(self) -> SecretEntry {
320 let env_var = self.env_var.expect("SecretBuilder: .env() is required");
321 let value = self.value.expect("SecretBuilder: .value() is required");
322 let placeholder = self
323 .placeholder
324 .unwrap_or_else(|| format!("$MSB_{env_var}"));
325
326 SecretEntry {
327 env_var,
328 value,
329 placeholder,
330 allowed_hosts: self.allowed_hosts,
331 injection: self.injection,
332 require_tls_identity: self.require_tls_identity,
333 }
334 }
335}
336
337impl Default for NetworkBuilder {
342 fn default() -> Self {
343 Self::new()
344 }
345}
346
347impl Default for TlsBuilder {
348 fn default() -> Self {
349 Self::new()
350 }
351}
352
353impl Default for SecretBuilder {
354 fn default() -> Self {
355 Self::new()
356 }
357}