use crate::errors::{ConfigError, VetisError};
use log::error;
use serde::{Deserialize, Deserializer};
use std::fs;
#[derive(Clone)]
pub struct SecurityConfigBuilder {
cert: Vec<u8>,
key: Vec<u8>,
ca_cert: Option<Vec<u8>>,
client_auth: bool,
}
impl SecurityConfigBuilder {
pub fn cert_from_bytes(mut self, cert: Vec<u8>) -> Self {
self.cert = cert;
self
}
pub fn cert_from_file(mut self, path: &str) -> Self {
let cert = fs::read(path);
match cert {
Ok(cert) => self.cert = cert,
Err(e) => {
error!("Failed to read certificate file: {}", e);
eprintln!("Failed to read certificate file: {}", e);
}
}
self
}
pub fn key_from_bytes(mut self, key: Vec<u8>) -> Self {
self.key = key;
self
}
pub fn key_from_file(mut self, path: &str) -> Self {
let key = fs::read(path);
match key {
Ok(key) => self.key = key,
Err(e) => {
error!("Failed to read key file: {}", e);
}
}
self
}
pub fn ca_cert_from_bytes(mut self, ca_cert: Vec<u8>) -> Self {
self.ca_cert = Some(ca_cert);
self
}
pub fn ca_cert_from_file(mut self, path: &str) -> Self {
let ca_cert = fs::read(path);
match ca_cert {
Ok(ca_cert) => self.ca_cert = Some(ca_cert),
Err(e) => {
error!("Failed to read CA certificate file: {}", e);
}
}
self
}
pub fn client_auth(mut self, client_auth: bool) -> Self {
self.client_auth = client_auth;
self
}
pub fn build(self) -> Result<SecurityConfig, VetisError> {
if self.cert.is_empty() {
return Err(VetisError::Config(ConfigError::Security(
"Missing certificate".to_string(),
)));
}
if self.key.is_empty() {
return Err(VetisError::Config(ConfigError::Security("Missing key".to_string())));
}
Ok(SecurityConfig {
cert: self.cert,
key: self.key,
ca_cert: self.ca_cert,
client_auth: self.client_auth,
})
}
}
#[derive(Clone, Deserialize)]
pub struct SecurityConfig {
cert: Vec<u8>,
key: Vec<u8>,
ca_cert: Option<Vec<u8>>,
client_auth: bool,
}
impl SecurityConfig {
pub fn builder() -> SecurityConfigBuilder {
SecurityConfigBuilder {
cert: Vec::new(),
key: Vec::new(),
ca_cert: None,
client_auth: false,
}
}
pub fn cert(&self) -> &Vec<u8> {
&self.cert
}
pub fn key(&self) -> &Vec<u8> {
&self.key
}
pub fn ca_cert(&self) -> &Option<Vec<u8>> {
&self.ca_cert
}
pub fn client_auth(&self) -> bool {
self.client_auth
}
}
#[derive(Clone, Deserialize)]
pub struct SecurityConfigFromFile {
cert_from_file: String,
key_from_file: String,
ca_cert_from_file: Option<String>,
client_auth: Option<bool>,
}
pub(crate) fn deserialize_security_from_file<'de, D>(
deserializer: D,
) -> Result<Option<SecurityConfig>, D::Error>
where
D: Deserializer<'de>,
{
let security =
SecurityConfigFromFile::deserialize(deserializer).map_err(serde::de::Error::custom)?;
let mut builder = SecurityConfig::builder()
.cert_from_file(&security.cert_from_file)
.key_from_file(&security.key_from_file);
if let Some(ca_cert_from_file) = security.ca_cert_from_file {
builder = builder.ca_cert_from_file(&ca_cert_from_file);
}
if let Some(client_auth) = security.client_auth {
builder = builder.client_auth(client_auth);
}
builder
.build()
.map_err(serde::de::Error::custom)
.map(Some)
}