From bcc185df400f0b459d78d6bdd3084ef5b6ac5e8a Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Thu, 30 Dec 2021 20:08:10 +0100 Subject: [PATCH] Add support for Consul TLS --- Cargo.lock | 128 ++------------------------------------------------ Cargo.toml | 2 +- src/consul.rs | 39 +++++++++++++-- src/main.rs | 22 ++++++++- 4 files changed, 61 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c05bdc0..9d35b3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -830,19 +830,6 @@ dependencies = [ "tokio-rustls", ] -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes 1.1.0", - "hyper 0.14.15", - "native-tls", - "tokio 1.14.0", - "tokio-native-tls", -] - [[package]] name = "idna" version = "0.2.3" @@ -1039,24 +1026,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "native-tls" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "net2" version = "0.2.37" @@ -1174,7 +1143,7 @@ dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", - "redox_syscall 0.1.57", + "redox_syscall", "rustc_version", "smallvec", "winapi 0.3.9", @@ -1215,12 +1184,6 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1a3ea4f0dd7f1f3e512cf97bf100819aa547f36a6eccac8dbaae839eb92363e" -[[package]] -name = "ppv-lite86" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" - [[package]] name = "pretty_env_logger" version = "0.4.0" @@ -1304,46 +1267,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "rcgen" version = "0.8.14" @@ -1362,15 +1285,6 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" version = "1.5.4" @@ -1388,15 +1302,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "reqwest" version = "0.11.7" @@ -1411,20 +1316,21 @@ dependencies = [ "http 0.2.5", "http-body 0.4.4", "hyper 0.14.15", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "lazy_static", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "rustls 0.20.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio 1.14.0", - "tokio-native-tls", + "tokio-rustls", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1797,20 +1703,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "rand", - "redox_syscall 0.2.10", - "remove_dir_all", - "winapi 0.3.9", -] - [[package]] name = "termcolor" version = "1.1.2" @@ -1982,16 +1874,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" -dependencies = [ - "native-tls", - "tokio 1.14.0", -] - [[package]] name = "tokio-reactor" version = "0.1.12" diff --git a/Cargo.toml b/Cargo.toml index 0d1374f..d970836 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3" 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_json = "1.0.53" tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] } diff --git a/src/consul.rs b/src/consul.rs index ee1935c..8eafcc2 100644 --- a/src/consul.rs +++ b/src/consul.rs @@ -1,4 +1,6 @@ use std::collections::HashMap; +use std::fs::File; +use std::io::Read; use anyhow::Result; use bytes::Bytes; @@ -6,6 +8,13 @@ use log::*; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; +pub struct ConsulConfig { + pub addr: String, + pub ca_cert: Option, + pub client_cert: Option, + pub client_key: Option, +} + // ---- Watch and retrieve Consul catalog ---- // #[derive(Serialize, Deserialize, Debug)] @@ -76,13 +85,33 @@ pub struct Consul { } impl Consul { - pub fn new(url: &str, kv_prefix: &str, local_node: &str) -> Self { - return Self { - client: reqwest::Client::new(), - url: url.trim_end_matches('/').to_string(), + pub fn new(config: ConsulConfig, kv_prefix: &str, local_node: &str) -> Result { + let client = match (&config.ca_cert, &config.client_cert, &config.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 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)?; + + reqwest::Client::builder() + .use_rustls_tls() + .add_root_certificate(reqwest::Certificate::from_pem(&ca_cert_buf[..])?) + .identity(reqwest::Identity::from_pem(&[&client_cert_buf[..], &client_key_buf[..]].concat()[..])?) + .build()? + } + _ => reqwest::Client::new(), + }; + + Ok(Self { + client, + url: config.addr.trim_end_matches('/').to_string(), kv_prefix: kv_prefix.to_string(), local_node: local_node.into(), - }; + }) } pub async fn list_nodes(&self) -> Result> { diff --git a/src/main.rs b/src/main.rs index 353af66..857d24e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,18 @@ struct Opt { )] pub consul_addr: String, + /// CA certificate for Consul server with TLS + #[structopt(long = "consul-ca-cert", env = "TRICOT_CONSUL_CA_CERT")] + pub consul_ca_cert: Option, + + /// Client certificate for Consul server with TLS + #[structopt(long = "consul-client-cert", env = "TRICOT_CONSUL_CLIENT_CERT")] + pub consul_client_cert: Option, + + /// Client key for Consul server with TLS + #[structopt(long = "consul-client-key", env = "TRICOT_CONSUL_CLIENT_KEY")] + pub consul_client_key: Option, + /// Prefix of Tricot's entries in Consul KV space #[structopt( long = "consul-kv-prefix", @@ -89,7 +101,15 @@ async fn main() { info!("Starting Tricot"); - let consul = consul::Consul::new(&opt.consul_addr, &opt.consul_kv_prefix, &opt.node_name); + let consul_config = consul::ConsulConfig{ + addr: opt.consul_addr.clone(), + ca_cert: opt.consul_ca_cert.clone(), + client_cert: opt.consul_client_cert.clone(), + client_key: opt.consul_client_key.clone(), + }; + + let consul = consul::Consul::new(consul_config, &opt.consul_kv_prefix, &opt.node_name) + .expect("Error creating Consul client"); let mut rx_proxy_config = proxy_config::spawn_proxy_config_task(consul.clone()); let cert_store = cert_store::CertStore::new(