From b8b734f9b2e9af9b1b81a56f74712aad9316b036 Mon Sep 17 00:00:00 2001 From: Dan Norris Date: Fri, 26 Jan 2024 16:38:39 -0500 Subject: [PATCH] feat: add custom CA support to the NATS provider, rework Redis TLS This PR does two things: * adds the ability to add a custom root CA to each NATS linkdef so that you can connect to servers that might be secured with self-signed certs * reworks how the Redis provider depends on rustls and other dependencies so that the webroot PKI certs are embedded. This removes a dependency on the host for anything TLS related. Signed-off-by: Dan Norris --- kvredis/Cargo.lock | 105 +++++++++++++++++++++++++-------- kvredis/Cargo.toml | 4 +- kvredis/src/main.rs | 21 ++++--- nats/Cargo.lock | 139 +++++++++++++++++++++++++++++++++++--------- nats/Cargo.toml | 8 ++- nats/src/main.rs | 90 +++++++++++++++++++++------- 6 files changed, 280 insertions(+), 87 deletions(-) diff --git a/kvredis/Cargo.lock b/kvredis/Cargo.lock index 8419c9f7..6cb6ce8b 100644 --- a/kvredis/Cargo.lock +++ b/kvredis/Cargo.lock @@ -150,10 +150,10 @@ dependencies = [ "once_cell", "rand", "regex", - "ring", + "ring 0.16.20", "rustls-native-certs", "rustls-pemfile", - "rustls-webpki", + "rustls-webpki 0.101.7", "serde", "serde_json", "serde_nanos", @@ -369,9 +369,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -1199,9 +1202,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "linux-raw-sys" @@ -1775,9 +1778,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea8c51b5dc1d8e5fd3350ec8167f464ec0995e79f2e90a075b63371500d557f" +checksum = "c580d9cbbe1d1b479e8d67cf9daf6a62c957e6846048408b80b43ac3f6af84cd" dependencies = [ "arc-swap", "async-trait", @@ -1789,11 +1792,18 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-webpki 0.101.7", "ryu", "sha1_smol", + "socket2", "tokio", + "tokio-retry", + "tokio-rustls", "tokio-util 0.7.8", "url", + "webpki-roots 0.23.1", ] [[package]] @@ -1904,7 +1914,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.22.6", "winreg", ] @@ -1917,12 +1927,26 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + [[package]] name = "rmp" version = "0.8.11" @@ -1986,13 +2010,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.5" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring", - "rustls-webpki", + "ring 0.17.7", + "rustls-webpki 0.101.7", "sct", ] @@ -2019,12 +2043,22 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.1" +version = "0.100.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +checksum = "5f6a5fc258f1c1276dfe3016516945546e2d5383911efc0fc4f1cdc5df3a4ae3" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.7", + "untrusted 0.9.0", ] [[package]] @@ -2054,8 +2088,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -2265,6 +2299,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.4.1" @@ -2784,6 +2824,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -2846,7 +2892,7 @@ dependencies = [ "log", "nkeys", "nuid 0.4.1", - "ring", + "ring 0.16.20", "serde", "serde_derive", "serde_json", @@ -3037,7 +3083,7 @@ dependencies = [ [[package]] name = "wasmcloud-provider-kvredis" -version = "0.22.0" +version = "0.23.0" dependencies = [ "async-trait", "atty", @@ -3112,8 +3158,8 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -3125,6 +3171,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.3", +] + [[package]] name = "weld-codegen" version = "0.7.0" diff --git a/kvredis/Cargo.toml b/kvredis/Cargo.toml index f3e7273d..a315b066 100644 --- a/kvredis/Cargo.toml +++ b/kvredis/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmcloud-provider-kvredis" -version = "0.22.0" +version = "0.23.0" edition = "2021" [dependencies] @@ -12,7 +12,7 @@ chrono = "0.4" crossbeam = "0.8" futures = "0.3" once_cell = "1.8" -redis = { version = "0.23.0", features = ["tokio-comp", "aio", "connection-manager", "rustls"] } +redis = { version = "0.24.0", features = ["tokio-rustls-comp", "aio", "connection-manager", "tls-rustls-webpki-roots"] } rmp-serde = "1.1.0" serde_bytes = "0.11" serde_json = "1.0" diff --git a/kvredis/src/main.rs b/kvredis/src/main.rs index 2e375142..43c504e6 100644 --- a/kvredis/src/main.rs +++ b/kvredis/src/main.rs @@ -85,14 +85,17 @@ impl ProviderHandler for KvRedisProvider { let redis_url = get_redis_url(&ld.values, &self.default_connect_url); if let Ok(client) = redis::Client::open(redis_url.clone()) { - if let Ok(conn_manager) = client.get_tokio_connection_manager().await { - let mut update_map = self.actors.write().await; - update_map.insert(ld.actor_id.to_string(), RwLock::new(conn_manager)); - } else { - warn!( - "Could not create Redis connection manager for actor {}, keyvalue operations will fail", - ld.actor_id - ); + match client.get_connection_manager().await { + Ok(conn_manager) => { + let mut update_map = self.actors.write().await; + update_map.insert(ld.actor_id.to_string(), RwLock::new(conn_manager)); + } + Err(e) => { + warn!( + "Could not create Redis connection manager for actor {}, keyvalue operations will fail: {}", + ld.actor_id, e + ); + } } } else { warn!( @@ -245,7 +248,7 @@ impl KeyValue for KvRedisProvider { async fn set(&self, ctx: &Context, arg: &SetRequest) -> RpcResult<()> { let mut cmd = match arg.expires { 0 => redis::Cmd::set(&arg.key, &arg.value), - _ => redis::Cmd::set_ex(&arg.key, &arg.value, arg.expires as usize), + _ => redis::Cmd::set_ex(&arg.key, &arg.value, arg.expires as u64), }; let _value: Option = self.exec(ctx, &mut cmd).await?; Ok(()) diff --git a/nats/Cargo.lock b/nats/Cargo.lock index ff3045cb..372f660a 100644 --- a/nats/Cargo.lock +++ b/nats/Cargo.lock @@ -144,10 +144,10 @@ dependencies = [ "once_cell", "rand", "regex", - "ring", + "ring 0.16.20", "rustls-native-certs", - "rustls-pemfile", - "rustls-webpki", + "rustls-pemfile 1.0.3", + "rustls-webpki 0.101.1", "serde", "serde_json", "serde_nanos", @@ -156,7 +156,7 @@ dependencies = [ "time 0.3.23", "tokio", "tokio-retry", - "tokio-rustls", + "tokio-rustls 0.24.1", "tracing", "url", ] @@ -363,9 +363,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -1038,9 +1041,9 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls", + "rustls 0.21.5", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", ] [[package]] @@ -1192,9 +1195,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "linux-raw-sys" @@ -1883,13 +1886,13 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-pemfile", + "rustls 0.21.5", + "rustls-pemfile 1.0.3", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", @@ -1908,12 +1911,26 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + [[package]] name = "rmp" version = "0.8.11" @@ -1982,11 +1999,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" dependencies = [ "log", - "ring", - "rustls-webpki", + "ring 0.16.20", + "rustls-webpki 0.101.1", "sct", ] +[[package]] +name = "rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +dependencies = [ + "log", + "ring 0.17.7", + "rustls-pki-types", + "rustls-webpki 0.102.1", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -1994,7 +2025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.3", "schannel", "security-framework", ] @@ -2008,14 +2039,41 @@ dependencies = [ "base64 0.21.2", ] +[[package]] +name = "rustls-pemfile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" +dependencies = [ + "base64 0.21.2", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9d979b3ce68192e42760c7810125eb6cf2ea10efae545a156063e61f314e2a" + [[package]] name = "rustls-webpki" version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4ca26037c909dedb327b48c3327d0ba91d3dd3c4e05dad328f210ffb68e95b" +dependencies = [ + "ring 0.17.7", + "rustls-pki-types", + "untrusted 0.9.0", ] [[package]] @@ -2045,8 +2103,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -2250,6 +2308,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.4.1" @@ -2457,7 +2521,18 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.5", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.2", + "rustls-pki-types", "tokio", ] @@ -2769,6 +2844,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -2832,7 +2913,7 @@ dependencies = [ "nkeys 0.2.0", "nuid 0.3.2", "parity-wasm", - "ring", + "ring 0.16.20", "serde", "serde_derive", "serde_json", @@ -2852,7 +2933,7 @@ dependencies = [ "log", "nkeys 0.3.0", "nuid 0.4.1", - "ring", + "ring 0.16.20", "serde", "serde_derive", "serde_json", @@ -3043,7 +3124,7 @@ dependencies = [ [[package]] name = "wasmcloud-provider-nats" -version = "0.17.4" +version = "0.18.0" dependencies = [ "anyhow", "async-nats", @@ -3056,11 +3137,13 @@ dependencies = [ "futures", "once_cell", "rmp-serde", + "rustls-pemfile 2.0.0", "serde", "serde_bytes", "serde_json", "thiserror", "tokio", + "tokio-rustls 0.25.0", "toml 0.5.11", "tracing", "tracing-futures", @@ -3120,8 +3203,8 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] diff --git a/nats/Cargo.toml b/nats/Cargo.toml index 4617588a..91219f8f 100644 --- a/nats/Cargo.toml +++ b/nats/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "wasmcloud-provider-nats" -version = "0.17.4" +version = "0.18.0" edition = "2021" [dependencies] +anyhow = "1.0.69" async-nats = "0.30" async-trait = "0.1" atty = "0.2" @@ -14,17 +15,18 @@ crossbeam="0.8" futures = "0.3" once_cell = "1.8" rmp-serde = "1.1.0" +rustls-pemfile = "2.0" +serde = {version = "1.0", features = ["derive"] } serde_bytes = "0.11" serde_json = "1.0" -serde = {version = "1.0", features = ["derive"] } thiserror = "1.0" tokio = { version = "1", features = ["full"] } +tokio-rustls = "0.25" toml = "0.5" tracing = "0.1" tracing-futures = "0.2" tracing-subscriber = { version = "0.3", features = ["env-filter"] } wascap = "0.8.0" -anyhow = "1.0.69" wasmbus-rpc = { version = "0.14", features = [ "otel" ] } wasmcloud-interface-messaging = "0.10" diff --git a/nats/src/main.rs b/nats/src/main.rs index f70b4f4b..7b72932b 100644 --- a/nats/src/main.rs +++ b/nats/src/main.rs @@ -24,6 +24,7 @@ const ENV_NATS_SUBSCRIPTION: &str = "SUBSCRIPTION"; const ENV_NATS_URI: &str = "URI"; const ENV_NATS_CLIENT_JWT: &str = "CLIENT_JWT"; const ENV_NATS_CLIENT_SEED: &str = "CLIENT_SEED"; +const ENV_NATS_TLS_CA: &str = "TLS_CA"; fn main() -> Result<(), Box> { // handle lattice control messages and forward rpc to the provider dispatch @@ -74,6 +75,8 @@ struct ConnectionConfig { auth_jwt: Option, #[serde(default)] auth_seed: Option, + #[serde(default)] + tls_ca: Option, /// ping interval in seconds #[serde(default)] @@ -101,6 +104,9 @@ impl ConnectionConfig { if extra.ping_interval_sec.is_some() { out.ping_interval_sec = extra.ping_interval_sec } + if extra.tls_ca.is_some() { + out.tls_ca = extra.tls_ca.clone() + } out } } @@ -113,6 +119,7 @@ impl Default for ConnectionConfig { auth_jwt: None, auth_seed: None, ping_interval_sec: None, + tls_ca: None, } } } @@ -154,6 +161,9 @@ impl ConnectionConfig { if config.cluster_uris.is_empty() { config.cluster_uris.push(DEFAULT_NATS_URI.to_string()); } + if let Some(tls_ca) = values.get(ENV_NATS_TLS_CA) { + config.tls_ca = Some(tls_ca.clone()); + } Ok(config) } } @@ -197,27 +207,9 @@ impl NatsMessagingProvider { cfg: ConnectionConfig, ld: &LinkDefinition, ) -> Result { - let opts = match (cfg.auth_jwt, cfg.auth_seed) { - (Some(jwt), Some(seed)) => { - let key_pair = std::sync::Arc::new( - KeyPair::from_seed(&seed) - .map_err(|e| RpcError::ProviderInit(format!("key init: {}", e)))?, - ); - async_nats::ConnectOptions::with_jwt(jwt, move |nonce| { - let key_pair = key_pair.clone(); - async move { key_pair.sign(&nonce).map_err(async_nats::AuthError::new) } - }) - } - (None, None) => async_nats::ConnectOptions::default(), - _ => { - return Err(RpcError::InvalidParameter( - "must provide both jwt and seed for jwt authentication".into(), - )); - } - }; - + let opts = build_connect_options(&cfg)?; // Use the first visible cluster_uri - let url = cfg.cluster_uris.get(0).unwrap(); + let url = cfg.cluster_uris.first().unwrap(); let client_name = format!( "NATS Messaging Provider - {} - {} - {}", @@ -485,6 +477,64 @@ fn should_strip_headers(topic: &str) -> bool { topic.starts_with("$SYS") } +fn build_connect_options(cfg: &ConnectionConfig) -> Result { + let opts = match (cfg.auth_jwt.clone(), cfg.auth_seed.clone()) { + (Some(jwt), Some(seed)) => { + let key_pair = std::sync::Arc::new( + KeyPair::from_seed(&seed) + .map_err(|e| RpcError::ProviderInit(format!("key init: {}", e)))?, + ); + async_nats::ConnectOptions::with_jwt(jwt, move |nonce| { + let key_pair = key_pair.clone(); + async move { key_pair.sign(&nonce).map_err(async_nats::AuthError::new) } + }) + } + (None, None) => async_nats::ConnectOptions::default(), + _ => { + return Err(RpcError::InvalidParameter( + "must provide both jwt and seed for jwt authentication".into(), + )); + } + }; + + if let Some(tls_ca) = &cfg.tls_ca { + return add_tls_ca(tls_ca, opts); + } + + Ok(opts) +} + +fn add_tls_ca( + tls_ca: &str, + opts: async_nats::ConnectOptions, +) -> Result { + let mut store_builder = async_nats::rustls::RootCertStore::empty(); + let parsed_ca = rustls_pemfile::read_one(&mut tls_ca.as_bytes()) + .map_err(|e| RpcError::ProviderInit(format!("tls ca: {}", e)))?; + if let Some(parsed) = parsed_ca { + match parsed { + rustls_pemfile::Item::X509Certificate(cert) => { + store_builder.add_parsable_certificates(&[cert]); + } + _ => { + return Err(RpcError::ProviderInit( + "tls ca: invalid certificate type, must be a DER encoded PEM file".into(), + )); + } + } + + let tls_client = async_nats::rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(store_builder) + .with_no_client_auth(); + Ok(opts.tls_client_config(tls_client).require_tls(true)) + } else { + Err(RpcError::ProviderInit( + "tls ca: invalid certificate type, must be a DER encoded PEM file".into(), + )) + } +} + #[cfg(test)] mod test { use std::collections::HashMap;