use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Default)]
pub struct TlsClientConfig {
pub ca_cert_path: Option<PathBuf>,
pub client_cert_path: Option<PathBuf>,
pub client_key_path: Option<PathBuf>,
pub server_name: Option<String>,
pub danger_accept_invalid_certs: bool,
}
impl TlsClientConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_ca_cert(mut self, path: impl AsRef<Path>) -> Self {
self.ca_cert_path = Some(path.as_ref().to_path_buf());
self
}
pub fn with_client_cert(
mut self,
cert_path: impl AsRef<Path>,
key_path: impl AsRef<Path>,
) -> Self {
self.client_cert_path = Some(cert_path.as_ref().to_path_buf());
self.client_key_path = Some(key_path.as_ref().to_path_buf());
self
}
pub fn with_server_name(mut self, name: impl Into<String>) -> Self {
self.server_name = Some(name.into());
self
}
#[cfg(any(test, feature = "dangerous-testing"))]
pub fn danger_accept_invalid_certs(mut self) -> Self {
self.danger_accept_invalid_certs = true;
self
}
pub fn is_mtls(&self) -> bool {
self.client_cert_path.is_some() && self.client_key_path.is_some()
}
pub fn to_network_config(&self) -> lnc_network::TlsConfig {
if self.is_mtls() {
lnc_network::TlsConfig::mtls(
self.client_cert_path
.as_ref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default(),
self.client_key_path
.as_ref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default(),
self.ca_cert_path
.as_ref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default(),
)
} else if let Some(ref ca_path) = self.ca_cert_path {
lnc_network::TlsConfig::client(Some(ca_path.to_string_lossy().to_string()))
} else {
lnc_network::TlsConfig::client(None::<String>)
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn test_tls_config_default() {
let config = TlsClientConfig::new();
assert!(config.ca_cert_path.is_none());
assert!(config.client_cert_path.is_none());
assert!(!config.is_mtls());
}
#[test]
fn test_tls_config_with_ca() {
let config = TlsClientConfig::new().with_ca_cert("/path/to/ca.pem");
assert_eq!(
config.ca_cert_path.as_ref().map(|p| p.to_str()),
Some(Some("/path/to/ca.pem"))
);
assert!(!config.is_mtls());
}
#[test]
fn test_tls_config_mtls() {
let config = TlsClientConfig::new()
.with_ca_cert("/path/to/ca.pem")
.with_client_cert("/path/to/cert.pem", "/path/to/key.pem");
assert!(config.is_mtls());
}
#[test]
fn test_tls_config_with_server_name() {
let config = TlsClientConfig::new().with_server_name("lance.example.com");
assert_eq!(config.server_name, Some("lance.example.com".to_string()));
}
#[test]
fn test_client_config_with_tls() {
use crate::ClientConfig;
let tls = TlsClientConfig::new().with_server_name("lance.example.com");
let config = ClientConfig::new("127.0.0.1:1992").with_tls(tls);
assert!(config.is_tls_enabled());
assert!(config.tls.is_some());
assert_eq!(
config.tls.as_ref().unwrap().server_name,
Some("lance.example.com".to_string())
);
}
#[test]
fn test_client_config_without_tls() {
use crate::ClientConfig;
let config = ClientConfig::new("127.0.0.1:1992");
assert!(!config.is_tls_enabled());
assert!(config.tls.is_none());
}
}