Skip to content

Commit

Permalink
feat(cli): Support a NEXTCLADE_EXTRA_CA_CERTS environment variable an…
Browse files Browse the repository at this point in the history
…d --extra-ca-certs option

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.

An option may be preferred to an env var by some users or in some
invocations.  It also provides a convenient place for documentation of
default CA cert handling and point of discovery for users.

Co-authored-by: ivan-aksamentov <[email protected]>
Supersedes: <#1527>
Related-to: <#1529>
Related-to: <#726>
  • Loading branch information
tsibley and ivan-aksamentov committed Oct 16, 2024
1 parent 80d8f83 commit 175e31b
Showing 1 changed file with 34 additions and 1 deletion.
35 changes: 34 additions & 1 deletion packages/nextclade-cli/src/io/http_client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use clap::{Parser, ValueHint};
use eyre::Report;
use eyre::{Report, WrapErr};
use log::info;
use nextclade::io::file::open_file_or_stdin;
use nextclade::make_internal_error;
use nextclade::utils::info::{this_package_name, this_package_version_str};
use reqwest::blocking::Client;
use reqwest::tls::Certificate;
use reqwest::{Method, Proxy};
use std::env;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::time::Duration;
use url::Url;
Expand All @@ -26,6 +30,15 @@ pub struct ProxyConfig {
#[clap(long)]
#[clap(value_hint = ValueHint::Other)]
pub proxy_pass: Option<String>,

/// Path to extra CA certificates as a PEM bundle.
///
/// You can also provide the path to CA certificates in the environment variable `NEXTCLADE_EXTRA_CA_CERTS`. The argument takes precedence over the environment variable if both are provided.
///
/// Default CA certificates are those obtained from the platform/OS-level trust store plus those from a baked-in copy of Mozilla's common CA trust store. You can override the certs obtained from the platform trust store by setting `SSL_CERT_FILE` or `SSL_CERT_DIR`. Filenames in the latter must be hashed in the style of OpenSSL's `c_rehash` utility.
#[clap(long)]
#[clap(value_hint = ValueHint::Other)]
pub extra_ca_certs: Option<PathBuf>,
}

pub struct HttpClient {
Expand Down Expand Up @@ -59,6 +72,13 @@ impl HttpClient {
client_builder
};

let extra_ca_certs_filepath = env::var_os("NEXTCLADE_EXTRA_CA_CERTS").map(PathBuf::from);
let extra_ca_certs_filepath = proxy_conf.extra_ca_certs.as_ref().or(extra_ca_certs_filepath.as_ref());

for cert in extra_ca_certs(extra_ca_certs_filepath)?.into_iter() {
client_builder = client_builder.add_root_certificate(cert);
}

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

let client = client_builder
Expand Down Expand Up @@ -110,3 +130,16 @@ impl HttpClient {
Ok(content)
}
}

fn extra_ca_certs(extra_ca_certs_filepath: Option<impl AsRef<Path>>) -> Result<Vec<Certificate>, Report> {
extra_ca_certs_filepath.map_or_else(
|| Ok(vec![]),
|filename| {
let mut pem = vec![];

open_file_or_stdin(&Some(filename))?.read_to_end(&mut pem)?;

Certificate::from_pem_bundle(&pem).wrap_err("While reading PEM bundle")
},
)
}

0 comments on commit 175e31b

Please sign in to comment.