Switch from OpenSSL to Rustls (#19104)

This PR also includes a downgrade of our async_tungstenite version to
0.24

Release Notes:

- N/A
This commit is contained in:
Mikayla Maki 2024-10-11 18:18:09 -07:00 committed by GitHub
parent 22ac178f9d
commit c85a3cc117
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 118 additions and 106 deletions

View file

@ -18,7 +18,6 @@ test-support = ["clock/test-support", "collections/test-support", "gpui/test-sup
[dependencies]
anyhow.workspace = true
async-recursion = "0.3"
async-tls = "0.13"
async-tungstenite = { workspace = true, features = ["async-std", "async-tls"] }
chrono = { workspace = true, features = ["serde"] }
clock.workspace = true
@ -35,6 +34,8 @@ postage.workspace = true
rand.workspace = true
release_channel.workspace = true
rpc = { workspace = true, features = ["gpui"] }
rustls-native-certs.workspace = true
rustls.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true

View file

@ -1137,13 +1137,31 @@ impl Client {
match url_scheme {
Https => {
let client_config = {
let mut root_store = rustls::RootCertStore::empty();
let root_certs = rustls_native_certs::load_native_certs();
for error in root_certs.errors {
log::warn!("error loading native certs: {:?}", error);
}
root_store.add_parsable_certificates(
&root_certs
.certs
.into_iter()
.map(|cert| cert.as_ref().to_owned())
.collect::<Vec<_>>(),
);
rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth()
};
let (stream, _) =
async_tungstenite::async_tls::client_async_tls_with_connector(
request,
stream,
Some(async_tls::TlsConnector::from(
http_client::TLS_CONFIG.clone(),
)),
Some(client_config.into()),
)
.await?;
Ok(Connection::new(

View file

@ -21,8 +21,6 @@ derive_more.workspace = true
futures.workspace = true
http = "1.1"
log.workspace = true
rustls-native-certs.workspace = true
rustls.workspace = true
serde.workspace = true
serde_json.workspace = true
smol.workspace = true

View file

@ -12,7 +12,7 @@ use http::request::Builder;
use std::fmt;
use std::{
any::type_name,
sync::{Arc, LazyLock, Mutex},
sync::{Arc, Mutex},
time::Duration,
};
pub use url::Url;
@ -35,23 +35,6 @@ pub enum RedirectPolicy {
}
pub struct FollowRedirects(pub bool);
pub static TLS_CONFIG: LazyLock<Arc<rustls::ClientConfig>> = LazyLock::new(|| {
let mut root_store = rustls::RootCertStore::empty();
let root_certs = rustls_native_certs::load_native_certs();
for error in root_certs.errors {
log::warn!("error loading native certs: {:?}", error);
}
root_store.add_parsable_certificates(&root_certs.certs);
Arc::new(
rustls::ClientConfig::builder()
.with_safe_defaults()
.with_root_certificates(root_store)
.with_no_client_auth(),
)
});
pub trait HttpRequestExt {
/// Set a read timeout on the request.
/// For isahc, this is the low_speed_timeout.

View file

@ -28,7 +28,7 @@ serde.workspace = true
smol.workspace = true
log.workspace = true
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
reqwest = { workspace = true, features = ["rustls-tls-manual-roots", "stream"] }
reqwest.workspace = true
[dev-dependencies]
gpui.workspace = true

View file

@ -2,7 +2,7 @@ use std::{any::type_name, borrow::Cow, io::Read, mem, pin::Pin, sync::OnceLock,
use anyhow::anyhow;
use bytes::{BufMut, Bytes, BytesMut};
use futures::{AsyncRead, TryStreamExt};
use futures::{AsyncRead, TryStreamExt as _};
use http_client::{http, ReadTimeout, RedirectPolicy};
use reqwest::{
header::{HeaderMap, HeaderValue},
@ -11,6 +11,7 @@ use reqwest::{
use smol::future::FutureExt;
const DEFAULT_CAPACITY: usize = 4096;
static RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
pub struct ReqwestClient {
client: reqwest::Client,
@ -20,20 +21,29 @@ pub struct ReqwestClient {
impl ReqwestClient {
pub fn new() -> Self {
reqwest::Client::new().into()
reqwest::Client::builder()
.use_rustls_tls()
.build()
.expect("Failed to initialize HTTP client")
.into()
}
pub fn user_agent(agent: &str) -> anyhow::Result<Self> {
let mut map = HeaderMap::new();
map.insert(http::header::USER_AGENT, HeaderValue::from_str(agent)?);
let client = reqwest::Client::builder().default_headers(map).build()?;
let client = reqwest::Client::builder()
.default_headers(map)
.use_rustls_tls()
.build()?;
Ok(client.into())
}
pub fn proxy_and_user_agent(proxy: Option<http::Uri>, agent: &str) -> anyhow::Result<Self> {
let mut map = HeaderMap::new();
map.insert(http::header::USER_AGENT, HeaderValue::from_str(agent)?);
let mut client = reqwest::Client::builder().default_headers(map);
let mut client = reqwest::Client::builder()
.use_rustls_tls()
.default_headers(map);
if let Some(proxy) = proxy.clone() {
client = client.proxy(reqwest::Proxy::all(proxy.to_string())?);
}
@ -44,8 +54,6 @@ impl ReqwestClient {
}
}
static RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
impl From<reqwest::Client> for ReqwestClient {
fn from(client: reqwest::Client) -> Self {
let handle = tokio::runtime::Handle::try_current().unwrap_or_else(|_| {