Turn match in restriction config into a list

This commit is contained in:
Σrebe - Romain GERARD 2024-04-30 22:21:47 +02:00
parent 1e07eb7b2a
commit 368f6657fd
No known key found for this signature in database
GPG key ID: 7A42B4B97E0332F4
5 changed files with 105 additions and 39 deletions

View file

@ -1,11 +1,18 @@
use crate::restrictions::types::{default_cidr, default_host};
use regex::Regex;
use ipnet::IpNet;
use std::fs::File;
use std::io::BufReader;
use std::net::IpAddr;
use std::ops::RangeInclusive;
use std::path::Path;
use std::str::FromStr;
use std::vec;
use regex::Regex;
use types::RestrictionsRules;
use crate::restrictions::types::{default_cidr, default_host};
pub mod types;
impl RestrictionsRules {
@ -18,41 +25,68 @@ impl RestrictionsRules {
path_prefixes: &[String],
restrict_to: &[(String, u16)],
) -> anyhow::Result<RestrictionsRules> {
let mut tunnels_restrictions = if restrict_to.is_empty() {
let tunnels_restrictions = if restrict_to.is_empty() {
let r = types::AllowConfig::Tunnel(types::AllowTunnelConfig {
protocol: vec![],
port: vec![],
host: default_host(),
cidr: default_cidr(),
});
vec![r]
let reverse_tunnel = types::AllowConfig::ReverseTunnel(types::AllowReverseTunnelConfig {
protocol: vec![],
port: vec![],
cidr: default_cidr(),
});
vec![r, reverse_tunnel]
} else {
restrict_to
.iter()
.map(|(host, port)| {
let reg = Regex::new(&format!("^{}$", regex::escape(host)))?;
Ok(types::AllowConfig::Tunnel(types::AllowTunnelConfig {
protocol: vec![],
port: vec![RangeInclusive::new(*port, *port)],
host: reg,
cidr: default_cidr(),
}))
let tunnels = if let Ok(ip) = IpAddr::from_str(host) {
vec![
types::AllowConfig::Tunnel(types::AllowTunnelConfig {
protocol: vec![],
port: vec![RangeInclusive::new(*port, *port)],
host: reg,
cidr: default_cidr(),
}),
types::AllowConfig::ReverseTunnel(types::AllowReverseTunnelConfig {
protocol: vec![],
port: vec![RangeInclusive::new(*port, *port)],
cidr: vec![IpNet::new(ip, if ip.is_ipv4() { 32 } else { 128 })?],
}),
]
} else {
vec![
types::AllowConfig::Tunnel(types::AllowTunnelConfig {
protocol: vec![],
port: vec![RangeInclusive::new(*port, *port)],
host: reg,
cidr: default_cidr(),
}),
types::AllowConfig::ReverseTunnel(types::AllowReverseTunnelConfig {
protocol: vec![],
port: vec![],
cidr: default_cidr(),
}),
]
};
Ok(tunnels)
})
.collect::<Result<Vec<_>, anyhow::Error>>()?
.into_iter()
.flatten()
.collect()
};
tunnels_restrictions.push(types::AllowConfig::ReverseTunnel(types::AllowReverseTunnelConfig {
protocol: vec![],
port: vec![],
cidr: default_cidr(),
}));
let restrictions = if path_prefixes.is_empty() {
// if no path prefixes are provided, we allow all
let reg = Regex::new(".").unwrap();
let r = types::RestrictionConfig {
name: "Allow All".to_string(),
r#match: types::MatchConfig::PathPrefix(reg),
r#match: vec![types::MatchConfig::Any],
allow: tunnels_restrictions,
};
vec![r]
@ -63,7 +97,7 @@ impl RestrictionsRules {
let reg = Regex::new(&format!("^{}$", regex::escape(path_prefix)))?;
Ok(types::RestrictionConfig {
name: format!("Allow path prefix {}", path_prefix),
r#match: types::MatchConfig::PathPrefix(reg),
r#match: vec![types::MatchConfig::PathPrefix(reg)],
allow: tunnels_restrictions.clone(),
})
})

View file

@ -12,7 +12,8 @@ pub struct RestrictionsRules {
#[derive(Debug, Clone, Deserialize)]
pub struct RestrictionConfig {
pub name: String,
pub r#match: MatchConfig,
#[serde(deserialize_with = "deserialize_non_empty_vec")]
pub r#match: Vec<MatchConfig>,
pub allow: Vec<AllowConfig>,
}
@ -109,6 +110,19 @@ where
Ok(ranges)
}
fn deserialize_non_empty_vec<'de, D, T>(d: D) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
let vec = <Vec<T>>::deserialize(d)?;
if vec.is_empty() {
Err(serde::de::Error::custom("List must not be empty"))
} else {
Ok(vec)
}
}
impl From<&LocalProtocol> for ReverseTunnelConfigProtocol {
fn from(value: &LocalProtocol) -> Self {
match value {