Skip to content

Commit edf5adc

Browse files
committed
feat: Support a NEXTCLADE_EXTRA_CA_CERTS environment variable
Allows adding additional CA certificates to the trust store specifically for Nextclade, for when modifying the system's trust store isn't desirable/possible. Works across all platforms. Currently requires using landed unreleased changes to rustls-platform-verifier so that macOS and Windows have the needed Verifier::new_with_extra_certs() API.¹ That API also has signature changes proposed² which, while unmerged, seem likely to land, so use those in anticipation. They actually bring the signature back closer to the latest release (0.3.4). ¹ <rustls/rustls-platform-verifier#58> ² <rustls/rustls-platform-verifier#145> Related-to: <#1529> Related-to: <#726>
1 parent 9b2d9dd commit edf5adc

File tree

4 files changed

+61
-11
lines changed

4 files changed

+61
-11
lines changed

Cargo.lock

Lines changed: 19 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ regex = "=1.8.4"
7373
reqwest = { version = "=0.12.8", default-features = false, features = ["blocking", "deflate", "gzip", "brotli", "socks", "rustls-tls"] }
7474
rstest = "=0.17.0"
7575
rstest_reuse = "=0.5.0"
76-
rustls-platform-verifier = "=0.3.4"
76+
rustls = { version = "=0.23.14", default-features = false, features = ["ring", "logging", "std", "tls12"] }
77+
rustls-platform-verifier = { git = "https://github.com/rustls/rustls-platform-verifier.git", rev = "ca87571fe47730665917b8c29f14a3989f3cbe57" }
78+
rustls-pemfile = "=2.2.0"
79+
rustls-pki-types = "=1.9.0"
80+
rustls-webpki = { version = "=0.102.8", features = ["ring"] }
7781
schemars = { version = "=0.8.12", features = ["chrono", "either", "enumset", "indexmap"] }
7882
semver = { version = "=1.0.17", features = ["serde"] }
7983
serde = { version = "=1.0.164", features = ["derive"] }

packages/nextclade-cli/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ pretty_assertions = { workspace = true }
4141
rayon = { workspace = true }
4242
regex = { workspace = true }
4343
reqwest = { workspace = true }
44+
rustls = { workspace = true }
4445
rustls-platform-verifier = { workspace = true }
46+
rustls-pemfile = { workspace = true }
47+
rustls-pki-types = { workspace = true }
48+
rustls-webpki = { workspace = true }
4549
schemars = { workspace = true }
4650
semver = { workspace = true }
4751
serde = { workspace = true }

packages/nextclade-cli/src/io/http_client.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
use clap::{Parser, ValueHint};
2-
use eyre::Report;
2+
use eyre::{Report, WrapErr};
33
use log::info;
44
use nextclade::make_internal_error;
55
use nextclade::utils::info::{this_package_name, this_package_version_str};
66
use reqwest::blocking::Client;
77
use reqwest::{Method, Proxy};
8-
use rustls_platform_verifier;
8+
use rustls::ClientConfig;
9+
use rustls_pemfile;
10+
use rustls_pki_types::CertificateDer;
11+
use rustls_platform_verifier::Verifier;
12+
use std::env;
13+
use std::io::BufReader;
14+
use std::fs::File;
915
use std::str::FromStr;
16+
use std::sync::Arc;
1017
use std::time::Duration;
1118
use url::Url;
1219

@@ -62,8 +69,13 @@ impl HttpClient {
6269

6370
let user_agent = format!("{} {}", this_package_name(), this_package_version_str());
6471

72+
let tls_config = ClientConfig::builder()
73+
.dangerous() // …but the rustls_platform_verifier::Verifier is safe
74+
.with_custom_certificate_verifier(Arc::new(Verifier::new_with_extra_roots(extra_ca_certs()?)?))
75+
.with_no_client_auth();
76+
6577
let client = client_builder
66-
.use_preconfigured_tls(rustls_platform_verifier::tls_config())
78+
.use_preconfigured_tls(tls_config)
6779
.connection_verbose(verbose)
6880
.connect_timeout(Some(Duration::from_secs(60)))
6981
.user_agent(user_agent)
@@ -112,3 +124,21 @@ impl HttpClient {
112124
Ok(content)
113125
}
114126
}
127+
128+
fn extra_ca_certs() -> Result<impl IntoIterator<Item = CertificateDer<'static>>, Report> {
129+
match env::var_os("NEXTCLADE_EXTRA_CA_CERTS") {
130+
Some(filename) => {
131+
let file = File::open(filename.clone())
132+
.wrap_err_with(|| format!("When opening NEXTCLADE_EXTRA_CA_CERTS file {filename:?}"))?;
133+
134+
let mut reader = BufReader::new(file);
135+
136+
let certs = rustls_pemfile::certs(&mut reader)
137+
.map(|c| c.wrap_err_with(|| "When parsing an extra CA certificate".to_owned()))
138+
.collect::<Result<Vec<_>, Report>>()?;
139+
140+
Ok(certs)
141+
}
142+
None => Ok(vec![])
143+
}
144+
}

0 commit comments

Comments
 (0)