use crate::cfg::{parse_bool, CfgParser, ExtCfgBounds};
use crate::core::env::{Env, GetEnv};
use bytesize::ByteSize;
use std::path::PathBuf;
use std::time::Duration;
const DEFAULT_AUDIT_ENABLED: bool = false;
const DEFAULT_AUDIT_REMOTE_VERIFY_SSL: bool = true;
const DEFAULT_AUDIT_REMOTE_TIMEOUT_S: u64 = 5;
#[derive(Clone, Debug, PartialEq)]
pub struct AuditConfig {
pub enabled: bool,
pub quota_size: Option<u64>,
pub remote_verify_ssl: bool,
pub remote_ca_path: Option<PathBuf>,
pub remote_timeout: Duration,
}
impl Default for AuditConfig {
fn default() -> Self {
AuditConfig {
enabled: DEFAULT_AUDIT_ENABLED,
quota_size: None,
remote_verify_ssl: DEFAULT_AUDIT_REMOTE_VERIFY_SSL,
remote_ca_path: None,
remote_timeout: Duration::from_secs(DEFAULT_AUDIT_REMOTE_TIMEOUT_S),
}
}
}
impl<EnvGetter: GetEnv, ExtCfg: ExtCfgBounds> CfgParser<EnvGetter, ExtCfg> {
pub(super) fn parse_audit_config(env: &mut Env<EnvGetter>, api_token: &str) -> AuditConfig {
let default_audit_enabled = if api_token.is_empty() {
DEFAULT_AUDIT_ENABLED
} else {
true
};
AuditConfig {
enabled: parse_bool(
env.get_optional::<String>("RS_AUDIT_ENABLED"),
default_audit_enabled,
),
quota_size: env
.get_optional::<ByteSize>("RS_AUDIT_QUOTA_SIZE")
.map(|size| size.as_u64()),
remote_verify_ssl: env
.get_optional("RS_AUDIT_REMOTE_VERIFY_SSL")
.unwrap_or(DEFAULT_AUDIT_REMOTE_VERIFY_SSL),
remote_ca_path: env
.get_optional::<String>("RS_AUDIT_REMOTE_CA_PATH")
.and_then(|p| {
if p.is_empty() {
None
} else {
Some(PathBuf::from(p))
}
}),
remote_timeout: Duration::from_secs(
env.get_optional("RS_AUDIT_REMOTE_TIMEOUT")
.unwrap_or(DEFAULT_AUDIT_REMOTE_TIMEOUT_S),
),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cfg::tests::MockEnvGetter;
use mockall::predicate::eq;
use rstest::rstest;
use std::env::VarError;
#[rstest]
fn test_audit_config() {
let mut env_getter = MockEnvGetter::new();
env_getter
.expect_get()
.with(eq("RS_AUDIT_ENABLED"))
.return_const(Ok("true".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_QUOTA_SIZE"))
.return_const(Ok("1MB".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_VERIFY_SSL"))
.return_const(Ok("false".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_CA_PATH"))
.return_const(Ok("/tmp/ca.pem".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_TIMEOUT"))
.return_const(Ok("10".to_string()));
let config =
CfgParser::<MockEnvGetter>::parse_audit_config(&mut Env::new(env_getter), "token");
assert_eq!(
config,
AuditConfig {
enabled: true,
quota_size: Some(1_000_000),
remote_verify_ssl: false,
remote_ca_path: Some(PathBuf::from("/tmp/ca.pem")),
remote_timeout: Duration::from_secs(10),
}
);
}
#[rstest]
fn test_default_audit_config_without_api_token() {
let mut env_getter = MockEnvGetter::new();
env_getter
.expect_get()
.return_const(Err(VarError::NotPresent));
let config = CfgParser::<MockEnvGetter>::parse_audit_config(&mut Env::new(env_getter), "");
assert_eq!(config, AuditConfig::default());
}
#[rstest]
fn test_default_audit_config_with_api_token() {
let mut env_getter = MockEnvGetter::new();
env_getter
.expect_get()
.return_const(Err(VarError::NotPresent));
let config =
CfgParser::<MockEnvGetter>::parse_audit_config(&mut Env::new(env_getter), "token");
assert_eq!(
config,
AuditConfig {
enabled: true,
..AuditConfig::default()
}
);
}
#[rstest]
fn test_audit_enabled_can_be_overridden_when_api_token_is_set() {
let mut env_getter = MockEnvGetter::new();
env_getter
.expect_get()
.with(eq("RS_AUDIT_ENABLED"))
.return_const(Ok("false".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_QUOTA_SIZE"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_VERIFY_SSL"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_CA_PATH"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_TIMEOUT"))
.return_const(Err(VarError::NotPresent));
let config =
CfgParser::<MockEnvGetter>::parse_audit_config(&mut Env::new(env_getter), "token");
assert!(!config.enabled);
}
#[rstest]
fn test_empty_ca_path_is_treated_as_none() {
let mut env_getter = MockEnvGetter::new();
env_getter
.expect_get()
.with(eq("RS_AUDIT_ENABLED"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_QUOTA_SIZE"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_VERIFY_SSL"))
.return_const(Err(VarError::NotPresent));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_CA_PATH"))
.return_const(Ok("".to_string()));
env_getter
.expect_get()
.with(eq("RS_AUDIT_REMOTE_TIMEOUT"))
.return_const(Err(VarError::NotPresent));
let config = CfgParser::<MockEnvGetter>::parse_audit_config(&mut Env::new(env_getter), "");
assert_eq!(config.remote_ca_path, None);
}
}