diff --git a/Cargo.lock b/Cargo.lock index 9968ceb0..0289d961 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3361,6 +3361,8 @@ dependencies = [ "rand_core 0.6.4", "rpassword", "rsa", + "rustls 0.20.8", + "rustls-pemfile", "sdkms", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 21513005..711dd5d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,8 @@ aes-kw = { version = "0.2.1", features = ["std"], optional = true} rsa = { version = "0.6.1", default = true, optional = true} rand = { version = "0.7", optional = true} aes-gcm = { version = "0.10.1", optional = true} +rustls = "0.20.8" +rustls-pemfile = "1.0.2" [dev-dependencies] abscissa_core = { version = "0.7", features = ["testing"] } diff --git a/Dockerfile.hashicorp b/Dockerfile.hashicorp new file mode 100644 index 00000000..91927e35 --- /dev/null +++ b/Dockerfile.hashicorp @@ -0,0 +1,11 @@ +FROM rust:1.66-alpine AS builder + +RUN apk add --no-cache g++ zlib zlib-dev + +WORKDIR /app +COPY . /app +RUN cargo build --release --features=hashicorp + +FROM alpine +COPY --from=builder /app/target/release/tmkms /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/tmkms"] \ No newline at end of file diff --git a/src/commands/hashicorp/test.rs b/src/commands/hashicorp/test.rs index f36e7d69..b461abcb 100644 --- a/src/commands/hashicorp/test.rs +++ b/src/commands/hashicorp/test.rs @@ -58,6 +58,7 @@ impl Runnable for TestCommand { &config.api_endpoint, &config.access_token, &self.pk_name, + "", ) .unwrap_or_else(|e| panic!("Unable to connect to Vault {} {}", config.api_endpoint, e)); diff --git a/src/commands/hashicorp/upload.rs b/src/commands/hashicorp/upload.rs index 3ae68817..3662a43c 100644 --- a/src/commands/hashicorp/upload.rs +++ b/src/commands/hashicorp/upload.rs @@ -100,6 +100,7 @@ impl UploadCommand { &config.api_endpoint, &vault_token, &self.pk_name, + &config.ca_cert, ) .unwrap_or_else(|_| panic!("Unable to connect to Vault at {}", config.api_endpoint)); diff --git a/src/commands/init/templates/keyring/hashicorp.toml b/src/commands/init/templates/keyring/hashicorp.toml index 8e7cb6e0..7398760d 100644 --- a/src/commands/init/templates/keyring/hashicorp.toml +++ b/src/commands/init/templates/keyring/hashicorp.toml @@ -7,3 +7,5 @@ api_endpoint= "http://127.0.0.1:8200" access_token="hvs.CAESINi91lCOFj-_dOGiUfpdZUPKk93LD8YyHz-qZcYLVwH_Gh4KHGh2cy5kdXV1T2tpcXliakFFblU1SUpqanczYjU" #Vault's transit secret engine key - vault write transit/keys/ type=ed25519 pk_name="cosmoshub-sign-key" +#Path to CA certificate to be used to connect to vault +ca_cert="" \ No newline at end of file diff --git a/src/config/provider/hashicorp.rs b/src/config/provider/hashicorp.rs index 26866868..79978fa8 100644 --- a/src/config/provider/hashicorp.rs +++ b/src/config/provider/hashicorp.rs @@ -18,4 +18,7 @@ pub struct HashiCorpConfig { /// Vault's key name with ed25519 pub+priv key pub pk_name: String, + + /// Path to CA certificate to connect to vault + pub ca_cert: String, } diff --git a/src/keyring/providers/hashicorp.rs b/src/keyring/providers/hashicorp.rs index e750a270..20e30b91 100644 --- a/src/keyring/providers/hashicorp.rs +++ b/src/keyring/providers/hashicorp.rs @@ -44,6 +44,7 @@ pub fn init( &config.api_endpoint, &config.access_token, &config.pk_name, + &config.ca_cert, ) .unwrap_or_else(|_| { panic!( diff --git a/src/keyring/providers/hashicorp/client.rs b/src/keyring/providers/hashicorp/client.rs index de21c8d8..7f592b48 100644 --- a/src/keyring/providers/hashicorp/client.rs +++ b/src/keyring/providers/hashicorp/client.rs @@ -4,7 +4,10 @@ use std::collections::{BTreeMap, HashMap}; use super::error::Error; use std::time::Duration; +use std::{fs, io, sync}; use ureq::Agent; +use rustls::RootCertStore; +use rustls_pemfile; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -120,20 +123,35 @@ impl std::fmt::Display for CreateKeyType { } impl TendermintValidatorApp { - pub fn connect(api_endpoint: &str, token: &str, key_name: &str) -> Result { - //this call performs token self lookup, to fail fast - //let mut client = Client::new(host, token)?; - + pub fn connect(api_endpoint: &str, token: &str, key_name: &str, ca_cert: &str) -> Result { //default conect timeout is 30s, this should be ok, since we block - let agent: Agent = ureq::AgentBuilder::new() + let mut agent_builder = ureq::AgentBuilder::new() .timeout_read(Duration::from_secs(5)) .timeout_write(Duration::from_secs(5)) .user_agent(&format!( "{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION") - )) - .build(); + )); + + if !ca_cert.is_empty() { + debug!("Using provided CA certificate at {}", ca_cert); + let cert_file = fs::File::open(ca_cert).expect("Cant open certificate file"); + let mut cert_rd = io::BufReader::new(cert_file); + let certs = rustls_pemfile::certs(&mut cert_rd).expect("Invalid certificate"); + + let mut roots = RootCertStore::empty(); + roots.add_parsable_certificates(&certs); + + let tls_config = rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(roots) + .with_no_client_auth(); + + agent_builder = agent_builder.tls_config(sync::Arc::new(tls_config)) + } + + let agent = agent_builder.build(); let app = TendermintValidatorApp { agent,