LCOV - code coverage report
Current view: top level - proxy/src/tls - client_config.rs (source / functions) Coverage Total Hit
Test: 5445d246133daeceb0507e6cc0797ab7c1c70cb8.info Lines: 24.5 % 49 12
Test Date: 2025-03-12 18:05:02 Functions: 28.6 % 7 2

            Line data    Source code
       1              : use std::env;
       2              : use std::io::Cursor;
       3              : use std::path::PathBuf;
       4              : use std::sync::Arc;
       5              : 
       6              : use anyhow::{Context, bail};
       7              : use rustls::crypto::ring;
       8              : 
       9              : /// We use an internal certificate authority when establishing a TLS connection with compute.
      10            0 : fn load_internal_certs(store: &mut rustls::RootCertStore) -> anyhow::Result<()> {
      11            0 :     let Some(ca_file) = env::var_os("NEON_INTERNAL_CA_FILE") else {
      12            0 :         return Ok(());
      13              :     };
      14            0 :     let ca_file = PathBuf::from(ca_file);
      15              : 
      16            0 :     let ca = std::fs::read(&ca_file)
      17            0 :         .with_context(|| format!("could not read CA from {}", ca_file.display()))?;
      18              : 
      19            0 :     for cert in rustls_pemfile::certs(&mut Cursor::new(&*ca)) {
      20            0 :         store
      21            0 :             .add(cert.context("could not parse internal CA certificate")?)
      22            0 :             .context("could not parse internal CA certificate")?;
      23              :     }
      24              : 
      25            0 :     Ok(())
      26            0 : }
      27              : 
      28              : /// For console redirect proxy, we need to establish a connection to compute via pg-sni-router.
      29              : /// pg-sni-router needs TLS and uses a Let's Encrypt signed certificate, so we
      30              : /// load certificates from our native store.
      31            0 : fn load_native_certs(store: &mut rustls::RootCertStore) -> anyhow::Result<()> {
      32            0 :     let der_certs = rustls_native_certs::load_native_certs();
      33            0 : 
      34            0 :     if !der_certs.errors.is_empty() {
      35            0 :         bail!("could not parse certificates: {:?}", der_certs.errors);
      36            0 :     }
      37            0 : 
      38            0 :     store.add_parsable_certificates(der_certs.certs);
      39            0 : 
      40            0 :     Ok(())
      41            0 : }
      42              : 
      43            0 : fn load_compute_certs() -> anyhow::Result<Arc<rustls::RootCertStore>> {
      44            0 :     let mut store = rustls::RootCertStore::empty();
      45            0 :     load_native_certs(&mut store)?;
      46            0 :     load_internal_certs(&mut store)?;
      47            0 :     Ok(Arc::new(store))
      48            0 : }
      49              : 
      50              : /// Loads the root certificates and constructs a client config suitable for connecting to the neon compute.
      51              : /// This function is blocking.
      52            0 : pub fn compute_client_config_with_root_certs() -> anyhow::Result<rustls::ClientConfig> {
      53            0 :     Ok(
      54            0 :         rustls::ClientConfig::builder_with_provider(Arc::new(ring::default_provider()))
      55            0 :             .with_safe_default_protocol_versions()
      56            0 :             .expect("ring should support the default protocol versions")
      57            0 :             .with_root_certificates(load_compute_certs()?)
      58            0 :             .with_no_client_auth(),
      59              :     )
      60            0 : }
      61              : 
      62              : #[cfg(test)]
      63           28 : pub fn compute_client_config_with_certs(
      64           28 :     certs: impl IntoIterator<Item = rustls::pki_types::CertificateDer<'static>>,
      65           28 : ) -> rustls::ClientConfig {
      66           28 :     let mut store = rustls::RootCertStore::empty();
      67           28 :     store.add_parsable_certificates(certs);
      68           28 : 
      69           28 :     rustls::ClientConfig::builder_with_provider(Arc::new(ring::default_provider()))
      70           28 :         .with_safe_default_protocol_versions()
      71           28 :         .expect("ring should support the default protocol versions")
      72           28 :         .with_root_certificates(store)
      73           28 :         .with_no_client_auth()
      74           28 : }
        

Generated by: LCOV version 2.1-beta