use crate::error::{DbError, DbResult};
use std::sync::Arc;
use tokio_rustls::rustls::pki_types::pem::PemObject;
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::TlsAcceptor;
pub fn load_tls_acceptor(cert_path: &str, key_path: &str) -> DbResult<TlsAcceptor> {
let certs: Vec<CertificateDer<'static>> = CertificateDer::pem_file_iter(cert_path)
.map_err(|e| {
DbError::InternalError(format!("Cannot open TLS cert file {}: {}", cert_path, e))
})?
.collect::<Result<_, _>>()
.map_err(|e| {
DbError::InternalError(format!(
"Invalid TLS certificate chain in {}: {}",
cert_path, e
))
})?;
if certs.is_empty() {
return Err(DbError::InternalError(format!(
"No certificates found in {}",
cert_path
)));
}
let key: PrivateKeyDer<'static> = PrivateKeyDer::from_pem_file(key_path).map_err(|e| {
DbError::InternalError(format!("Cannot load TLS key from {}: {}", key_path, e))
})?;
let config = tokio_rustls::rustls::ServerConfig::builder_with_provider(Arc::new(
tokio_rustls::rustls::crypto::ring::default_provider(),
))
.with_safe_default_protocol_versions()
.map_err(|e| DbError::InternalError(format!("TLS provider error: {}", e)))?
.with_no_client_auth()
.with_single_cert(certs, key)
.map_err(|e| DbError::InternalError(format!("TLS configuration error: {}", e)))?;
tracing::info!(cert = %cert_path, "Native HTTPS/TLS termination enabled");
Ok(TlsAcceptor::from(Arc::new(config)))
}
pub const TLS_HANDSHAKE_CONTENT_TYPE: u8 = 0x16;
pub fn tls_required() -> bool {
matches!(
std::env::var("SOLIDB_TLS_REQUIRE").as_deref(),
Ok("1") | Ok("true")
)
}