Implement glob pattern hostnames
no wildcard certificates: one certificate per matching hostname that actually recieves requests
This commit is contained in:
parent
11c6f0b1c2
commit
098a6cf2cd
5 changed files with 48 additions and 7 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -472,6 +472,12 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.1.26"
|
||||
|
@ -1880,6 +1886,7 @@ dependencies = [
|
|||
"envy",
|
||||
"futures 0.3.18",
|
||||
"futures-util",
|
||||
"glob",
|
||||
"http 0.2.5",
|
||||
"hyper 0.14.15",
|
||||
"hyper-reverse-proxy",
|
||||
|
|
|
@ -31,3 +31,4 @@ hyper-reverse-proxy = "0.4"
|
|||
unicase = "2"
|
||||
lazy_static = "1.4"
|
||||
structopt = "0.3"
|
||||
glob = "0.3"
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustls::sign::CertifiedKey;
|
|||
|
||||
use crate::cert::{Cert, CertSer};
|
||||
use crate::consul::*;
|
||||
use crate::proxy_config::ProxyConfig;
|
||||
use crate::proxy_config::*;
|
||||
|
||||
pub struct CertStore {
|
||||
consul: Consul,
|
||||
|
@ -39,11 +39,13 @@ impl CertStore {
|
|||
|
||||
let proxy_config: Arc<ProxyConfig> = rx_proxy_config.borrow().clone();
|
||||
for ent in proxy_config.entries.iter() {
|
||||
domains.insert(ent.host.clone());
|
||||
if let HostDescription::Hostname(domain) = &ent.host {
|
||||
domains.insert(domain.clone());
|
||||
}
|
||||
}
|
||||
info!("Ensuring we have certs for domains: {:?}", domains);
|
||||
|
||||
for dom in domains.iter() {
|
||||
info!("Ensuring we have certs for domains: {:?}", domains);
|
||||
if let Err(e) = self.get_cert(dom).await {
|
||||
warn!("Error get_cert {}: {}", dom, e);
|
||||
}
|
||||
|
@ -58,7 +60,7 @@ impl CertStore {
|
|||
.borrow()
|
||||
.entries
|
||||
.iter()
|
||||
.any(|ent| ent.host == domain)
|
||||
.any(|ent| ent.host.matches(domain))
|
||||
{
|
||||
bail!("Domain {} should not have a TLS certificate.", domain);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ async fn handle(
|
|||
.entries
|
||||
.iter()
|
||||
.filter(|ent| {
|
||||
ent.host == host
|
||||
ent.host.matches(host)
|
||||
&& ent
|
||||
.path_prefix
|
||||
.as_ref()
|
||||
|
|
|
@ -15,11 +15,34 @@ use crate::consul::*;
|
|||
|
||||
// ---- Extract proxy config from Consul catalog ----
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HostDescription {
|
||||
Hostname(String),
|
||||
Pattern(glob::Pattern),
|
||||
}
|
||||
|
||||
impl HostDescription {
|
||||
fn new(desc: &str) -> Result<Self> {
|
||||
if desc.chars().any(|x| matches!(x, '*' | '?' | '[' | ']')) {
|
||||
Ok(Self::Pattern(glob::Pattern::new(desc)?))
|
||||
} else {
|
||||
Ok(Self::Hostname(desc.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matches(&self, v: &str) -> bool {
|
||||
match self {
|
||||
Self::Pattern(p) => p.matches(v),
|
||||
Self::Hostname(s) => s == v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProxyEntry {
|
||||
pub target_addr: SocketAddr,
|
||||
|
||||
pub host: String,
|
||||
pub host: HostDescription,
|
||||
pub path_prefix: Option<String>,
|
||||
pub priority: u32,
|
||||
pub add_headers: Vec<(String, String)>,
|
||||
|
@ -65,9 +88,17 @@ fn parse_tricot_tag(
|
|||
_ => 100,
|
||||
};
|
||||
|
||||
let host = match HostDescription::new(host) {
|
||||
Ok(h) => h,
|
||||
Err(e) => {
|
||||
warn!("Invalid hostname pattern {}: {}", host, e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some(ProxyEntry {
|
||||
target_addr,
|
||||
host: host.to_string(),
|
||||
host,
|
||||
path_prefix,
|
||||
priority,
|
||||
add_headers: add_headers.to_vec(),
|
||||
|
|
Loading…
Reference in a new issue