//! TLS configuration helpers for tonic server and client. use std::fs; use tonic::transport::{Certificate, ClientTlsConfig, Identity, ServerTlsConfig}; use crate::{config::TlsConfig, error::GrpcTransportError}; /// Build a tonic `ServerTlsConfig` from our TLS config. /// /// # Errors /// /// Returns [`GrpcTransportError`] if the server cert, server key, or CA cert /// file cannot be read. pub fn server_tls_config(tls: &TlsConfig) -> Result { let server_cert = fs::read(&tls.server_cert) .map_err(|e| GrpcTransportError::TlsConfig(format!("read server cert: {e}")))?; let server_key = fs::read(&tls.server_key) .map_err(|e| GrpcTransportError::TlsConfig(format!("read server key: {e}")))?; let ca_cert = fs::read(&tls.ca_cert) .map_err(|e| GrpcTransportError::TlsConfig(format!("read CA cert: {e}")))?; let identity = Identity::from_pem(server_cert, server_key); let ca = Certificate::from_pem(ca_cert); Ok(ServerTlsConfig::new().identity(identity).client_ca_root(ca)) } /// Build a tonic `ClientTlsConfig` from our TLS config. /// /// # Errors /// /// Returns [`GrpcTransportError`] if the CA cert (or, when mutual TLS is /// configured, the client cert/key) file cannot be read. pub fn client_tls_config(tls: &TlsConfig) -> Result { let ca_cert = fs::read(&tls.ca_cert) .map_err(|e| GrpcTransportError::TlsConfig(format!("read CA cert: {e}")))?; let ca = Certificate::from_pem(ca_cert); let mut config = ClientTlsConfig::new().ca_certificate(ca); if let (Some(cert_path), Some(key_path)) = (&tls.client_cert, &tls.client_key) { let cert = fs::read(cert_path) .map_err(|e| GrpcTransportError::TlsConfig(format!("read client cert: {e}")))?; let key = fs::read(key_path) .map_err(|e| GrpcTransportError::TlsConfig(format!("read client key: {e}")))?; config = config.identity(Identity::from_pem(cert, key)); } Ok(config) }