Commit 4024cfa9 authored by MrMan's avatar MrMan

Progress wiring up userdb and passdb config template

parent d7794aec
use std::fs::{create_dir_all, File, copy};
use std::fs::{File, copy};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio, Child as ChildProcess};
......@@ -7,15 +7,18 @@ use std::sync::mpsc::{sync_channel, SyncSender, Receiver};
use askama::Template;
use chrono::prelude::Local;
use make_absolute_path;
use ensure_directory;
use simple_signal::{Signal};
use simple_signal;
use components::db::*;
use components::*;
use config::{DovecotCfg, DovecotDBSettings};
use config::{DovecotCfg, DovecotDBSettings, DovecotSettingName};
const DOVECOT_CONF_FILENAME: &'static str = "dovecot.conf";
const DOVECOT_SQL_CONF_FILENAME: &'static str = "dovecot-sql.conf.ext";
const DOVECOT_USERDB_CONF_FILENAME: &'static str = "dovecot-sql-userdb.conf.ext";
const DOVECOT_PASSDB_CONF_FILENAME: &'static str = "dovecot-sql-passdb.conf.ext";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum DovecotCmd {
......@@ -191,7 +194,10 @@ struct DovecotConfTemplate<'a> {
unix_socket_path: &'a String,
userdb: &'a Option<DovecotDBSettings>,
userdb_conf_abs_path: String,
passdb: &'a Option<DovecotDBSettings>,
passdb_conf_abs_path: String,
}
#[derive(Template)]
......@@ -199,8 +205,7 @@ struct DovecotConfTemplate<'a> {
struct DovecotUserDBConfTemplate<'a> {
filename: &'a str,
generation_time: String,
userdb: &'a Option<DovecotDBSettings>,
settings: &'a DovecotDBSettings,
}
#[derive(Template)]
......@@ -209,7 +214,7 @@ struct DovecotPassDBConfTemplate<'a> {
filename: &'a str,
generation_time: String,
passdb: &'a Option<DovecotDBSettings>,
settings: &'a DovecotDBSettings,
}
impl FileConfigurable<DovecotCfg> for Dovecot {
......@@ -217,7 +222,7 @@ impl FileConfigurable<DovecotCfg> for Dovecot {
info!("updating on-disk configuration for dovecot");
// Ensure configuration directory exists
let config_dir_abs_path = ensure_directory(&self.cfg.config_output_dir);
let config_dir_abs_path = ensure_directory(&self.cfg.config_output_dir)?;
// Build dovecot conf template
let main_conf_tmpl = DovecotConfTemplate {
......@@ -228,51 +233,57 @@ impl FileConfigurable<DovecotCfg> for Dovecot {
unix_socket_path: &self.cfg.unix_socket_path,
userdb: &self.cfg.userdb,
passdb: &self.cfg.passdb,
};
// Build userdb SQL configuration template
let userdb_conf_tmpl = DovecotUserDBConfTemplate {
filename: DOVECOT_USERDB_CONF_FILENAME,
generation_time: Local::now().to_string(),
userdb: &self.cfg.userdb,
};
userdb_conf_abs_path: String::from(""),
// Build passdb SQL configuration template
let passdb_conf_tmpl = DovecotPassDBConfTemplate {
filename: DOVECOT_PASSDB_CONF_FILENAME,
generation_time: Local::now().to_string(),
passdb: &self.cfg.passdb,
passdb_conf_abs_path: String::from(""),
};
// Generate file paths for the dovecot.conf file
let output_dir = Path::new(&self.cfg.config_output_dir);
let paths_and_tmpl: Vec<(Path, Template)> = vec!([
(output_dir.join(DOVECOT_CONF_FILENAME), main_conf_tmpl),
(output_dir.join(DOVECOT_USERDB_CONF_FILENAME), userdb_conf_tmpl),
(output_dir.join(DOVECOT_PASSDB_CONF_FILENAME), passdb_conf_tmpl),
]);
// let dovecot_conf_path = Path::new(&self.cfg.config_output_dir).join(DOVECOT_CONF_FILENAME);
// let dovecot_conf_file_path = make_absolute_path(dovecot_conf_path.to_path_buf())?;
// // Generate file paths for the userdb conf
// let dovecot_sql_conf_path = Path::new(&self.cfg.config_output_dir).join(DOVECOT_SQL_CONF_FILENAME);
// let dovecot_sql_conf_file_path = make_absolute_path(dovecot_sql_conf_path.to_path_buf())?;
// // Generate paths for configuration files
// let dovecot_conf_path = config_dir_abs_path.join(dovecot_conf.filename);
// let dovecot_sql_conf_path = config_dir_abs_path.join(dovecot_sql_conf.filename);
// // Render the file contents
// debug!("{} will be written to [{:?}]", &dovecot_conf.filename, dovecot_conf_path.to_str());
// debug!("{} will be written to [{:?}]", &dovecot_sql_conf.filename, dovecot_sql_conf_path.to_str());
// let mut dovecot_conf_file = File::create(dovecot_conf_path)?;
// let mut dovecot_sql_conf_file = File::create(dovecot_sql_conf_path)?;
let main_conf_path = output_dir.join(DOVECOT_CONF_FILENAME);
let main_conf_abs_path = make_absolute_path(main_conf_path.to_path_buf())?;
// Render the main config
debug!("{} will be written to [{}]", &main_conf_tmpl.filename, &main_conf_abs_path);
let mut main_conf_file = File::create(main_conf_path)?;
main_conf_file.write_all(main_conf_tmpl.render()?.as_bytes())?;
// Write the userdb sql conf if settings were specified
if let Some(settings) = &self.cfg.userdb {
// Build userdb SQL configuration template
let tmpl = DovecotUserDBConfTemplate {
filename: DOVECOT_USERDB_CONF_FILENAME,
generation_time: Local::now().to_string(),
settings,
};
let conf_path = output_dir.join(DOVECOT_USERDB_CONF_FILENAME);
let conf_abs_path = make_absolute_path(main_conf_path.to_path_buf())?;
// Render the main config
debug!("{} will be written to [{}]", &tmpl.filename, &conf_abs_path);
let mut conf_file = File::create(conf_path)?;
conf_file.write_all(tmpl.render()?.as_bytes())?;
}
// dovecot_conf_file.write_all(dovecot_conf.render()?.as_bytes())?;
// dovecot_sql_conf_file.write_all(dovecot_sql_conf.render()?.as_bytes())?;
// Write the passdb sql conf if settings were specified
if let Some(settings) = &self.cfg.passdb {
// Build passdb SQL configuration template
let tmpl = DovecotPassDBConfTemplate {
filename: DOVECOT_PASSDB_CONF_FILENAME,
generation_time: Local::now().to_string(),
settings,
};
let conf_path = output_dir.join(DOVECOT_PASSDB_CONF_FILENAME);
let conf_abs_path = make_absolute_path(main_conf_path.to_path_buf())?;
// Render the main config
debug!("{} will be written to [{}]", &tmpl.filename, &conf_abs_path);
let mut conf_file = File::create(conf_path)?;
conf_file.write_all(tmpl.render()?.as_bytes())?;
}
debug!("successfully wrote dovecot configuration files to disk");
Ok(())
......@@ -280,7 +291,7 @@ impl FileConfigurable<DovecotCfg> for Dovecot {
fn install_config(&self) -> Result<(), Error> {
// Generate the directories the files are going to go into
let config_dir_path = Path::new(&self.cfg.config_dir);
let config_dir_path = Path::new(&self.cfg.config_output_dir);
let config_output_dir_path = Path::new(&self.cfg.config_output_dir);
debug!(
"installing config file(s) from directory [{:?}] to [{:?}]",
......@@ -288,9 +299,8 @@ impl FileConfigurable<DovecotCfg> for Dovecot {
config_output_dir_path.to_str(),
);
// Ensure config output path exists
debug!("ensuring configuration output path [{:?}] exists...", config_output_dir_path);
if !config_output_dir_path.exists() { create_dir_all(&config_output_dir_path)?; }
// Ensure configuration directory exists
let config_dir_abs_path = ensure_directory(&self.cfg.config_output_dir)?;
// Copy dovecot.conf
let dovecot_conf_from = config_dir_path.clone().join(DOVECOT_CONF_FILENAME);
......@@ -298,11 +308,17 @@ impl FileConfigurable<DovecotCfg> for Dovecot {
debug!("copying dovecot.conf from [{:?}] to [{:?}]", dovecot_conf_from, dovecot_conf_to);
copy(&dovecot_conf_from, &dovecot_conf_to)?;
// Copy dovecot-sql.conf.ext
let dovecot_sql_conf_from = config_dir_path.clone().join(DOVECOT_SQL_CONF_FILENAME);
let dovecot_sql_conf_to = config_output_dir_path.clone().join(DOVECOT_SQL_CONF_FILENAME);
debug!("copying dovecot-sql.conf.ext from [{:?}] to [{:?}]", dovecot_sql_conf_from, dovecot_sql_conf_to);
copy(&dovecot_sql_conf_from, &dovecot_sql_conf_to)?;
// Copy dovecot userdb conf
let userdb_conf_from = config_dir_path.clone().join(DOVECOT_USERDB_CONF_FILENAME);
let userdb_conf_to = config_output_dir_path.clone().join(DOVECOT_PASSDB_CONF_FILENAME);
debug!("copying dovecot-sql.conf.ext from [{:?}] to [{:?}]", userdb_conf_from, userdb_conf_to);
copy(&userdb_conf_from, &userdb_conf_to)?;
// Copy dovecot passdb conf
let passdb_conf_from = config_dir_path.clone().join(DOVECOT_PASSDB_CONF_FILENAME);
let passdb_conf_to = config_output_dir_path.clone().join(DOVECOT_PASSDB_CONF_FILENAME);
debug!("copying dovecot-sql.conf.ext from [{:?}] to [{:?}]", passdb_conf_from, passdb_conf_to);
copy(&passdb_conf_from, &passdb_conf_to)?;
Ok(())
}
......
......@@ -205,6 +205,20 @@ impl From<String> for DBType {
}
}
/// For objects (mostly enums) that have a dovecot setting name
pub trait DovecotSettingName {
fn dovecot_setting_name(self) -> &'static str;
}
impl DovecotSettingName for DBType {
fn dovecot_setting_name(self) -> &'static str {
match self {
SQLite => "sqlite",
PostgresSQL => "pgsql",
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum AuthBackendType {
Dovecot
......@@ -226,11 +240,10 @@ pub struct DovecotCfg {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DovecotDBSettings {
driver: DBType,
connect: String,
user_query: String,
pass_query: String,
iterate_query: String,
pub driver: DBType,
pub connect: String,
pub query: String,
pub iterate_query: String,
}
///////////////
......
......@@ -24,8 +24,8 @@ use std::env;
use std::process;
use clap::{App, Arg, SubCommand, ArgMatches};
use components::Error;
use std::path::PathBuf;
use std::fs::canonicalize;
use std::path::{Path, PathBuf};
use std::fs::{canonicalize, create_dir_all};
use std::env::current_dir;
const CONFIG_PATH_ENV_VAR: &str = "CONFIG_PATH";
......@@ -172,15 +172,14 @@ pub fn make_absolute_path_from_str(path: &String) -> Result<String, Error> {
/// Ensure a given directory exists (creating if it necessary), returning the absolute path to the directory)
pub fn ensure_directory(path: &str) -> Result<String, Error> {
// Generate the directories the files are going to go into
let config_dir = Path::new(path);
let config_dir_abs_path = make_absolute_path(config_dir.to_path_buf())?;
let dir = Path::new(path);
debug!("ensuring configuration output path [{:?}] exists...", dir.to_str());
// Ensure config directory exists and is a proper directory
debug!("writing config files to dir [{:?}]", config_dir_abs_path);
if !config_dir_abs_path.exists() { create_dir_all(&config_dir_abs_path)?; }
if config_dir_abs_path.exists() && !config_dir_abs_path.is_dir() {
return Err(Error::InvalidEnvironment("Provided config dir is not a directory"));
if !dir.exists() { create_dir_all(&dir)?; }
if dir.exists() && !dir.is_dir() {
return Err(Error::InvalidEnvironment(&format!("Provided directory [{:?}] is invalid", dir.to_str())));
}
Ok(config_dr_abs_path)
make_absolute_path(dir.to_path_buf())
}
......@@ -145,13 +145,10 @@
# Query to get a list of all usernames.
#iterate_query = SELECT username AS user FROM users
driver = sqlite
connect = {{ abs_db_path }}
driver = {{ settings.driver.dovecot_setting_name() }}
connect = {{ settings.connect }}
password_query = SELECT username, domain, password \
FROM mailbox_users WHERE username = '%n' AND domain = '%d'
user_query = SELECT home, uid, gid FROM users WHERE username = '%n' AND domain = '%d'
pass_query = {{ settings.query }}
# For using doveadm -A:
iterate_query = SELECT username, domain FROM users
\ No newline at end of file
iterate_query = {{ settings.iterate_query }}
\ No newline at end of file
......@@ -145,13 +145,10 @@
# Query to get a list of all usernames.
#iterate_query = SELECT username AS user FROM users
driver = sqlite
connect = {{ abs_db_path }}
driver = {{ settings.driver.dovecot_setting_name() }}
connect = {{ settings.connect }}
password_query = SELECT username, domain, password \
FROM mailbox_users WHERE username = '%n' AND domain = '%d'
user_query = SELECT home, uid, gid FROM users WHERE username = '%n' AND domain = '%d'
user_query = {{ settings.query }}
# For using doveadm -A:
iterate_query = SELECT username, domain FROM users
\ No newline at end of file
iterate_query = {{ settings.iterate_query }}
\ No newline at end of file
{% match db_settings.userdb %}
{% when Some with (settings) %}
{% match userdb %}
{% when Some with (userdb_settings) %}
userdb {
driver = {{ settings.userdb.driver }}
args = {{ user_db_conf_abs_path }}
driver = {{ userdb_settings.driver.dovecot_setting_name() }}
args = {{ userdb_conf_abs_path }}
}
{% when None %}
{% endmatch %}
{% match db_settings.passdb %}
{% when Some with (settings) %}
{% match passdb %}
{% when Some with (passdb_settings) %}
passdb {
driver = {{ settings.passdb.driver }}
args = {{ pass_db_conf_abs_path }}
driver = {{ passdb_settings.driver.dovecot_setting_name() }}
args = {{ passdb_conf_abs_path }}
}
{% when None %}
{% endmatch %}
service auth {
unix_listener {{ db_settings.unix_socket_path }} {
unix_listener {{ unix_socket_path }} {
mode = 0666
user = postfix
group = postfix
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment