diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config/options.rs | 9 | ||||
-rw-r--r-- | src/config/runtime.rs | 37 | ||||
-rw-r--r-- | src/consul.rs | 33 | ||||
-rw-r--r-- | src/consul_actor.rs | 5 | ||||
-rw-r--r-- | src/diplonat.rs | 2 |
5 files changed, 78 insertions, 8 deletions
diff --git a/src/config/options.rs b/src/config/options.rs index f62d14c..793838a 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -37,6 +37,15 @@ pub struct ConfigOptsConsul { pub node_name: Option<String>, /// Consul's REST URL [default: "http://127.0.0.1:8500"] pub url: Option<String>, + /// Consul's CA certificate [default: None] + pub ca_cert: Option<String>, + /// Skip TLS verification for Consul server [default: false] + #[serde(default)] + pub tls_skip_verify: bool, + /// Consul's client certificate [default: None] + pub client_cert: Option<String>, + /// Consul's client key [default: None] + pub client_key: Option<String>, } /// Model of all potential configuration options diff --git a/src/config/runtime.rs b/src/config/runtime.rs index a1582e4..2e7b573 100644 --- a/src/config/runtime.rs +++ b/src/config/runtime.rs @@ -1,6 +1,8 @@ +use std::fs::File; +use std::io::Read; use std::time::Duration; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use crate::config::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul}; @@ -18,6 +20,7 @@ pub struct RuntimeConfigAcme { pub struct RuntimeConfigConsul { pub node_name: String, pub url: String, + pub tls: Option<(Option<reqwest::Certificate>, bool, reqwest::Identity)>, } #[derive(Debug)] @@ -77,7 +80,37 @@ impl RuntimeConfigConsul { .expect("'DIPLONAT_CONSUL_NODE_NAME' environment variable is required"); let url = opts.url.unwrap_or(super::CONSUL_URL.to_string()); - Ok(Self { node_name, url }) + let tls = match (&opts.client_cert, &opts.client_key) { + (Some(client_cert), Some(client_key)) => { + let cert = match &opts.ca_cert { + Some(ca_cert) => { + let mut ca_cert_buf = vec![]; + File::open(ca_cert)?.read_to_end(&mut ca_cert_buf)?; + Some(reqwest::Certificate::from_pem(&ca_cert_buf[..])?) + } + None => None, + }; + + let mut client_cert_buf = vec![]; + File::open(client_cert)?.read_to_end(&mut client_cert_buf)?; + + let mut client_key_buf = vec![]; + File::open(client_key)?.read_to_end(&mut client_key_buf)?; + + let ident = + reqwest::Identity::from_pem(&[&client_cert_buf[..], &client_key_buf[..]].concat()[..])?; + + Some((cert, opts.tls_skip_verify, ident)) + } + (None, None) => None, + _ => bail!("Incomplete TLS configuration parameters"), + }; + + Ok(Self { + node_name, + url, + tls, + }) } } diff --git a/src/consul.rs b/src/consul.rs index 4e4f79c..c7ac2b6 100644 --- a/src/consul.rs +++ b/src/consul.rs @@ -3,6 +3,8 @@ use std::collections::HashMap; use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; +use crate::config::RuntimeConfigConsul; + #[derive(Serialize, Deserialize, Debug)] pub struct ServiceEntry { pub Tags: Vec<String>, @@ -20,10 +22,35 @@ pub struct Consul { } impl Consul { - pub fn new(url: &str) -> Self { + pub fn new(config: &RuntimeConfigConsul) -> Self { + let client = if let Some((ca, skip_verify, ident)) = config.tls.clone() { + if skip_verify { + reqwest::Client::builder() + .use_rustls_tls() + .danger_accept_invalid_certs(true) + .identity(ident) + .build() + .expect("Unable to build reqwest client") + } else if let Some(ca) = ca { + reqwest::Client::builder() + .use_rustls_tls() + .add_root_certificate(ca) + .identity(ident) + .build() + .expect("Unable to build reqwest client") + } else { + reqwest::Client::builder() + .use_rustls_tls() + .identity(ident) + .build() + .expect("Unable to build reqwest client") + } + } else { + reqwest::Client::new() + }; return Self { - client: reqwest::Client::new(), - url: url.to_string(), + client, + url: config.url.clone(), idx: None, }; } diff --git a/src/consul_actor.rs b/src/consul_actor.rs index 61789ca..8b722b6 100644 --- a/src/consul_actor.rs +++ b/src/consul_actor.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; use serde_lexpr::{error, from_str}; use tokio::{sync::watch, time::sleep}; +use crate::config::RuntimeConfigConsul; use crate::{consul, messages}; #[derive(Serialize, Deserialize, Debug)] @@ -74,14 +75,14 @@ fn to_open_ports(params: &Vec<DiplonatConsul>) -> messages::PublicExposedPorts { } impl ConsulActor { - pub fn new(url: &str, node: &str) -> Self { + pub fn new(config: &RuntimeConfigConsul, node: &str) -> Self { let (tx, rx) = watch::channel(messages::PublicExposedPorts { tcp_ports: HashSet::new(), udp_ports: HashSet::new(), }); return Self { - consul: consul::Consul::new(url), + consul: consul::Consul::new(config), rx_open_ports: rx, tx_open_ports: tx, node: node.to_string(), diff --git a/src/diplonat.rs b/src/diplonat.rs index 397ba82..22ebd6e 100644 --- a/src/diplonat.rs +++ b/src/diplonat.rs @@ -16,7 +16,7 @@ impl Diplonat { let rt_cfg = ConfigOpts::from_env()?; println!("{:#?}", rt_cfg); - let ca = ConsulActor::new(&rt_cfg.consul.url, &rt_cfg.consul.node_name); + let ca = ConsulActor::new(&rt_cfg.consul, &rt_cfg.consul.node_name); let fw = FirewallActor::new(rt_cfg.firewall.refresh_time, &ca.rx_open_ports).await?; |