Skip to content

Commit

Permalink
Add support for custom TLS certificate authority bundle
Browse files Browse the repository at this point in the history
* Custom TLS CA can be configured via one of the
  `MATURIN_CA_BUNDLE`, `REQUESTS_CA_BUNDLE` and `CURL_CA_BUNDLE` env vars.
  • Loading branch information
messense committed Feb 14, 2023
1 parent bfd8a0e commit 4c7b1fe
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 6 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ configparser = { version = "3.0.0", optional = true }
multipart = { version = "0.18.0", features = ["client"], default-features = false, optional = true }
ureq = { version = "2.6.1", features = ["gzip", "socks-proxy"], default-features = false, optional = true }
native-tls-crate = { package = "native-tls", version = "0.2.8", optional = true }
rustls = { version = "0.20.8", optional = true }
rustls-pemfile = { version = "1.0.1", optional = true }
keyring = { version = "1.1.1", optional = true }

[dev-dependencies]
Expand All @@ -103,8 +105,8 @@ upload = ["ureq", "multipart", "configparser", "bytesize", "dialoguer/password"]
# keyring doesn't support *BSD so it's not enabled in `full` by default
password-storage = ["upload", "keyring"]

rustls = ["ureq/tls", "cargo-xwin/rustls-tls"]
native-tls = ["ureq/native-tls", "native-tls-crate", "cargo-xwin/native-tls"]
rustls = ["ureq/tls", "dep:rustls", "cargo-xwin/rustls-tls", "rustls-pemfile"]
native-tls = ["ureq/native-tls", "native-tls-crate", "cargo-xwin/native-tls", "rustls-pemfile"]

# cross compile using zig or xwin
cross-compile = ["zig", "xwin"]
Expand Down
48 changes: 44 additions & 4 deletions src/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use fs_err::File;
use multipart::client::lazy::Multipart;
use regex::Regex;
use std::env;
use std::ffi::OsString;
use std::io;
use std::path::{Path, PathBuf};
use thiserror::Error;
Expand Down Expand Up @@ -269,21 +270,60 @@ fn http_proxy() -> Result<String, env::VarError> {
.or_else(|_| env::var("http_proxy"))
}

#[cfg(feature = "native-tls")]
fn tls_ca_bundle() -> Option<OsString> {
env::var_os("MATURIN_CA_BUNDLE")
.or_else(|| env::var_os("REQUESTS_CA_BUNDLE"))
.or_else(|| env::var_os("CURL_CA_BUNDLE"))
}

// Prefer rustls if both native-tls and rustls features are enabled
#[cfg(all(feature = "native-tls", not(feature = "rustls")))]
#[allow(clippy::result_large_err)]
fn http_agent() -> Result<ureq::Agent, UploadError> {
use std::sync::Arc;

let mut builder =
ureq::builder().tls_connector(Arc::new(native_tls_crate::TlsConnector::new()?));
let mut builder = ureq::builder();
if let Ok(proxy) = http_proxy() {
let proxy = ureq::Proxy::new(proxy)?;
builder = builder.proxy(proxy);
};
let mut tls_builder = native_tls_crate::TlsConnector::builder();
if let Some(ca_bundle) = tls_ca_bundle() {
let mut reader = io::BufReader::new(File::open(ca_bundle)?);
for cert in rustls_pemfile::certs(&mut reader)? {
tls_builder.add_root_certificate(native_tls_crate::Certificate::from_pem(&cert)?);
}
}
builder = builder.tls_connector(Arc::new(tls_builder.build()?));
Ok(builder.build())
}

#[cfg(not(feature = "native-tls"))]
#[cfg(feature = "rustls")]
#[allow(clippy::result_large_err)]
fn http_agent() -> Result<ureq::Agent, UploadError> {
use std::sync::Arc;

let mut builder = ureq::builder();
if let Ok(proxy) = http_proxy() {
let proxy = ureq::Proxy::new(proxy)?;
builder = builder.proxy(proxy);
};
if let Some(ca_bundle) = tls_ca_bundle() {
let mut reader = io::BufReader::new(File::open(ca_bundle)?);
let certs = rustls_pemfile::certs(&mut reader)?;
let mut root_certs = rustls::RootCertStore::empty();
root_certs.add_parsable_certificates(&certs);
let client_config = rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_certs)
.with_no_client_auth();
Ok(builder.tls_config(Arc::new(client_config)).build())
} else {
Ok(builder.build())
}
}

#[cfg(not(any(feature = "native-tls", feature = "rustls")))]
#[allow(clippy::result_large_err)]
fn http_agent() -> Result<ureq::Agent, UploadError> {
let mut builder = ureq::builder();
Expand Down

0 comments on commit 4c7b1fe

Please sign in to comment.