From 04bdd029fefbce08184c12809b5d6e4bf2a12fa1 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 30 Dec 2021 20:42:56 +0100 Subject: [PATCH] Add TLS support for Consul --- Cargo.lock | 337 +++++++++++------------------------------- Cargo.toml | 2 +- src/config/options.rs | 6 + src/config/runtime.rs | 32 +++- src/consul.rs | 18 ++- src/consul_actor.rs | 5 +- src/diplonat.rs | 2 +- 7 files changed, 145 insertions(+), 257 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de22689..73e1e76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,12 +67,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bumpalo" version = "3.2.0" @@ -91,15 +85,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - [[package]] name = "c_linked_list" version = "1.1.1" @@ -108,9 +93,9 @@ checksum = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" [[package]] name = "cc" -version = "1.0.50" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -124,22 +109,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "core-foundation" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - [[package]] name = "diplonat" version = "0.1.0" @@ -197,21 +166,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -345,17 +299,6 @@ dependencies = [ "libc", ] -[[package]] -name = "getrandom" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.3" @@ -364,7 +307,7 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -469,16 +412,16 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "bytes 1.1.0", + "http", "hyper", - "native-tls", + "rustls", "tokio", - "tokio-native-tls", + "tokio-rustls", ] [[package]] @@ -504,7 +447,7 @@ dependencies = [ "http", "hyper", "log", - "rand 0.8.4", + "rand", "tokio", "url", "xmltree", @@ -642,31 +585,13 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "native-tls" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" -dependencies = [ - "lazy_static 1.4.0", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nix" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d95c5fa8b641c10ad0b8887454ebaafa3c92b5cd5350f8fc693adafd178e7b" dependencies = [ - "bitflags 0.4.0", + "bitflags", "cfg-if 0.1.10", "libc", "rustc_version", @@ -699,39 +624,6 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" -[[package]] -name = "openssl" -version = "0.10.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" -dependencies = [ - "bitflags 1.3.2", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-sys", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" - -[[package]] -name = "openssl-sys" -version = "0.9.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "percent-encoding" version = "2.1.0" @@ -790,12 +682,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" - [[package]] name = "ppv-lite86" version = "0.2.15" @@ -853,19 +739,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.14", - "libc", - "rand_chacha 0.2.1", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - [[package]] name = "rand" version = "0.8.4" @@ -873,19 +746,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -dependencies = [ - "c2-chacha", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] @@ -895,16 +758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.14", + "rand_core", ] [[package]] @@ -913,16 +767,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -931,15 +776,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core 0.6.3", + "rand_core", ] -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" - [[package]] name = "regex" version = "0.2.11" @@ -980,15 +819,6 @@ version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -dependencies = [ - "winapi 0.3.8", -] - [[package]] name = "reqwest" version = "0.11.8" @@ -1003,20 +833,21 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "lazy_static 1.4.0", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-native-tls", + "tokio-rustls", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1024,6 +855,21 @@ dependencies = [ "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi 0.3.8", +] + [[package]] name = "rustc_version" version = "0.1.7" @@ -1033,6 +879,27 @@ dependencies = [ "semver", ] +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.2" @@ -1040,36 +907,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] -name = "schannel" -version = "0.1.17" +name = "sct" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "lazy_static 1.4.0", - "winapi 0.3.8", -] - -[[package]] -name = "security-framework" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" -dependencies = [ - "core-foundation-sys", - "libc", + "ring", + "untrusted", ] [[package]] @@ -1154,6 +998,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "syn" version = "1.0.83" @@ -1165,20 +1015,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "rand 0.7.3", - "redox_syscall", - "remove_dir_all", - "winapi 0.3.8", -] - [[package]] name = "termcolor" version = "1.1.0" @@ -1234,13 +1070,14 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.0" +name = "tokio-rustls" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ - "native-tls", + "rustls", "tokio", + "webpki", ] [[package]] @@ -1319,6 +1156,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -1337,12 +1180,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" -[[package]] -name = "vcpkg" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" - [[package]] name = "void" version = "1.0.2" @@ -1359,12 +1196,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -1447,6 +1278,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "wildmatch" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index fe65969..f3c6f11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ iptables = "0.2.2" log = "0.4" pretty_env_logger = "0.4" regex = "1" -reqwest = { version = "0.11", features = ["json"] } +reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls-manual-roots" ] } serde = { version = "1.0.107", features = ["derive"] } serde-lexpr = "0.1.1" serde_json = "1.0.53" diff --git a/src/config/options.rs b/src/config/options.rs index f62d14c..7334083 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -37,6 +37,12 @@ pub struct ConfigOptsConsul { pub node_name: Option, /// Consul's REST URL [default: "http://127.0.0.1:8500"] pub url: Option, + /// Consul's CA certificate [default: None] + pub ca_cert: Option, + /// Consul's client certificate [default: None] + pub client_cert: Option, + /// Consul's client key [default: None] + pub client_key: Option, } /// Model of all potential configuration options diff --git a/src/config/runtime.rs b/src/config/runtime.rs index a1582e4..cc80b0d 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<(reqwest::Certificate, reqwest::Identity)>, } #[derive(Debug)] @@ -77,7 +80,32 @@ 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.ca_cert, &opts.client_cert, &opts.client_key) { + (Some(ca_cert), Some(client_cert), Some(client_key)) => { + let mut ca_cert_buf = vec![]; + File::open(ca_cert)?.read_to_end(&mut ca_cert_buf)?; + let cert = reqwest::Certificate::from_pem(&ca_cert_buf[..])?; + + 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, ident)) + } + (None, 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..4677931 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, @@ -20,10 +22,20 @@ pub struct Consul { } impl Consul { - pub fn new(url: &str) -> Self { + pub fn new(config: &RuntimeConfigConsul) -> Self { + let client = if let Some((ca, ident)) = config.tls.clone() { + reqwest::Client::builder() + .use_rustls_tls() + .add_root_certificate(ca) + .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) -> 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?;