aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config/options.rs9
-rw-r--r--src/config/runtime.rs37
-rw-r--r--src/consul.rs33
-rw-r--r--src/consul_actor.rs5
-rw-r--r--src/diplonat.rs2
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?;