fix(startup): never panic when the system CA bundle is absent (#6769)

This commit is contained in:
Zhengchao An
2026-08-28 08:34:51 +08:00
committed by GitHub
parent 22741603f5
commit e388a3ff53
7 changed files with 132 additions and 33 deletions
@@ -43,7 +43,7 @@ impl AwsMetadataFetcher {
///
/// Returns a new instance of `AwsMetadataFetcher`.
pub fn new(timeout: Duration) -> Self {
let client = Client::builder().timeout(timeout).build().unwrap_or_else(|_| Client::new());
let client = super::metadata_http_client(timeout);
Self {
client,
@@ -34,7 +34,7 @@ pub struct AzureMetadataFetcher {
impl AzureMetadataFetcher {
/// Creates a new `AzureMetadataFetcher`.
pub fn new(timeout: Duration) -> Self {
let client = Client::builder().timeout(timeout).build().unwrap_or_else(|_| Client::new());
let client = super::metadata_http_client(timeout);
Self {
client,
@@ -34,7 +34,7 @@ pub struct GcpMetadataFetcher {
impl GcpMetadataFetcher {
/// Creates a new `GcpMetadataFetcher`.
pub fn new(timeout: Duration) -> Self {
let client = Client::builder().timeout(timeout).build().unwrap_or_else(|_| Client::new());
let client = super::metadata_http_client(timeout);
Self {
client,
@@ -24,3 +24,40 @@ mod gcp;
pub use aws::*;
pub use azure::*;
pub use gcp::*;
/// Build the metadata HTTP client without panicking when the host has no
/// system CA bundle (issue #6734).
///
/// `reqwest::Client::new()` panics when the TLS backend cannot load any
/// system trust root, which is exactly the state of a minimal container
/// image. Cloud metadata endpoints are plain HTTP link-local addresses, so a
/// client with an explicit empty trust store is fully functional here; TLS
/// requests through it fail closed at the handshake.
pub(crate) fn metadata_http_client(timeout: std::time::Duration) -> reqwest::Client {
reqwest::Client::builder().timeout(timeout).build().unwrap_or_else(|error| {
tracing::warn!(
"cloud metadata HTTP client could not load system TLS roots ({error}); continuing with an empty trust store"
);
reqwest::Client::builder()
.timeout(timeout)
.tls_certs_only(std::iter::empty::<reqwest::Certificate>())
.build()
.expect("HTTP client construction must succeed with an explicit empty trust store")
})
}
#[cfg(test)]
mod tests {
// The startup panic fix for hosts without a CA bundle (issue #6734) rests
// on the constructor never panicking and its degraded fallback — an
// explicit empty trust store — always building.
#[test]
fn metadata_http_client_construction_never_panics() {
let _ = super::metadata_http_client(std::time::Duration::from_secs(1));
reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(1))
.tls_certs_only(std::iter::empty::<reqwest::Certificate>())
.build()
.expect("empty-trust-store client build must succeed without touching system roots");
}
}