#[derive(Debug, Clone)]
pub struct TlsServerConfig {
pub cert_path: String,
pub key_path: String,
pub client_ca_path: Option<String>,
}
impl TlsServerConfig {
pub fn new(cert_path: impl Into<String>, key_path: impl Into<String>) -> Self {
Self {
cert_path: cert_path.into(),
key_path: key_path.into(),
client_ca_path: None,
}
}
pub fn with_client_ca(mut self, client_ca_path: impl Into<String>) -> Self {
self.client_ca_path = Some(client_ca_path.into());
self
}
}
#[derive(Debug, Clone, Default)]
pub struct TlsClientConfig {
pub ca_cert_path: Option<String>,
pub server_name: Option<String>,
pub client_cert_path: Option<String>,
pub client_key_path: Option<String>,
pub danger_accept_invalid_certs: bool,
}
#[derive(Debug, Clone, Default)]
pub struct TlsClientConfigBuilder {
config: TlsClientConfig,
}
impl TlsClientConfigBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_ca_cert_path(mut self, path: impl Into<String>) -> Self {
self.config.ca_cert_path = Some(path.into());
self
}
pub fn with_server_name(mut self, name: impl Into<String>) -> Self {
self.config.server_name = Some(name.into());
self
}
pub fn with_client_auth(
mut self,
cert_path: impl Into<String>,
key_path: impl Into<String>,
) -> Self {
self.config.client_cert_path = Some(cert_path.into());
self.config.client_key_path = Some(key_path.into());
self
}
pub fn with_danger_accept_invalid_certs(mut self) -> Self {
self.config.danger_accept_invalid_certs = true;
self
}
pub fn build(self) -> TlsClientConfig {
self.config
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn server_config_defaults_have_no_client_ca() {
let cfg = TlsServerConfig::new("cert.pem", "key.pem");
assert_eq!(cfg.cert_path, "cert.pem");
assert_eq!(cfg.key_path, "key.pem");
assert!(cfg.client_ca_path.is_none());
}
#[test]
fn server_config_client_ca_enables_mutual_tls() {
let cfg = TlsServerConfig::new("cert.pem", "key.pem").with_client_ca("ca.pem");
assert_eq!(cfg.client_ca_path.as_deref(), Some("ca.pem"));
}
#[test]
fn client_builder_sets_every_field() {
let cfg = TlsClientConfigBuilder::new()
.with_ca_cert_path("ca.pem")
.with_server_name("example.test")
.with_client_auth("client.pem", "client.key")
.build();
assert_eq!(cfg.ca_cert_path.as_deref(), Some("ca.pem"));
assert_eq!(cfg.server_name.as_deref(), Some("example.test"));
assert_eq!(cfg.client_cert_path.as_deref(), Some("client.pem"));
assert_eq!(cfg.client_key_path.as_deref(), Some("client.key"));
assert!(!cfg.danger_accept_invalid_certs);
}
#[test]
fn client_builder_danger_mode() {
let cfg = TlsClientConfigBuilder::new()
.with_danger_accept_invalid_certs()
.build();
assert!(cfg.danger_accept_invalid_certs);
assert!(cfg.ca_cert_path.is_none());
}
#[test]
fn client_config_default_is_secure() {
let cfg = TlsClientConfig::default();
assert!(cfg.ca_cert_path.is_none());
assert!(!cfg.danger_accept_invalid_certs);
}
}