lldap/src/infra/configuration.rs

122 lines
3.6 KiB
Rust
Raw Normal View History

2021-08-26 19:56:42 +00:00
use anyhow::{Context, Result};
2021-03-02 19:30:43 +00:00
use figment::{
providers::{Env, Format, Serialized, Toml},
Figment,
};
use lldap_model::opaque::{server::ServerSetup, KeyPair};
2021-03-02 19:30:43 +00:00
use serde::{Deserialize, Serialize};
2021-03-02 19:13:58 +00:00
use crate::infra::cli::RunOpts;
2021-03-02 19:51:33 +00:00
#[derive(Clone, Debug, Deserialize, Serialize, derive_builder::Builder)]
#[builder(
pattern = "owned",
default = "Configuration::default()",
build_fn(name = "private_build", validate = "Self::validate")
)]
2021-03-02 19:30:43 +00:00
pub struct Configuration {
2021-03-02 22:07:01 +00:00
pub ldap_port: u16,
pub ldaps_port: u16,
pub http_port: u16,
pub jwt_secret: String,
pub ldap_base_dn: String,
2021-03-12 08:33:43 +00:00
pub ldap_user_dn: String,
pub ldap_user_pass: String,
pub database_url: String,
2021-03-02 22:07:01 +00:00
pub verbose: bool,
pub key_file: String,
#[serde(skip)]
#[builder(field(private), setter(strip_option))]
server_setup: Option<ServerSetup>,
2021-03-02 19:30:43 +00:00
}
impl ConfigurationBuilder {
#[cfg(test)]
pub fn build(self) -> Result<Configuration> {
let server_setup = get_server_setup(self.key_file.as_deref().unwrap_or("server_key"))?;
Ok(self.server_setup(server_setup).private_build()?)
}
fn validate(&self) -> Result<(), String> {
if self.server_setup.is_none() {
Err("Don't use `private_build`, use `build` instead".to_string())
} else {
Ok(())
2021-03-02 19:30:43 +00:00
}
}
}
impl Configuration {
pub fn get_server_setup(&self) -> &ServerSetup {
self.server_setup.as_ref().unwrap()
}
pub fn get_server_keys(&self) -> &KeyPair {
self.get_server_setup().keypair()
}
fn merge_with_cli(mut self: Configuration, cli_opts: RunOpts) -> Configuration {
if cli_opts.verbose {
2021-03-02 22:07:01 +00:00
self.verbose = true;
}
if let Some(port) = cli_opts.ldap_port {
self.ldap_port = port;
}
if let Some(port) = cli_opts.ldaps_port {
self.ldaps_port = port;
}
2021-03-02 22:07:01 +00:00
self
}
pub(super) fn default() -> Self {
Configuration {
ldap_port: 3890,
ldaps_port: 6360,
http_port: 17170,
jwt_secret: String::from("secretjwtsecret"),
ldap_base_dn: String::from("dc=example,dc=com"),
// cn=admin,dc=example,dc=com
ldap_user_dn: String::from("admin"),
ldap_user_pass: String::from("password"),
database_url: String::from("sqlite://users.db?mode=rwc"),
verbose: false,
key_file: String::from("server_key"),
server_setup: None,
}
}
}
fn get_server_setup(file_path: &str) -> Result<ServerSetup> {
use std::path::Path;
let path = Path::new(file_path);
if path.exists() {
2021-08-26 19:56:42 +00:00
let bytes =
std::fs::read(file_path).context(format!("Could not read key file `{}`", file_path))?;
Ok(ServerSetup::deserialize(&bytes)?)
} else {
let mut rng = rand::rngs::OsRng;
let server_setup = ServerSetup::new(&mut rng);
2021-08-26 19:56:42 +00:00
std::fs::write(path, server_setup.serialize()).context(format!(
"Could not write the generated server setup to file `{}`",
file_path,
))?;
Ok(server_setup)
}
}
pub fn init(cli_opts: RunOpts) -> Result<Configuration> {
let config_file = cli_opts.config_file.clone();
let config: Configuration = Figment::from(Serialized::defaults(Configuration::default()))
.merge(Toml::file(config_file))
.merge(Env::prefixed("LLDAP_"))
.extract()?;
2021-03-02 19:30:43 +00:00
let mut config = config.merge_with_cli(cli_opts);
config.server_setup = Some(get_server_setup(&config.key_file)?);
2021-03-02 19:30:43 +00:00
Ok(config)
2021-03-02 19:13:58 +00:00
}