1#[cfg(feature = "hashbrown")]
5use hashbrown::{HashMap, HashSet, hash_map::Entry};
6#[cfg(not(feature = "hashbrown"))]
7use std::collections::{HashMap, HashSet, hash_map::Entry};
8use std::hash::Hash;
9use std::net::{IpAddr, SocketAddr};
10use std::ops::RangeInclusive;
11use std::sync::Arc;
12
13use matchit::Router;
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17use crate::{
18 error::AddError,
19 utils::{self, IntoIpRange, authority::Authority},
20};
21
22pub type ValidateFn = Arc<
24 dyn for<'h> Fn(
25 &str,
26 &Authority,
27 Box<dyn Iterator<Item = (&'h str, &'h str)> + Send + Sync + 'h>,
28 Option<&[u8]>,
29 ) -> AclClassification
30 + Send
31 + Sync,
32>;
33
34#[derive(Clone)]
35pub struct HttpAcl {
37 allow_http: bool,
38 allow_https: bool,
39 allowed_methods: HashSet<HttpRequestMethod>,
40 denied_methods: HashSet<HttpRequestMethod>,
41 allowed_hosts: HashSet<Box<str>>,
42 denied_hosts: HashSet<Box<str>>,
43 allowed_port_ranges: Box<[RangeInclusive<u16>]>,
44 denied_port_ranges: Box<[RangeInclusive<u16>]>,
45 allowed_ip_ranges: Box<[RangeInclusive<IpAddr>]>,
46 denied_ip_ranges: Box<[RangeInclusive<IpAddr>]>,
47 static_dns_mapping: HashMap<Box<str>, SocketAddr>,
48 allowed_headers: HashMap<Box<str>, Option<Box<str>>>,
49 denied_headers: HashMap<Box<str>, Option<Box<str>>>,
50 allowed_url_paths_router: Router<()>,
51 denied_url_paths_router: Router<()>,
52 validate_fn: Option<ValidateFn>,
53 allow_non_global_ip_ranges: bool,
54 method_acl_default: bool,
55 host_acl_default: bool,
56 port_acl_default: bool,
57 ip_acl_default: bool,
58 header_acl_default: bool,
59 url_path_acl_default: bool,
60}
61
62impl std::fmt::Debug for HttpAcl {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 f.debug_struct("HttpAcl")
65 .field("allow_http", &self.allow_http)
66 .field("allow_https", &self.allow_https)
67 .field("allowed_methods", &self.allowed_methods)
68 .field("denied_methods", &self.denied_methods)
69 .field("allowed_hosts", &self.allowed_hosts)
70 .field("denied_hosts", &self.denied_hosts)
71 .field("allowed_port_ranges", &self.allowed_port_ranges)
72 .field("denied_port_ranges", &self.denied_port_ranges)
73 .field("allowed_ip_ranges", &self.allowed_ip_ranges)
74 .field("denied_ip_ranges", &self.denied_ip_ranges)
75 .field("static_dns_mapping", &self.static_dns_mapping)
76 .field("allowed_headers", &self.allowed_headers)
77 .field("denied_headers", &self.denied_headers)
78 .field(
79 "allow_non_global_ip_ranges",
80 &self.allow_non_global_ip_ranges,
81 )
82 .field("method_acl_default", &self.method_acl_default)
83 .field("host_acl_default", &self.host_acl_default)
84 .field("port_acl_default", &self.port_acl_default)
85 .field("ip_acl_default", &self.ip_acl_default)
86 .field("header_acl_default", &self.header_acl_default)
87 .field("url_path_acl_default", &self.url_path_acl_default)
88 .finish()
89 }
90}
91
92impl PartialEq for HttpAcl {
93 fn eq(&self, other: &Self) -> bool {
94 self.allow_http == other.allow_http
95 && self.allow_https == other.allow_https
96 && self.allowed_methods == other.allowed_methods
97 && self.denied_methods == other.denied_methods
98 && self.allowed_hosts == other.allowed_hosts
99 && self.denied_hosts == other.denied_hosts
100 && self.allowed_port_ranges == other.allowed_port_ranges
101 && self.denied_port_ranges == other.denied_port_ranges
102 && self.allowed_ip_ranges == other.allowed_ip_ranges
103 && self.denied_ip_ranges == other.denied_ip_ranges
104 && self.static_dns_mapping == other.static_dns_mapping
105 && self.allowed_headers == other.allowed_headers
106 && self.denied_headers == other.denied_headers
107 && self.allow_non_global_ip_ranges == other.allow_non_global_ip_ranges
108 && self.method_acl_default == other.method_acl_default
109 && self.host_acl_default == other.host_acl_default
110 && self.port_acl_default == other.port_acl_default
111 && self.ip_acl_default == other.ip_acl_default
112 && self.header_acl_default == other.header_acl_default
113 && self.url_path_acl_default == other.url_path_acl_default
114 }
115}
116
117impl std::default::Default for HttpAcl {
118 fn default() -> Self {
119 Self {
120 allow_http: true,
121 allow_https: true,
122 allowed_methods: [
123 HttpRequestMethod::CONNECT,
124 HttpRequestMethod::DELETE,
125 HttpRequestMethod::GET,
126 HttpRequestMethod::HEAD,
127 HttpRequestMethod::OPTIONS,
128 HttpRequestMethod::PATCH,
129 HttpRequestMethod::POST,
130 HttpRequestMethod::PUT,
131 HttpRequestMethod::TRACE,
132 ]
133 .into_iter()
134 .collect(),
135 denied_methods: HashSet::new(),
136 allowed_hosts: HashSet::new(),
137 denied_hosts: HashSet::new(),
138 allowed_port_ranges: vec![80..=80, 443..=443].into_boxed_slice(),
139 denied_port_ranges: Vec::new().into_boxed_slice(),
140 allowed_ip_ranges: Vec::new().into_boxed_slice(),
141 denied_ip_ranges: Vec::new().into_boxed_slice(),
142 static_dns_mapping: HashMap::new(),
143 allowed_headers: HashMap::new(),
144 denied_headers: HashMap::new(),
145 allowed_url_paths_router: Router::new(),
146 denied_url_paths_router: Router::new(),
147 validate_fn: None,
148 allow_non_global_ip_ranges: false,
149 method_acl_default: false,
150 host_acl_default: false,
151 port_acl_default: false,
152 ip_acl_default: false,
153 header_acl_default: true,
154 url_path_acl_default: true,
155 }
156 }
157}
158
159impl HttpAcl {
160 pub fn builder() -> HttpAclBuilder {
162 HttpAclBuilder::new()
163 }
164
165 pub fn is_scheme_allowed(&self, scheme: &str) -> AclClassification {
167 if scheme == "http" && self.allow_http || scheme == "https" && self.allow_https {
168 AclClassification::AllowedUserAcl
169 } else {
170 AclClassification::DeniedUserAcl
171 }
172 }
173
174 pub fn is_method_allowed(&self, method: impl Into<HttpRequestMethod>) -> AclClassification {
178 let method = method.into();
179 if self.allowed_methods.contains(&method) {
180 AclClassification::AllowedUserAcl
181 } else if self.denied_methods.contains(&method) {
182 AclClassification::DeniedUserAcl
183 } else if self.method_acl_default {
184 AclClassification::AllowedDefault
185 } else {
186 AclClassification::DeniedDefault
187 }
188 }
189
190 pub fn is_host_allowed(&self, host: &str) -> AclClassification {
194 if self.allowed_hosts.iter().any(|h| h.as_ref() == host) {
195 AclClassification::AllowedUserAcl
196 } else if self.denied_hosts.iter().any(|h| h.as_ref() == host) {
197 AclClassification::DeniedUserAcl
198 } else if self.host_acl_default {
199 AclClassification::AllowedDefault
200 } else {
201 AclClassification::DeniedDefault
202 }
203 }
204
205 pub fn is_port_allowed(&self, port: u16) -> AclClassification {
207 if Self::is_port_in_ranges(port, &self.allowed_port_ranges) {
208 AclClassification::AllowedUserAcl
209 } else if Self::is_port_in_ranges(port, &self.denied_port_ranges) {
210 AclClassification::DeniedUserAcl
211 } else if self.port_acl_default {
212 AclClassification::AllowedDefault
213 } else {
214 AclClassification::DeniedDefault
215 }
216 }
217
218 pub fn is_ip_allowed(&self, ip: &IpAddr) -> AclClassification {
220 if !utils::ip::is_global_ip(ip) && !self.allow_non_global_ip_ranges {
221 AclClassification::DeniedNotGlobal
222 } else if Self::is_ip_in_ranges(ip, &self.allowed_ip_ranges) {
223 AclClassification::AllowedUserAcl
224 } else if Self::is_ip_in_ranges(ip, &self.denied_ip_ranges) {
225 AclClassification::DeniedUserAcl
226 } else if self.ip_acl_default {
227 AclClassification::AllowedDefault
228 } else {
229 AclClassification::DeniedDefault
230 }
231 }
232
233 pub fn resolve_static_dns_mapping(&self, host: &str) -> Option<SocketAddr> {
237 self.static_dns_mapping.get(host).copied()
238 }
239
240 pub fn is_header_allowed(&self, header_name: &str, header_value: &str) -> AclClassification {
244 if let Some(allowed_value) = self.allowed_headers.get(header_name) {
245 if allowed_value.as_deref() == Some(header_value) || allowed_value.is_none() {
246 AclClassification::AllowedUserAcl
247 } else {
248 AclClassification::DeniedUserAcl
249 }
250 } else if let Some(denied_value) = self.denied_headers.get(header_name) {
251 if denied_value.as_deref() == Some(header_value) || denied_value.is_none() {
252 AclClassification::DeniedUserAcl
253 } else {
254 AclClassification::AllowedUserAcl
255 }
256 } else if self.header_acl_default {
257 AclClassification::AllowedDefault
258 } else {
259 AclClassification::DeniedDefault
260 }
261 }
262
263 pub fn is_url_path_allowed(&self, url_path: &str) -> AclClassification {
267 if self.allowed_url_paths_router.at(url_path).is_ok() {
268 AclClassification::AllowedUserAcl
269 } else if self.denied_url_paths_router.at(url_path).is_ok() {
270 AclClassification::DeniedUserAcl
271 } else if self.url_path_acl_default {
272 AclClassification::AllowedDefault
273 } else {
274 AclClassification::DeniedDefault
275 }
276 }
277
278 pub fn is_valid<'h>(
280 &self,
281 scheme: &str,
282 authority: &Authority,
283 headers: impl Iterator<Item = (&'h str, &'h str)> + Send + Sync + 'h,
284 body: Option<&[u8]>,
285 ) -> AclClassification {
286 if let Some(validate_fn) = &self.validate_fn {
287 validate_fn(scheme, authority, Box::new(headers), body)
288 } else {
289 AclClassification::AllowedDefault
290 }
291 }
292
293 fn is_ip_in_ranges(ip: &IpAddr, ranges: &[RangeInclusive<IpAddr>]) -> bool {
295 ranges.iter().any(|range| range.contains(ip))
296 }
297
298 fn is_port_in_ranges(port: u16, ranges: &[RangeInclusive<u16>]) -> bool {
300 ranges.iter().any(|range| range.contains(&port))
301 }
302}
303
304#[non_exhaustive]
306#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
307pub enum AclClassification {
308 AllowedUserAcl,
310 AllowedDefault,
312 DeniedUserAcl,
314 DeniedDefault,
316 Denied(String),
318 DeniedNotGlobal,
320}
321
322impl std::fmt::Display for AclClassification {
323 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324 match self {
325 AclClassification::AllowedUserAcl => {
326 write!(f, "The entity is allowed according to the allowed ACL.")
327 }
328 AclClassification::AllowedDefault => write!(
329 f,
330 "The entity is allowed because the default is to allow if no ACL match is found."
331 ),
332 AclClassification::DeniedUserAcl => {
333 write!(f, "The entity is denied according to the denied ACL.")
334 }
335 AclClassification::DeniedNotGlobal => {
336 write!(f, "The ip is denied because it is not global.")
337 }
338 AclClassification::DeniedDefault => write!(
339 f,
340 "The entity is denied because the default is to deny if no ACL match is found."
341 ),
342 AclClassification::Denied(reason) => {
343 write!(f, "The entity is denied because {reason}.")
344 }
345 }
346 }
347}
348
349impl AclClassification {
350 pub fn is_allowed(&self) -> bool {
352 matches!(
353 self,
354 AclClassification::AllowedUserAcl | AclClassification::AllowedDefault
355 )
356 }
357
358 pub fn is_denied(&self) -> bool {
360 matches!(
361 self,
362 AclClassification::DeniedUserAcl
363 | AclClassification::Denied(_)
364 | AclClassification::DeniedDefault
365 | AclClassification::DeniedNotGlobal
366 )
367 }
368}
369
370#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
372#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
373pub enum HttpRequestMethod {
374 CONNECT,
376 DELETE,
378 GET,
380 HEAD,
382 OPTIONS,
384 PATCH,
386 POST,
388 PUT,
390 TRACE,
392 OTHER(Box<str>),
394}
395
396impl From<&str> for HttpRequestMethod {
397 fn from(method: &str) -> Self {
398 match method {
399 "CONNECT" => HttpRequestMethod::CONNECT,
400 "DELETE" => HttpRequestMethod::DELETE,
401 "GET" => HttpRequestMethod::GET,
402 "HEAD" => HttpRequestMethod::HEAD,
403 "OPTIONS" => HttpRequestMethod::OPTIONS,
404 "PATCH" => HttpRequestMethod::PATCH,
405 "POST" => HttpRequestMethod::POST,
406 "PUT" => HttpRequestMethod::PUT,
407 "TRACE" => HttpRequestMethod::TRACE,
408 _ => HttpRequestMethod::OTHER(method.into()),
409 }
410 }
411}
412
413impl HttpRequestMethod {
414 pub fn as_str(&self) -> &str {
416 match self {
417 HttpRequestMethod::CONNECT => "CONNECT",
418 HttpRequestMethod::DELETE => "DELETE",
419 HttpRequestMethod::GET => "GET",
420 HttpRequestMethod::HEAD => "HEAD",
421 HttpRequestMethod::OPTIONS => "OPTIONS",
422 HttpRequestMethod::PATCH => "PATCH",
423 HttpRequestMethod::POST => "POST",
424 HttpRequestMethod::PUT => "PUT",
425 HttpRequestMethod::TRACE => "TRACE",
426 HttpRequestMethod::OTHER(other) => other,
427 }
428 }
429}
430
431#[derive(Default, Clone)]
433#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
434pub struct HttpAclBuilder {
435 allow_http: bool,
436 allow_https: bool,
437 allowed_methods: Vec<HttpRequestMethod>,
438 denied_methods: Vec<HttpRequestMethod>,
439 allowed_hosts: Vec<String>,
440 denied_hosts: Vec<String>,
441 allowed_port_ranges: Vec<RangeInclusive<u16>>,
442 denied_port_ranges: Vec<RangeInclusive<u16>>,
443 allowed_ip_ranges: Vec<RangeInclusive<IpAddr>>,
444 denied_ip_ranges: Vec<RangeInclusive<IpAddr>>,
445 static_dns_mapping: HashMap<String, SocketAddr>,
446 allowed_headers: HashMap<String, Option<String>>,
447 denied_headers: HashMap<String, Option<String>>,
448 allowed_url_paths: Vec<String>,
449 #[cfg_attr(feature = "serde", serde(skip))]
450 allowed_url_paths_router: Router<()>,
451 denied_url_paths: Vec<String>,
452 #[cfg_attr(feature = "serde", serde(skip))]
453 denied_url_paths_router: Router<()>,
454 allow_non_global_ip_ranges: bool,
455 method_acl_default: bool,
456 host_acl_default: bool,
457 port_acl_default: bool,
458 ip_acl_default: bool,
459 header_acl_default: bool,
460 url_path_acl_default: bool,
461}
462
463impl std::fmt::Debug for HttpAclBuilder {
464 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
465 f.debug_struct("HttpAclBuilder")
466 .field("allow_http", &self.allow_http)
467 .field("allow_https", &self.allow_https)
468 .field("allowed_methods", &self.allowed_methods)
469 .field("denied_methods", &self.denied_methods)
470 .field("allowed_hosts", &self.allowed_hosts)
471 .field("denied_hosts", &self.denied_hosts)
472 .field("allowed_port_ranges", &self.allowed_port_ranges)
473 .field("denied_port_ranges", &self.denied_port_ranges)
474 .field("allowed_ip_ranges", &self.allowed_ip_ranges)
475 .field("denied_ip_ranges", &self.denied_ip_ranges)
476 .field("static_dns_mapping", &self.static_dns_mapping)
477 .field("allowed_headers", &self.allowed_headers)
478 .field("denied_headers", &self.denied_headers)
479 .field("allowed_url_paths", &self.allowed_url_paths)
480 .field("denied_url_paths", &self.denied_url_paths)
481 .field(
482 "allow_non_global_ip_ranges",
483 &self.allow_non_global_ip_ranges,
484 )
485 .field("method_acl_default", &self.method_acl_default)
486 .field("host_acl_default", &self.host_acl_default)
487 .field("port_acl_default", &self.port_acl_default)
488 .field("ip_acl_default", &self.ip_acl_default)
489 .field("header_acl_default", &self.header_acl_default)
490 .field("url_path_acl_default", &self.url_path_acl_default)
491 .finish()
492 }
493}
494
495impl PartialEq for HttpAclBuilder {
496 fn eq(&self, other: &Self) -> bool {
497 self.allow_http == other.allow_http
498 && self.allow_https == other.allow_https
499 && self.allowed_methods == other.allowed_methods
500 && self.denied_methods == other.denied_methods
501 && self.allowed_hosts == other.allowed_hosts
502 && self.denied_hosts == other.denied_hosts
503 && self.allowed_port_ranges == other.allowed_port_ranges
504 && self.denied_port_ranges == other.denied_port_ranges
505 && self.allowed_ip_ranges == other.allowed_ip_ranges
506 && self.denied_ip_ranges == other.denied_ip_ranges
507 && self.static_dns_mapping == other.static_dns_mapping
508 && self.allowed_headers == other.allowed_headers
509 && self.denied_headers == other.denied_headers
510 && self.allowed_url_paths == other.allowed_url_paths
511 && self.denied_url_paths == other.denied_url_paths
512 && self.allow_non_global_ip_ranges == other.allow_non_global_ip_ranges
513 && self.method_acl_default == other.method_acl_default
514 && self.host_acl_default == other.host_acl_default
515 && self.port_acl_default == other.port_acl_default
516 && self.ip_acl_default == other.ip_acl_default
517 && self.header_acl_default == other.header_acl_default
518 && self.url_path_acl_default == other.url_path_acl_default
519 }
520}
521
522impl HttpAclBuilder {
523 pub fn new() -> Self {
525 Self {
526 allow_http: true,
527 allow_https: true,
528 allowed_methods: vec![
529 HttpRequestMethod::CONNECT,
530 HttpRequestMethod::DELETE,
531 HttpRequestMethod::GET,
532 HttpRequestMethod::HEAD,
533 HttpRequestMethod::OPTIONS,
534 HttpRequestMethod::PATCH,
535 HttpRequestMethod::POST,
536 HttpRequestMethod::PUT,
537 HttpRequestMethod::TRACE,
538 ],
539 denied_methods: Vec::new(),
540 allowed_hosts: Vec::new(),
541 denied_hosts: Vec::new(),
542 allowed_port_ranges: vec![80..=80, 443..=443],
543 denied_port_ranges: Vec::new(),
544 allowed_ip_ranges: Vec::new(),
545 denied_ip_ranges: Vec::new(),
546 allowed_headers: HashMap::new(),
547 denied_headers: HashMap::new(),
548 allowed_url_paths: Vec::new(),
549 allowed_url_paths_router: Router::new(),
550 denied_url_paths: Vec::new(),
551 denied_url_paths_router: Router::new(),
552 allow_non_global_ip_ranges: false,
553 static_dns_mapping: HashMap::new(),
554 method_acl_default: false,
555 host_acl_default: false,
556 port_acl_default: false,
557 ip_acl_default: false,
558 header_acl_default: true,
559 url_path_acl_default: true,
560 }
561 }
562
563 pub fn http(mut self, allow: bool) -> Self {
565 self.allow_http = allow;
566 self
567 }
568
569 pub fn https(mut self, allow: bool) -> Self {
571 self.allow_https = allow;
572 self
573 }
574
575 pub fn non_global_ip_ranges(mut self, allow: bool) -> Self {
579 self.allow_non_global_ip_ranges = allow;
580 self
581 }
582
583 pub fn method_acl_default(mut self, allow: bool) -> Self {
585 self.method_acl_default = allow;
586 self
587 }
588
589 pub fn host_acl_default(mut self, allow: bool) -> Self {
591 self.host_acl_default = allow;
592 self
593 }
594
595 pub fn port_acl_default(mut self, allow: bool) -> Self {
597 self.port_acl_default = allow;
598 self
599 }
600
601 pub fn ip_acl_default(mut self, allow: bool) -> Self {
603 self.ip_acl_default = allow;
604 self
605 }
606
607 pub fn header_acl_default(mut self, allow: bool) -> Self {
609 self.header_acl_default = allow;
610 self
611 }
612
613 pub fn url_path_acl_default(mut self, allow: bool) -> Self {
615 self.url_path_acl_default = allow;
616 self
617 }
618
619 pub fn add_allowed_method(
623 mut self,
624 method: impl Into<HttpRequestMethod>,
625 ) -> Result<Self, AddError> {
626 let method = method.into();
627 if self.denied_methods.contains(&method) {
628 Err(AddError::AlreadyDeniedMethod(method))
629 } else if self.allowed_methods.contains(&method) {
630 Err(AddError::AlreadyAllowedMethod(method))
631 } else {
632 self.allowed_methods.push(method);
633 Ok(self)
634 }
635 }
636
637 pub fn remove_allowed_method(mut self, method: impl Into<HttpRequestMethod>) -> Self {
641 let method = method.into();
642 self.allowed_methods.retain(|m| m != &method);
643 self
644 }
645
646 pub fn allowed_methods(
650 mut self,
651 methods: Vec<impl Into<HttpRequestMethod>>,
652 ) -> Result<Self, AddError> {
653 let methods = methods.into_iter().map(|m| m.into()).collect::<Vec<_>>();
654
655 for method in &methods {
656 if self.denied_methods.contains(method) {
657 return Err(AddError::AlreadyDeniedMethod(method.clone()));
658 }
659 }
660 self.allowed_methods = methods;
661 Ok(self)
662 }
663
664 pub fn clear_allowed_methods(mut self) -> Self {
666 self.allowed_methods.clear();
667 self
668 }
669
670 pub fn add_denied_method(
674 mut self,
675 method: impl Into<HttpRequestMethod>,
676 ) -> Result<Self, AddError> {
677 let method = method.into();
678 if self.allowed_methods.contains(&method) {
679 Err(AddError::AlreadyAllowedMethod(method))
680 } else if self.denied_methods.contains(&method) {
681 Err(AddError::AlreadyDeniedMethod(method))
682 } else {
683 self.denied_methods.push(method);
684 Ok(self)
685 }
686 }
687
688 pub fn remove_denied_method(mut self, method: impl Into<HttpRequestMethod>) -> Self {
692 let method = method.into();
693 self.denied_methods.retain(|m| m != &method);
694 self
695 }
696
697 pub fn denied_methods(
701 mut self,
702 methods: Vec<impl Into<HttpRequestMethod>>,
703 ) -> Result<Self, AddError> {
704 let methods = methods.into_iter().map(|m| m.into()).collect::<Vec<_>>();
705
706 for method in &methods {
707 if self.allowed_methods.contains(method) {
708 return Err(AddError::AlreadyAllowedMethod(method.clone()));
709 }
710 }
711 self.denied_methods = methods;
712 Ok(self)
713 }
714
715 pub fn clear_denied_methods(mut self) -> Self {
717 self.denied_methods.clear();
718 self
719 }
720
721 pub fn add_allowed_host(mut self, host: String) -> Result<Self, AddError> {
725 if utils::authority::is_valid_host(&host) {
726 if self.denied_hosts.contains(&host) {
727 Err(AddError::AlreadyDeniedHost(host))
728 } else if self.allowed_hosts.contains(&host) {
729 Err(AddError::AlreadyAllowedHost(host))
730 } else {
731 self.allowed_hosts.push(host);
732 Ok(self)
733 }
734 } else {
735 Err(AddError::InvalidEntity(host))
736 }
737 }
738
739 pub fn remove_allowed_host(mut self, host: String) -> Self {
743 self.allowed_hosts.retain(|h| h != &host);
744 self
745 }
746
747 pub fn allowed_hosts(mut self, hosts: Vec<String>) -> Result<Self, AddError> {
751 for host in &hosts {
752 if utils::authority::is_valid_host(host) {
753 if self.denied_hosts.contains(host) {
754 return Err(AddError::AlreadyDeniedHost(host.clone()));
755 }
756 } else {
757 return Err(AddError::InvalidEntity(host.clone()));
758 }
759 }
760 self.allowed_hosts = hosts;
761 Ok(self)
762 }
763
764 pub fn clear_allowed_hosts(mut self) -> Self {
766 self.allowed_hosts.clear();
767 self
768 }
769
770 pub fn add_denied_host(mut self, host: String) -> Result<Self, AddError> {
774 if utils::authority::is_valid_host(&host) {
775 if self.allowed_hosts.contains(&host) {
776 Err(AddError::AlreadyAllowedHost(host))
777 } else if self.denied_hosts.contains(&host) {
778 Err(AddError::AlreadyDeniedHost(host))
779 } else {
780 self.denied_hosts.push(host);
781 Ok(self)
782 }
783 } else {
784 Err(AddError::InvalidEntity(host))
785 }
786 }
787
788 pub fn remove_denied_host(mut self, host: String) -> Self {
792 self.denied_hosts.retain(|h| h != &host);
793 self
794 }
795
796 pub fn denied_hosts(mut self, hosts: Vec<String>) -> Result<Self, AddError> {
800 for host in &hosts {
801 if utils::authority::is_valid_host(host) {
802 if self.allowed_hosts.contains(host) {
803 return Err(AddError::AlreadyAllowedHost(host.clone()));
804 }
805 } else {
806 return Err(AddError::InvalidEntity(host.clone()));
807 }
808 }
809 self.denied_hosts = hosts;
810 Ok(self)
811 }
812
813 pub fn clear_denied_hosts(mut self) -> Self {
815 self.denied_hosts.clear();
816 self
817 }
818
819 pub fn add_allowed_port_range(
821 mut self,
822 port_range: RangeInclusive<u16>,
823 ) -> Result<Self, AddError> {
824 if self.denied_port_ranges.contains(&port_range) {
825 Err(AddError::AlreadyDeniedPortRange(port_range))
826 } else if self.allowed_port_ranges.contains(&port_range) {
827 Err(AddError::AlreadyAllowedPortRange(port_range))
828 } else if utils::range_overlaps(&self.allowed_port_ranges, &port_range, None)
829 || utils::range_overlaps(&self.denied_port_ranges, &port_range, None)
830 {
831 Err(AddError::Overlaps(format!("{port_range:?}")))
832 } else {
833 self.allowed_port_ranges.push(port_range);
834 Ok(self)
835 }
836 }
837
838 pub fn remove_allowed_port_range(mut self, port_range: RangeInclusive<u16>) -> Self {
840 self.allowed_port_ranges.retain(|p| p != &port_range);
841 self
842 }
843
844 pub fn allowed_port_ranges(
846 mut self,
847 port_ranges: Vec<RangeInclusive<u16>>,
848 ) -> Result<Self, AddError> {
849 for (i, port_range) in port_ranges.iter().enumerate() {
850 if self.denied_port_ranges.contains(port_range) {
851 return Err(AddError::AlreadyDeniedPortRange(port_range.clone()));
852 } else if utils::range_overlaps(&port_ranges, port_range, Some(i))
853 || utils::range_overlaps(&self.denied_port_ranges, port_range, None)
854 {
855 return Err(AddError::Overlaps(format!("{port_range:?}")));
856 }
857 }
858 self.allowed_port_ranges = port_ranges;
859 Ok(self)
860 }
861
862 pub fn clear_allowed_port_ranges(mut self) -> Self {
864 self.allowed_port_ranges.clear();
865 self
866 }
867
868 pub fn add_denied_port_range(
870 mut self,
871 port_range: RangeInclusive<u16>,
872 ) -> Result<Self, AddError> {
873 if self.allowed_port_ranges.contains(&port_range) {
874 Err(AddError::AlreadyAllowedPortRange(port_range))
875 } else if self.denied_port_ranges.contains(&port_range) {
876 Err(AddError::AlreadyDeniedPortRange(port_range))
877 } else if utils::range_overlaps(&self.allowed_port_ranges, &port_range, None)
878 || utils::range_overlaps(&self.denied_port_ranges, &port_range, None)
879 {
880 Err(AddError::Overlaps(format!("{port_range:?}")))
881 } else {
882 self.denied_port_ranges.push(port_range);
883 Ok(self)
884 }
885 }
886
887 pub fn remove_denied_port_range(mut self, port_range: RangeInclusive<u16>) -> Self {
889 self.denied_port_ranges.retain(|p| p != &port_range);
890 self
891 }
892
893 pub fn denied_port_ranges(
895 mut self,
896 port_ranges: Vec<RangeInclusive<u16>>,
897 ) -> Result<Self, AddError> {
898 for port_range in &port_ranges {
899 if self.allowed_port_ranges.contains(port_range) {
900 return Err(AddError::AlreadyAllowedPortRange(port_range.clone()));
901 }
902 }
903 self.denied_port_ranges = port_ranges;
904 Ok(self)
905 }
906
907 pub fn clear_denied_port_ranges(mut self) -> Self {
909 self.denied_port_ranges.clear();
910 self
911 }
912
913 pub fn add_allowed_ip_range<Ip: IntoIpRange>(mut self, ip_range: Ip) -> Result<Self, AddError> {
915 let ip_range = ip_range
916 .into_range()
917 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
918 if self.denied_ip_ranges.contains(&ip_range) {
919 return Err(AddError::AlreadyDeniedIpRange(ip_range));
920 } else if self.allowed_ip_ranges.contains(&ip_range) {
921 return Err(AddError::AlreadyAllowedIpRange(ip_range));
922 } else if utils::range_overlaps(&self.allowed_ip_ranges, &ip_range, None)
923 || utils::range_overlaps(&self.denied_ip_ranges, &ip_range, None)
924 {
925 return Err(AddError::Overlaps(format!("{ip_range:?}")));
926 }
927 self.allowed_ip_ranges.push(ip_range);
928 Ok(self)
929 }
930
931 pub fn remove_allowed_ip_range<Ip: IntoIpRange>(
933 mut self,
934 ip_range: Ip,
935 ) -> Result<Self, AddError> {
936 let ip_range = ip_range
937 .into_range()
938 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
939 self.allowed_ip_ranges.retain(|ip| ip != &ip_range);
940 Ok(self)
941 }
942
943 pub fn allowed_ip_ranges<Ip: IntoIpRange>(
945 mut self,
946 ip_ranges: Vec<Ip>,
947 ) -> Result<Self, AddError> {
948 let ip_ranges = ip_ranges
949 .into_iter()
950 .map(|ip| ip.into_range())
951 .collect::<Option<Vec<_>>>()
952 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
953 for (i, ip_range) in ip_ranges.iter().enumerate() {
954 if self.denied_ip_ranges.contains(ip_range) {
955 return Err(AddError::AlreadyDeniedIpRange(ip_range.clone()));
956 } else if utils::range_overlaps(&ip_ranges, ip_range, Some(i))
957 || utils::range_overlaps(&self.denied_ip_ranges, ip_range, None)
958 {
959 return Err(AddError::Overlaps(format!("{ip_range:?}")));
960 }
961 }
962 self.allowed_ip_ranges = ip_ranges;
963 Ok(self)
964 }
965
966 pub fn clear_allowed_ip_ranges(mut self) -> Self {
968 self.allowed_ip_ranges.clear();
969 self
970 }
971
972 pub fn add_denied_ip_range<Ip: IntoIpRange>(mut self, ip_range: Ip) -> Result<Self, AddError> {
974 let ip_range = ip_range
975 .into_range()
976 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
977 if self.allowed_ip_ranges.contains(&ip_range) {
978 return Err(AddError::AlreadyAllowedIpRange(ip_range));
979 } else if self.denied_ip_ranges.contains(&ip_range) {
980 return Err(AddError::AlreadyDeniedIpRange(ip_range));
981 } else if utils::range_overlaps(&self.allowed_ip_ranges, &ip_range, None)
982 || utils::range_overlaps(&self.denied_ip_ranges, &ip_range, None)
983 {
984 return Err(AddError::Overlaps(format!("{ip_range:?}")));
985 }
986 self.denied_ip_ranges.push(ip_range);
987 Ok(self)
988 }
989
990 pub fn remove_denied_ip_range<Ip: IntoIpRange>(
992 mut self,
993 ip_range: Ip,
994 ) -> Result<Self, AddError> {
995 let ip_range = ip_range
996 .into_range()
997 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
998 self.denied_ip_ranges.retain(|ip| ip != &ip_range);
999 Ok(self)
1000 }
1001
1002 pub fn denied_ip_ranges<Ip: IntoIpRange>(
1004 mut self,
1005 ip_ranges: Vec<Ip>,
1006 ) -> Result<Self, AddError> {
1007 let ip_ranges = ip_ranges
1008 .into_iter()
1009 .map(|ip| ip.into_range())
1010 .collect::<Option<Vec<_>>>()
1011 .ok_or_else(|| AddError::InvalidEntity("Invalid IP range".to_string()))?;
1012 for (i, ip_range) in ip_ranges.iter().enumerate() {
1013 if self.allowed_ip_ranges.contains(ip_range) {
1014 return Err(AddError::AlreadyAllowedIpRange(ip_range.clone()));
1015 } else if utils::range_overlaps(&ip_ranges, ip_range, Some(i))
1016 || utils::range_overlaps(&self.allowed_ip_ranges, ip_range, None)
1017 {
1018 return Err(AddError::Overlaps(format!("{ip_range:?}")));
1019 }
1020 }
1021 self.denied_ip_ranges = ip_ranges;
1022 Ok(self)
1023 }
1024
1025 pub fn clear_denied_ip_ranges(mut self) -> Self {
1027 self.denied_ip_ranges.clear();
1028 self
1029 }
1030
1031 pub fn add_static_dns_mapping(
1035 mut self,
1036 host: String,
1037 sock_addr: SocketAddr,
1038 ) -> Result<Self, AddError> {
1039 if utils::authority::is_valid_host(&host) {
1040 if let Entry::Vacant(e) = self.static_dns_mapping.entry(host.clone()) {
1041 e.insert(sock_addr);
1042 Ok(self)
1043 } else {
1044 Err(AddError::AlreadyPresentStaticDnsMapping(host, sock_addr))
1045 }
1046 } else {
1047 Err(AddError::InvalidEntity(host))
1048 }
1049 }
1050
1051 pub fn remove_static_dns_mapping(mut self, host: &str) -> Self {
1055 self.static_dns_mapping.remove(host);
1056 self
1057 }
1058
1059 pub fn static_dns_mappings(
1063 mut self,
1064 mappings: HashMap<String, SocketAddr>,
1065 ) -> Result<Self, AddError> {
1066 for (host, ip) in &mappings {
1067 if utils::authority::is_valid_host(host) {
1068 if self.static_dns_mapping.contains_key(host) {
1069 return Err(AddError::AlreadyPresentStaticDnsMapping(host.clone(), *ip));
1070 }
1071 self.static_dns_mapping.insert(host.to_string(), *ip);
1072 } else {
1073 return Err(AddError::InvalidEntity(host.clone()));
1074 }
1075 }
1076 Ok(self)
1077 }
1078
1079 pub fn clear_static_dns_mappings(mut self) -> Self {
1081 self.static_dns_mapping.clear();
1082 self
1083 }
1084
1085 pub fn add_allowed_header(
1091 mut self,
1092 header: String,
1093 value: Option<String>,
1094 ) -> Result<Self, AddError> {
1095 if self.denied_headers.contains_key(&header) {
1096 Err(AddError::AlreadyDeniedHeader(header, value.clone()))
1097 } else if let Entry::Vacant(e) = self.allowed_headers.entry(header.clone()) {
1098 e.insert(value);
1099 Ok(self)
1100 } else {
1101 Err(AddError::AlreadyAllowedHeader(header, value))
1102 }
1103 }
1104
1105 pub fn remove_allowed_header(mut self, header: &str) -> Self {
1109 self.allowed_headers.remove(header);
1110 self
1111 }
1112
1113 pub fn allowed_headers(
1117 mut self,
1118 headers: HashMap<String, Option<String>>,
1119 ) -> Result<Self, AddError> {
1120 for (header, value) in &headers {
1121 if self.denied_headers.contains_key(header) {
1122 return Err(AddError::AlreadyDeniedHeader(header.clone(), value.clone()));
1123 }
1124 }
1125 self.allowed_headers = headers;
1126 Ok(self)
1127 }
1128
1129 pub fn clear_allowed_headers(mut self) -> Self {
1131 self.allowed_headers.clear();
1132 self
1133 }
1134
1135 pub fn add_denied_header(
1141 mut self,
1142 header: String,
1143 value: Option<String>,
1144 ) -> Result<Self, AddError> {
1145 if self.allowed_headers.contains_key(&header) {
1146 Err(AddError::AlreadyAllowedHeader(header, value.clone()))
1147 } else if let Entry::Vacant(e) = self.denied_headers.entry(header.clone()) {
1148 e.insert(value);
1149 Ok(self)
1150 } else {
1151 Err(AddError::AlreadyDeniedHeader(header, value))
1152 }
1153 }
1154
1155 pub fn remove_denied_header(mut self, header: &str) -> Self {
1159 self.denied_headers.remove(header);
1160 self
1161 }
1162
1163 pub fn denied_headers(
1167 mut self,
1168 headers: HashMap<String, Option<String>>,
1169 ) -> Result<Self, AddError> {
1170 for (header, value) in &headers {
1171 if self.allowed_headers.contains_key(header) {
1172 return Err(AddError::AlreadyAllowedHeader(
1173 header.clone(),
1174 value.clone(),
1175 ));
1176 }
1177 }
1178 self.denied_headers = headers;
1179 Ok(self)
1180 }
1181
1182 pub fn clear_denied_headers(mut self) -> Self {
1184 self.denied_headers.clear();
1185 self
1186 }
1187
1188 pub fn add_allowed_url_path(mut self, url_path: String) -> Result<Self, AddError> {
1192 if self.denied_url_paths.contains(&url_path)
1193 || self.denied_url_paths_router.at(&url_path).is_ok()
1194 {
1195 Err(AddError::AlreadyDeniedUrlPath(url_path))
1196 } else if self.allowed_url_paths.contains(&url_path)
1197 || self.allowed_url_paths_router.at(&url_path).is_ok()
1198 {
1199 Err(AddError::AlreadyAllowedUrlPath(url_path))
1200 } else {
1201 self.allowed_url_paths.push(url_path.clone());
1202 self.allowed_url_paths_router
1203 .insert(url_path, ())
1204 .map_err(|_| AddError::InvalidEntity("Invalid URL path".to_string()))?;
1205 Ok(self)
1206 }
1207 }
1208
1209 pub fn remove_allowed_url_path(mut self, url_path: &str) -> Self {
1213 self.allowed_url_paths.retain(|p| p != url_path);
1214 self.allowed_url_paths_router = {
1215 let mut router = Router::new();
1216 for url_path in &self.allowed_url_paths {
1217 router
1218 .insert(url_path.clone(), ())
1219 .expect("failed to insert url path");
1220 }
1221 router
1222 };
1223 self
1224 }
1225
1226 pub fn allowed_url_paths(mut self, url_paths: Vec<String>) -> Result<Self, AddError> {
1230 for url_path in &url_paths {
1231 if self.denied_url_paths.contains(url_path)
1232 || self.denied_url_paths_router.at(url_path).is_ok()
1233 {
1234 return Err(AddError::AlreadyDeniedUrlPath(url_path.clone()));
1235 }
1236 }
1237 self.allowed_url_paths_router = Router::new();
1238 for url_path in &url_paths {
1239 self.allowed_url_paths_router
1240 .insert(url_path.clone(), ())
1241 .map_err(|_| AddError::InvalidEntity(format!("Invalid URL path: {url_path}")))?;
1242 }
1243 self.allowed_url_paths = url_paths;
1244 Ok(self)
1245 }
1246
1247 pub fn clear_allowed_url_paths(mut self) -> Self {
1249 self.allowed_url_paths.clear();
1250 self.allowed_url_paths_router = Router::new();
1251 self
1252 }
1253
1254 pub fn add_denied_url_path(mut self, url_path: String) -> Result<Self, AddError> {
1258 if self.allowed_url_paths.contains(&url_path)
1259 || self.allowed_url_paths_router.at(&url_path).is_ok()
1260 {
1261 Err(AddError::AlreadyAllowedUrlPath(url_path))
1262 } else if self.denied_url_paths.contains(&url_path)
1263 || self.denied_url_paths_router.at(&url_path).is_ok()
1264 {
1265 Err(AddError::AlreadyDeniedUrlPath(url_path))
1266 } else {
1267 self.denied_url_paths.push(url_path.clone());
1268 self.denied_url_paths_router
1269 .insert(url_path, ())
1270 .map_err(|_| AddError::InvalidEntity("Invalid URL path".to_string()))?;
1271 Ok(self)
1272 }
1273 }
1274
1275 pub fn remove_denied_url_path(mut self, url_path: &str) -> Self {
1279 self.denied_url_paths.retain(|p| p != url_path);
1280 self.denied_url_paths_router = {
1281 let mut router = Router::new();
1282 for url_path in &self.denied_url_paths {
1283 router
1284 .insert(url_path.clone(), ())
1285 .expect("failed to insert url path");
1286 }
1287 router
1288 };
1289 self
1290 }
1291
1292 pub fn denied_url_paths(mut self, url_paths: Vec<String>) -> Result<Self, AddError> {
1296 for url_path in &url_paths {
1297 if self.allowed_url_paths.contains(url_path)
1298 || self.allowed_url_paths_router.at(url_path).is_ok()
1299 {
1300 return Err(AddError::AlreadyAllowedUrlPath(url_path.clone()));
1301 }
1302 }
1303 self.denied_url_paths_router = Router::new();
1304 for url_path in &url_paths {
1305 self.denied_url_paths_router
1306 .insert(url_path.clone(), ())
1307 .map_err(|_| AddError::InvalidEntity(format!("Invalid URL path: {url_path}")))?;
1308 }
1309 self.denied_url_paths = url_paths;
1310 Ok(self)
1311 }
1312
1313 pub fn clear_denied_url_paths(mut self) -> Self {
1315 self.denied_url_paths.clear();
1316 self.denied_url_paths_router = Router::new();
1317 self
1318 }
1319
1320 pub fn build(self) -> HttpAcl {
1322 self.build_full(None)
1323 }
1324
1325 pub fn build_full(self, validate_fn: Option<ValidateFn>) -> HttpAcl {
1327 HttpAcl {
1328 allow_http: self.allow_http,
1329 allow_https: self.allow_https,
1330 allowed_methods: self.allowed_methods.into_iter().collect(),
1331 denied_methods: self.denied_methods.into_iter().collect(),
1332 allowed_hosts: self
1333 .allowed_hosts
1334 .into_iter()
1335 .map(|x| x.into_boxed_str())
1336 .collect(),
1337 denied_hosts: self
1338 .denied_hosts
1339 .into_iter()
1340 .map(|x| x.into_boxed_str())
1341 .collect(),
1342 allowed_port_ranges: self.allowed_port_ranges.into_boxed_slice(),
1343 denied_port_ranges: self.denied_port_ranges.into_boxed_slice(),
1344 allowed_ip_ranges: self.allowed_ip_ranges.into_boxed_slice(),
1345 denied_ip_ranges: self.denied_ip_ranges.into_boxed_slice(),
1346 allowed_headers: self
1347 .allowed_headers
1348 .into_iter()
1349 .map(|(k, v)| (k.into_boxed_str(), v.map(|s| s.into_boxed_str())))
1350 .collect(),
1351 denied_headers: self
1352 .denied_headers
1353 .into_iter()
1354 .map(|(k, v)| (k.into_boxed_str(), v.map(|s| s.into_boxed_str())))
1355 .collect(),
1356 allowed_url_paths_router: self.allowed_url_paths_router,
1357 denied_url_paths_router: self.denied_url_paths_router,
1358 static_dns_mapping: self
1359 .static_dns_mapping
1360 .into_iter()
1361 .map(|(k, v)| (k.into_boxed_str(), v))
1362 .collect(),
1363 validate_fn,
1364 allow_non_global_ip_ranges: self.allow_non_global_ip_ranges,
1365 method_acl_default: self.method_acl_default,
1366 host_acl_default: self.host_acl_default,
1367 port_acl_default: self.port_acl_default,
1368 ip_acl_default: self.ip_acl_default,
1369 header_acl_default: self.header_acl_default,
1370 url_path_acl_default: self.url_path_acl_default,
1371 }
1372 }
1373
1374 pub fn try_build_full(mut self, validate_fn: Option<ValidateFn>) -> Result<HttpAcl, AddError> {
1377 if !utils::has_unique_elements(&self.allowed_methods) {
1378 return Err(AddError::NotUnique(
1379 "Allowed methods must be unique.".to_string(),
1380 ));
1381 }
1382 for method in &self.allowed_methods {
1383 if self.denied_methods.contains(method) {
1384 return Err(AddError::BothAllowedAndDenied(format!(
1385 "Method `{}`",
1386 method.as_str()
1387 )));
1388 }
1389 }
1390 if !utils::has_unique_elements(&self.denied_methods) {
1391 return Err(AddError::NotUnique(
1392 "Denied methods must be unique.".to_string(),
1393 ));
1394 }
1395 for method in &self.denied_methods {
1396 if self.allowed_methods.contains(method) {
1397 return Err(AddError::BothAllowedAndDenied(format!(
1398 "Method `{}`",
1399 method.as_str()
1400 )));
1401 }
1402 }
1403 if !utils::has_unique_elements(&self.allowed_hosts) {
1404 return Err(AddError::NotUnique(
1405 "Allowed hosts must be unique.".to_string(),
1406 ));
1407 }
1408 for host in &self.allowed_hosts {
1409 if !utils::authority::is_valid_host(host) {
1410 return Err(AddError::InvalidEntity(host.to_string()));
1411 }
1412 if self.denied_hosts.contains(host) {
1413 return Err(AddError::BothAllowedAndDenied(format!("Host `{host}`")));
1414 }
1415 }
1416 if !utils::has_unique_elements(&self.denied_hosts) {
1417 return Err(AddError::NotUnique(
1418 "Denied hosts must be unique.".to_string(),
1419 ));
1420 }
1421 for host in &self.denied_hosts {
1422 if !utils::authority::is_valid_host(host) {
1423 return Err(AddError::InvalidEntity(host.to_string()));
1424 }
1425 if self.allowed_hosts.contains(host) {
1426 return Err(AddError::BothAllowedAndDenied(format!("Host `{host}`")));
1427 }
1428 }
1429 if !utils::has_unique_elements(&self.allowed_port_ranges) {
1430 return Err(AddError::NotUnique(
1431 "Allowed port ranges must be unique.".to_string(),
1432 ));
1433 }
1434 if utils::has_overlapping_ranges(&self.allowed_port_ranges) {
1435 return Err(AddError::Overlaps(
1436 "Allowed port ranges must not overlap.".to_string(),
1437 ));
1438 }
1439 for port_range in &self.allowed_port_ranges {
1440 if self.denied_port_ranges.contains(port_range) {
1441 return Err(AddError::BothAllowedAndDenied(format!(
1442 "Port range `{port_range:?}`"
1443 )));
1444 }
1445 }
1446 if !utils::has_unique_elements(&self.denied_port_ranges) {
1447 return Err(AddError::NotUnique(
1448 "Denied port ranges must be unique.".to_string(),
1449 ));
1450 }
1451 if utils::has_overlapping_ranges(&self.denied_port_ranges) {
1452 return Err(AddError::Overlaps(
1453 "Denied port ranges must not overlap.".to_string(),
1454 ));
1455 }
1456 for port_range in &self.denied_port_ranges {
1457 if self.allowed_port_ranges.contains(port_range) {
1458 return Err(AddError::BothAllowedAndDenied(format!(
1459 "Port range `{port_range:?}`"
1460 )));
1461 }
1462 }
1463 if !utils::has_unique_elements(&self.allowed_ip_ranges) {
1464 return Err(AddError::NotUnique(
1465 "Allowed IP ranges must be unique.".to_string(),
1466 ));
1467 }
1468 if utils::has_overlapping_ranges(&self.allowed_ip_ranges) {
1469 return Err(AddError::Overlaps(
1470 "Allowed IP ranges must not overlap.".to_string(),
1471 ));
1472 }
1473 for ip_range in &self.allowed_ip_ranges {
1474 if self.denied_ip_ranges.contains(ip_range) {
1475 return Err(AddError::BothAllowedAndDenied(format!(
1476 "IP range `{ip_range:?}`"
1477 )));
1478 }
1479
1480 if (!utils::ip::is_global_ip(ip_range.start())
1481 || !utils::ip::is_global_ip(ip_range.end()))
1482 && !self.allow_non_global_ip_ranges
1483 {
1484 return Err(AddError::NonGlobalIpRange(ip_range.clone()));
1485 }
1486 }
1487 if !utils::has_unique_elements(&self.denied_ip_ranges) {
1488 return Err(AddError::NotUnique(
1489 "Denied IP ranges must be unique.".to_string(),
1490 ));
1491 }
1492 if utils::has_overlapping_ranges(&self.denied_ip_ranges) {
1493 return Err(AddError::Overlaps(
1494 "Denied IP ranges must not overlap.".to_string(),
1495 ));
1496 }
1497 for ip_range in &self.denied_ip_ranges {
1498 if self.allowed_ip_ranges.contains(ip_range) {
1499 return Err(AddError::BothAllowedAndDenied(format!(
1500 "IP range `{ip_range:?}`"
1501 )));
1502 }
1503
1504 if (!utils::ip::is_global_ip(ip_range.start())
1505 || !utils::ip::is_global_ip(ip_range.end()))
1506 && !self.allow_non_global_ip_ranges
1507 {
1508 return Err(AddError::NonGlobalIpRange(ip_range.clone()));
1509 }
1510 }
1511 if !utils::has_unique_elements(&self.static_dns_mapping) {
1512 return Err(AddError::NotUnique(
1513 "Static DNS mapping must be unique.".to_string(),
1514 ));
1515 }
1516 for host in self.static_dns_mapping.keys() {
1517 if !utils::authority::is_valid_host(host) {
1518 return Err(AddError::InvalidEntity(host.to_string()));
1519 }
1520 }
1521 if !utils::has_unique_elements(&self.allowed_url_paths) {
1522 return Err(AddError::NotUnique(
1523 "Allowed URL paths must be unique.".to_string(),
1524 ));
1525 }
1526 for url_path in &self.allowed_url_paths {
1527 if self.denied_url_paths.contains(url_path)
1528 || self.denied_url_paths_router.at(url_path).is_ok()
1529 {
1530 return Err(AddError::BothAllowedAndDenied(format!(
1531 "URL path `{url_path}`"
1532 )));
1533 } else if self.allowed_url_paths_router.at(url_path).is_err() {
1534 self.allowed_url_paths_router
1535 .insert(url_path.clone(), ())
1536 .map_err(|_| {
1537 AddError::InvalidEntity(format!(
1538 "Failed to insert allowed URL path `{url_path}`."
1539 ))
1540 })?;
1541 }
1542 }
1543 if !utils::has_unique_elements(&self.denied_url_paths) {
1544 return Err(AddError::NotUnique(
1545 "Denied URL paths must be unique.".to_string(),
1546 ));
1547 }
1548 for url_path in &self.denied_url_paths {
1549 if self.allowed_url_paths.contains(url_path)
1550 || self.allowed_url_paths_router.at(url_path).is_ok()
1551 {
1552 return Err(AddError::BothAllowedAndDenied(format!(
1553 "URL path `{url_path}`"
1554 )));
1555 } else if self.denied_url_paths_router.at(url_path).is_err() {
1556 self.denied_url_paths_router
1557 .insert(url_path.clone(), ())
1558 .map_err(|_| {
1559 AddError::InvalidEntity(format!(
1560 "Failed to insert denied URL path `{url_path}`."
1561 ))
1562 })?;
1563 }
1564 }
1565 Ok(self.build_full(validate_fn))
1566 }
1567
1568 pub fn try_build(self) -> Result<HttpAcl, AddError> {
1571 self.try_build_full(None)
1572 }
1573}