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 upstream_ca_cert(mut self, path: impl Into<PathBuf>) -> Self {
218 self.config.upstream_ca_cert.push(path.into());
219 self
220 }
221
222 pub fn intercept_ca_cert(mut self, path: impl Into<PathBuf>) -> Self {
224 self.config.intercept_ca.cert_path = Some(path.into());
225 self
226 }
227
228 pub fn intercept_ca_key(mut self, path: impl Into<PathBuf>) -> Self {
230 self.config.intercept_ca.key_path = Some(path.into());
231 self
232 }
233
234 pub fn build(self) -> TlsConfig {
236 self.config
237 }
238}
239
240impl SecretBuilder {
241 pub fn new() -> Self {
243 Self {
244 env_var: None,
245 value: None,
246 placeholder: None,
247 allowed_hosts: Vec::new(),
248 injection: SecretInjection::default(),
249 require_tls_identity: true,
250 }
251 }
252
253 pub fn env(mut self, var: impl Into<String>) -> Self {
255 self.env_var = Some(var.into());
256 self
257 }
258
259 pub fn value(mut self, value: impl Into<String>) -> Self {
261 self.value = Some(value.into());
262 self
263 }
264
265 pub fn placeholder(mut self, placeholder: impl Into<String>) -> Self {
268 self.placeholder = Some(placeholder.into());
269 self
270 }
271
272 pub fn allow_host(mut self, host: impl Into<String>) -> Self {
274 self.allowed_hosts.push(HostPattern::Exact(host.into()));
275 self
276 }
277
278 pub fn allow_host_pattern(mut self, pattern: impl Into<String>) -> Self {
280 self.allowed_hosts
281 .push(HostPattern::Wildcard(pattern.into()));
282 self
283 }
284
285 pub fn allow_any_host_dangerous(mut self, i_understand_the_risk: bool) -> Self {
288 if i_understand_the_risk {
289 self.allowed_hosts.push(HostPattern::Any);
290 }
291 self
292 }
293
294 pub fn require_tls_identity(mut self, enabled: bool) -> Self {
296 self.require_tls_identity = enabled;
297 self
298 }
299
300 pub fn inject_headers(mut self, enabled: bool) -> Self {
302 self.injection.headers = enabled;
303 self
304 }
305
306 pub fn inject_basic_auth(mut self, enabled: bool) -> Self {
308 self.injection.basic_auth = enabled;
309 self
310 }
311
312 pub fn inject_query(mut self, enabled: bool) -> Self {
314 self.injection.query_params = enabled;
315 self
316 }
317
318 pub fn inject_body(mut self, enabled: bool) -> Self {
320 self.injection.body = enabled;
321 self
322 }
323
324 pub fn build(self) -> SecretEntry {
329 let env_var = self.env_var.expect("SecretBuilder: .env() is required");
330 let value = self.value.expect("SecretBuilder: .value() is required");
331 let placeholder = self
332 .placeholder
333 .unwrap_or_else(|| format!("$MSB_{env_var}"));
334
335 SecretEntry {
336 env_var,
337 value,
338 placeholder,
339 allowed_hosts: self.allowed_hosts,
340 injection: self.injection,
341 require_tls_identity: self.require_tls_identity,
342 }
343 }
344}
345
346impl Default for NetworkBuilder {
351 fn default() -> Self {
352 Self::new()
353 }
354}
355
356impl Default for TlsBuilder {
357 fn default() -> Self {
358 Self::new()
359 }
360}
361
362impl Default for SecretBuilder {
363 fn default() -> Self {
364 Self::new()
365 }
366}