2021-06-02 01:42:40 +02:00
|
|
|
//! These contain the server "cores". These are able to startup the server
|
|
|
|
//! (bootstrap) to a running state and then execute tasks. This is where modules
|
|
|
|
//! are logically ordered based on their depenedncies for execution. Some of these
|
|
|
|
//! are task-only i.e. reindexing, and some of these launch the server into a
|
|
|
|
//! fully operational state (https, ldap, etc).
|
|
|
|
//!
|
|
|
|
//! Generally, this is the "entry point" where the server begins to run, and
|
|
|
|
//! the entry point for all client traffic which is then directed to the
|
2021-07-24 03:12:35 +02:00
|
|
|
//! various `actors`.
|
2021-06-02 01:42:40 +02:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
mod https;
|
2020-06-10 04:07:43 +02:00
|
|
|
mod ldaps;
|
2020-08-04 04:58:11 +02:00
|
|
|
use libc::umask;
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
// use crossbeam::channel::unbounded;
|
2021-07-08 02:09:15 +02:00
|
|
|
use crate::prelude::*;
|
2020-03-07 01:49:39 +01:00
|
|
|
use std::sync::Arc;
|
2020-09-06 00:44:35 +02:00
|
|
|
use tokio::sync::mpsc::unbounded_channel as unbounded;
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
use crate::config::Configuration;
|
|
|
|
|
|
|
|
// SearchResult
|
2020-09-06 00:44:35 +02:00
|
|
|
// use self::ctx::ServerCtx;
|
2020-03-07 01:49:39 +01:00
|
|
|
use crate::actors::v1_read::QueryServerReadV1;
|
|
|
|
use crate::actors::v1_write::QueryServerWriteV1;
|
|
|
|
use crate::async_log;
|
2021-04-14 01:56:40 +02:00
|
|
|
use crate::be::{Backend, BackendConfig, BackendTransaction, FsType};
|
2020-03-07 01:49:39 +01:00
|
|
|
use crate::crypto::setup_tls;
|
2020-08-24 04:15:21 +02:00
|
|
|
use crate::idm::server::{IdmServer, IdmServerDelayed};
|
2020-03-07 01:49:39 +01:00
|
|
|
use crate::interval::IntervalActor;
|
2020-06-10 04:07:43 +02:00
|
|
|
use crate::ldap::LdapServer;
|
2020-03-07 01:49:39 +01:00
|
|
|
use crate::schema::Schema;
|
2020-09-06 00:44:35 +02:00
|
|
|
use crate::status::StatusActor;
|
2021-07-08 02:09:15 +02:00
|
|
|
use crate::utils::{duration_from_epoch_now, touch_file_or_quit};
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
use kanidm_proto::v1::OperationError;
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
use async_std::task;
|
2020-05-07 06:08:06 +02:00
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// === internal setup helpers
|
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
fn setup_backend(config: &Configuration, schema: &Schema) -> Result<Backend, OperationError> {
|
2021-02-21 06:04:58 +01:00
|
|
|
setup_backend_vacuum(config, schema, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn setup_backend_vacuum(
|
|
|
|
config: &Configuration,
|
|
|
|
schema: &Schema,
|
|
|
|
vacuum: bool,
|
|
|
|
) -> Result<Backend, OperationError> {
|
2020-06-24 13:17:46 +02:00
|
|
|
// Limit the scope of the schema txn.
|
2020-09-06 00:44:35 +02:00
|
|
|
// let schema_txn = task::block_on(schema.write());
|
2020-06-24 13:17:46 +02:00
|
|
|
let schema_txn = schema.write();
|
|
|
|
let idxmeta = schema_txn.reload_idxmeta();
|
|
|
|
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit_be = AuditScope::new("backend_setup", uuid::Uuid::new_v4(), config.log_level);
|
2020-03-07 01:49:39 +01:00
|
|
|
let pool_size: u32 = config.threads as u32;
|
2020-08-04 08:52:57 +02:00
|
|
|
let fstype: FsType = if config
|
|
|
|
.db_fs_type
|
|
|
|
.as_ref()
|
|
|
|
.map(|s| s == "zfs")
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-05-21 08:35:09 +02:00
|
|
|
FsType::Zfs
|
2020-08-04 08:52:57 +02:00
|
|
|
} else {
|
|
|
|
FsType::Generic
|
|
|
|
};
|
|
|
|
|
2021-04-14 01:56:40 +02:00
|
|
|
let cfg = BackendConfig::new(
|
2020-08-04 08:52:57 +02:00
|
|
|
config.db_path.as_str(),
|
|
|
|
pool_size,
|
|
|
|
fstype,
|
2021-04-14 01:56:40 +02:00
|
|
|
config.db_arc_size,
|
2020-08-04 08:52:57 +02:00
|
|
|
);
|
2021-04-14 01:56:40 +02:00
|
|
|
|
|
|
|
let be = Backend::new(&mut audit_be, cfg, idxmeta, vacuum);
|
2020-03-07 01:49:39 +01:00
|
|
|
// debug!
|
2020-06-05 06:01:20 +02:00
|
|
|
audit_be.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
be
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO #54: We could move most of the be/schema/qs setup and startup
|
|
|
|
// outside of this call, then pass in "what we need" in a cloneable
|
|
|
|
// form, this way we could have seperate Idm vs Qs threads, and dedicated
|
|
|
|
// threads for write vs read
|
|
|
|
fn setup_qs_idms(
|
|
|
|
audit: &mut AuditScope,
|
|
|
|
be: Backend,
|
2020-06-24 13:17:46 +02:00
|
|
|
schema: Schema,
|
2020-12-02 02:12:07 +01:00
|
|
|
config: &Configuration,
|
2020-08-24 04:15:21 +02:00
|
|
|
) -> Result<(QueryServer, IdmServer, IdmServerDelayed), OperationError> {
|
2020-03-07 01:49:39 +01:00
|
|
|
// Create a query_server implementation
|
2021-06-29 06:23:39 +02:00
|
|
|
let query_server = QueryServer::new(audit, be, schema);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// TODO #62: Should the IDM parts be broken out to the IdmServer?
|
|
|
|
// What's important about this initial setup here is that it also triggers
|
|
|
|
// the schema and acp reload, so they are now configured correctly!
|
|
|
|
// Initialise the schema core.
|
|
|
|
//
|
|
|
|
// Now search for the schema itself, and validate that the system
|
|
|
|
// in memory matches the BE on disk, and that it's syntactically correct.
|
|
|
|
// Write it out if changes are needed.
|
2020-03-22 02:31:02 +01:00
|
|
|
query_server.initialise_helper(audit, duration_from_epoch_now())?;
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// We generate a SINGLE idms only!
|
|
|
|
|
2020-12-02 02:12:07 +01:00
|
|
|
let (idms, idms_delayed) = IdmServer::new(audit, query_server.clone(), config.origin.clone())?;
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-08-24 04:15:21 +02:00
|
|
|
Ok((query_server, idms, idms_delayed))
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
|
2021-07-01 06:51:25 +02:00
|
|
|
macro_rules! dbscan_setup_be {
|
|
|
|
(
|
|
|
|
$audit:expr,
|
|
|
|
$config:expr
|
|
|
|
) => {{
|
|
|
|
let schema = match Schema::new(&mut $audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
$audit.write_log();
|
|
|
|
error!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match setup_backend($config, &schema) {
|
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dbscan_list_indexes_core(config: &Configuration) {
|
|
|
|
let mut audit = AuditScope::new(
|
|
|
|
"dbscan_list_indexes",
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
config.log_level,
|
|
|
|
);
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = dbscan_setup_be!(audit, config);
|
2021-07-01 06:51:25 +02:00
|
|
|
let be_rotxn = be.read();
|
|
|
|
|
2021-08-26 03:48:03 +02:00
|
|
|
match be_rotxn.list_indexes() {
|
2021-07-01 06:51:25 +02:00
|
|
|
Ok(mut idx_list) => {
|
|
|
|
idx_list.sort_unstable();
|
|
|
|
idx_list.iter().for_each(|idx_name| {
|
|
|
|
println!("{}", idx_name);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Failed to retrieve index list: {:?}", e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dbscan_list_id2entry_core(config: &Configuration) {
|
|
|
|
let mut audit = AuditScope::new(
|
|
|
|
"dbscan_list_id2entry",
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
config.log_level,
|
|
|
|
);
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = dbscan_setup_be!(audit, config);
|
2021-07-01 06:51:25 +02:00
|
|
|
let be_rotxn = be.read();
|
|
|
|
|
2021-08-26 03:48:03 +02:00
|
|
|
match be_rotxn.list_id2entry() {
|
2021-07-01 06:51:25 +02:00
|
|
|
Ok(mut id_list) => {
|
|
|
|
id_list.sort_unstable_by_key(|k| k.0);
|
|
|
|
id_list.iter().for_each(|(id, value)| {
|
|
|
|
println!("{:>8}: {}", id, value);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Failed to retrieve id2entry list: {:?}", e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dbscan_list_index_analysis_core(config: &Configuration) {
|
|
|
|
let mut audit = AuditScope::new(
|
|
|
|
"dbscan_list_index_analysis",
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
config.log_level,
|
|
|
|
);
|
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let _be = dbscan_setup_be!(audit, config);
|
2021-07-01 06:51:25 +02:00
|
|
|
// TBD in after slopes merge.
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dbscan_list_index_core(config: &Configuration, index_name: &str) {
|
|
|
|
let mut audit = AuditScope::new("dbscan_list_index", uuid::Uuid::new_v4(), config.log_level);
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = dbscan_setup_be!(audit, config);
|
2021-07-01 06:51:25 +02:00
|
|
|
let be_rotxn = be.read();
|
|
|
|
|
2021-08-26 03:48:03 +02:00
|
|
|
match be_rotxn.list_index_content(index_name) {
|
2021-07-01 06:51:25 +02:00
|
|
|
Ok(mut idx_list) => {
|
|
|
|
idx_list.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
|
|
|
idx_list.iter().for_each(|(key, value)| {
|
|
|
|
println!("{:>50}: {:?}", key, value);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Failed to retrieve index list: {:?}", e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dbscan_get_id2entry_core(config: &Configuration, id: u64) {
|
|
|
|
let mut audit = AuditScope::new(
|
|
|
|
"dbscan_get_id2entry",
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
config.log_level,
|
|
|
|
);
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = dbscan_setup_be!(audit, config);
|
2021-07-01 06:51:25 +02:00
|
|
|
let be_rotxn = be.read();
|
|
|
|
|
2021-08-26 03:48:03 +02:00
|
|
|
match be_rotxn.get_id2entry(id) {
|
2021-07-01 06:51:25 +02:00
|
|
|
Ok((id, value)) => println!("{:>8}: {}", id, value),
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Failed to retrieve id2entry value: {:?}", e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
pub fn backup_server_core(config: &Configuration, dst_path: &str) {
|
2020-06-24 13:17:46 +02:00
|
|
|
let mut audit = AuditScope::new("backend_backup", uuid::Uuid::new_v4(), config.log_level);
|
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
let be_ro_txn = be.read();
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = be_ro_txn.backup(&mut audit, dst_path);
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
match r {
|
|
|
|
Ok(_) => info!("Backup success!"),
|
|
|
|
Err(e) => {
|
|
|
|
error!("Backup failed: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// Let the txn abort, even on success.
|
|
|
|
}
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
pub fn restore_server_core(config: &Configuration, dst_path: &str) {
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit = AuditScope::new("backend_restore", uuid::Uuid::new_v4(), config.log_level);
|
2021-09-15 00:24:37 +02:00
|
|
|
touch_file_or_quit(config.db_path.as_str());
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// First, we provide the in-memory schema so that core attrs are indexed correctly.
|
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
2020-06-07 01:53:10 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema) {
|
2020-06-24 13:17:46 +02:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
2021-07-08 02:09:15 +02:00
|
|
|
error!("Failed to setup backend: {:?}", e);
|
2020-06-24 13:17:46 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
};
|
2020-06-24 13:17:46 +02:00
|
|
|
|
|
|
|
let be_wr_txn = be.write();
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = be_wr_txn
|
|
|
|
.restore(&mut audit, dst_path)
|
|
|
|
.and_then(|_| be_wr_txn.commit(&mut audit));
|
|
|
|
|
|
|
|
if r.is_err() {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Failed to restore database: {:?}", r);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
2020-06-07 01:53:10 +02:00
|
|
|
info!("Database loaded successfully");
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
info!("Attempting to init query server ...");
|
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let (qs, _idms, _idms_delayed) = match setup_qs_idms(&mut audit, be, schema, config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to setup query server or idm server -> {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
info!("Success!");
|
|
|
|
|
|
|
|
info!("Start reindex phase ...");
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let qs_write = task::block_on(qs.write_async(duration_from_epoch_now()));
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = qs_write
|
|
|
|
.reindex(&mut audit)
|
|
|
|
.and_then(|_| qs_write.commit(&mut audit));
|
|
|
|
|
|
|
|
match r {
|
|
|
|
Ok(_) => info!("Reindex Success!"),
|
|
|
|
Err(e) => {
|
2020-06-07 01:53:10 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Restore failed: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
2020-06-07 01:53:10 +02:00
|
|
|
|
|
|
|
info!("✅ Restore Success!");
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
pub fn reindex_server_core(config: &Configuration) {
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit = AuditScope::new("server_reindex", uuid::Uuid::new_v4(), config.log_level);
|
2020-06-24 13:17:46 +02:00
|
|
|
eprintln!("Start Index Phase 1 ...");
|
2020-03-07 01:49:39 +01:00
|
|
|
// First, we provide the in-memory schema so that core attrs are indexed correctly.
|
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Failed to setup in memory schema: {:?}", e);
|
2020-03-07 01:49:39 +01:00
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema) {
|
2020-06-24 13:17:46 +02:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
};
|
2020-06-24 13:17:46 +02:00
|
|
|
|
|
|
|
// Reindex only the core schema attributes to bootstrap the process.
|
|
|
|
let be_wr_txn = be.write();
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = be_wr_txn
|
|
|
|
.reindex(&mut audit)
|
|
|
|
.and_then(|_| be_wr_txn.commit(&mut audit));
|
|
|
|
|
|
|
|
// Now that's done, setup a minimal qs and reindex from that.
|
|
|
|
if r.is_err() {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Failed to reindex database: {:?}", r);
|
2020-03-07 01:49:39 +01:00
|
|
|
std::process::exit(1);
|
|
|
|
}
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Index Phase 1 Success!");
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-18 02:30:42 +02:00
|
|
|
audit.write_log();
|
|
|
|
let mut audit = AuditScope::new("server_reindex", uuid::Uuid::new_v4(), config.log_level);
|
|
|
|
|
|
|
|
eprintln!("Attempting to init query server ...");
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2021-09-15 00:24:37 +02:00
|
|
|
let (qs, _idms, _idms_delayed) = match setup_qs_idms(&mut audit, be, schema, config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to setup query server or idm server -> {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Init Query Server Success!");
|
|
|
|
|
|
|
|
audit.write_log();
|
|
|
|
let mut audit = AuditScope::new("server_reindex", uuid::Uuid::new_v4(), config.log_level);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Start Index Phase 2 ...");
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let qs_write = task::block_on(qs.write_async(duration_from_epoch_now()));
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = qs_write
|
|
|
|
.reindex(&mut audit)
|
|
|
|
.and_then(|_| qs_write.commit(&mut audit));
|
|
|
|
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
match r {
|
2020-06-18 02:30:42 +02:00
|
|
|
Ok(_) => eprintln!("Index Phase 2 Success!"),
|
2020-03-07 01:49:39 +01:00
|
|
|
Err(e) => {
|
2020-06-18 02:30:42 +02:00
|
|
|
eprintln!("Reindex failed: {:?}", e);
|
2020-03-07 01:49:39 +01:00
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-02-21 06:04:58 +01:00
|
|
|
pub fn vacuum_server_core(config: &Configuration) {
|
|
|
|
let mut audit = AuditScope::new("server_vacuum", uuid::Uuid::new_v4(), config.log_level);
|
|
|
|
|
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// The schema doesn't matter here. Vacuum is run as part of db open to avoid
|
|
|
|
// locking.
|
2021-09-15 00:24:37 +02:00
|
|
|
let r = setup_backend_vacuum(config, &schema, true);
|
2021-02-21 06:04:58 +01:00
|
|
|
|
|
|
|
audit.write_log();
|
|
|
|
|
|
|
|
match r {
|
|
|
|
Ok(_) => eprintln!("Vacuum Success!"),
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Vacuum failed: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
pub fn domain_rename_core(config: &Configuration, new_domain_name: &str) {
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit = AuditScope::new("domain_rename", uuid::Uuid::new_v4(), config.log_level);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// Start the backend.
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// setup the qs - *with* init of the migrations and schema.
|
2021-09-15 00:24:37 +02:00
|
|
|
let (qs, _idms, _idms_delayed) = match setup_qs_idms(&mut audit, be, schema, config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to setup query server or idm server -> {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
let qs_write = task::block_on(qs.write_async(duration_from_epoch_now()));
|
2020-03-07 01:49:39 +01:00
|
|
|
let r = qs_write
|
2020-08-04 04:58:11 +02:00
|
|
|
.domain_rename(&mut audit, new_domain_name)
|
2020-03-07 01:49:39 +01:00
|
|
|
.and_then(|_| qs_write.commit(&mut audit));
|
|
|
|
|
|
|
|
match r {
|
|
|
|
Ok(_) => info!("Domain Rename Success!"),
|
|
|
|
Err(e) => {
|
|
|
|
error!("Domain Rename Failed - Rollback has occured: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-06-07 01:53:10 +02:00
|
|
|
/*
|
2020-03-07 01:49:39 +01:00
|
|
|
pub fn reset_sid_core(config: Configuration) {
|
2020-06-05 06:01:20 +02:00
|
|
|
let mut audit = AuditScope::new("reset_sid_core", uuid::Uuid::new_v4());
|
2020-03-07 01:49:39 +01:00
|
|
|
// Setup the be
|
|
|
|
let be = match setup_backend(&config) {
|
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2020-03-22 02:31:02 +01:00
|
|
|
let nsid = be.reset_db_s_uuid(&mut audit);
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
info!("New Server ID: {:?}", nsid);
|
|
|
|
}
|
2020-06-07 01:53:10 +02:00
|
|
|
*/
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-08-04 04:58:11 +02:00
|
|
|
pub fn verify_server_core(config: &Configuration) {
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit = AuditScope::new("server_verify", uuid::Uuid::new_v4(), config.log_level);
|
2020-03-07 01:49:39 +01:00
|
|
|
// setup the qs - without initialise!
|
|
|
|
let schema_mem = match Schema::new(&mut audit) {
|
|
|
|
Ok(sc) => sc,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2020-06-24 13:17:46 +02:00
|
|
|
// Setup the be
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema_mem) {
|
2020-06-24 13:17:46 +02:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
2021-06-29 06:23:39 +02:00
|
|
|
let server = QueryServer::new(&mut audit, be, schema_mem);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// Run verifications.
|
|
|
|
let r = server.verify(&mut audit);
|
|
|
|
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
if r.is_empty() {
|
2021-07-01 06:51:25 +02:00
|
|
|
eprintln!("Verification passed!");
|
2020-03-07 01:49:39 +01:00
|
|
|
std::process::exit(0);
|
|
|
|
} else {
|
|
|
|
for er in r {
|
|
|
|
error!("{:?}", er);
|
|
|
|
}
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now add IDM server verifications?
|
|
|
|
}
|
|
|
|
|
2021-06-02 01:30:37 +02:00
|
|
|
pub fn recover_account_core(config: &Configuration, name: &str) {
|
2020-06-18 02:30:42 +02:00
|
|
|
let mut audit = AuditScope::new("recover_account", uuid::Uuid::new_v4(), config.log_level);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// Start the backend.
|
2021-09-15 00:24:37 +02:00
|
|
|
let be = match setup_backend(config, &schema) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE: {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// setup the qs - *with* init of the migrations and schema.
|
2021-09-15 00:24:37 +02:00
|
|
|
let (_qs, idms, _idms_delayed) = match setup_qs_idms(&mut audit, be, schema, config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to setup query server or idm server -> {:?}", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Run the password change.
|
2020-09-06 00:44:35 +02:00
|
|
|
let mut idms_prox_write = task::block_on(idms.proxy_write_async(duration_from_epoch_now()));
|
2021-09-15 00:24:37 +02:00
|
|
|
match idms_prox_write.recover_account(&mut audit, name, None) {
|
2021-06-02 01:30:37 +02:00
|
|
|
Ok(new_pw) => match idms_prox_write.commit(&mut audit) {
|
2020-08-04 04:58:11 +02:00
|
|
|
Ok(()) => {
|
|
|
|
audit.write_log();
|
2021-06-17 05:53:23 +02:00
|
|
|
eprintln!("Password reset to -> {}", new_pw);
|
2020-08-04 04:58:11 +02:00
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
error!("A critical error during commit occured {:?}", e);
|
|
|
|
audit.write_log();
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
},
|
2020-03-07 01:49:39 +01:00
|
|
|
Err(e) => {
|
|
|
|
error!("Error during password reset -> {:?}", e);
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
// abort the txn
|
|
|
|
std::mem::drop(idms_prox_write);
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
pub async fn create_server_core(config: Configuration) -> Result<(), ()> {
|
2020-03-07 01:49:39 +01:00
|
|
|
// Until this point, we probably want to write to the log macro fns.
|
|
|
|
|
|
|
|
if config.integration_test_config.is_some() {
|
|
|
|
warn!("RUNNING IN INTEGRATION TEST MODE.");
|
|
|
|
warn!("IF YOU SEE THIS IN PRODUCTION YOU MUST CONTACT SUPPORT IMMEDIATELY.");
|
|
|
|
}
|
|
|
|
|
|
|
|
info!("Starting kanidm with configuration: {}", config);
|
2020-07-28 08:55:58 +02:00
|
|
|
// Setup umask, so that every we touch or create is secure.
|
|
|
|
let _ = unsafe { umask(0o0027) };
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
// The log task is spawned. It will only consume a single thread at a time.
|
2020-06-05 06:01:20 +02:00
|
|
|
let (log_tx, log_rx) = unbounded();
|
2020-09-06 00:44:35 +02:00
|
|
|
tokio::spawn(async_log::run(log_rx));
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
// Similar, create a stats task which aggregates statistics from the
|
2020-06-24 13:17:46 +02:00
|
|
|
// server as they come in.
|
2020-09-06 00:44:35 +02:00
|
|
|
let status_ref = StatusActor::start(log_tx.clone(), config.log_level);
|
2020-05-07 06:08:06 +02:00
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// Setup TLS (if any)
|
2020-09-06 00:44:35 +02:00
|
|
|
let _opt_tls_params = match setup_tls(&config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(opt_tls_params) => opt_tls_params,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to configure TLS parameters -> {:?}", e);
|
2020-06-05 06:01:20 +02:00
|
|
|
return Err(());
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-24 13:17:46 +02:00
|
|
|
let mut audit = AuditScope::new("setup_qs_idms", uuid::Uuid::new_v4(), config.log_level);
|
|
|
|
|
|
|
|
let schema = match Schema::new(&mut audit) {
|
|
|
|
Ok(s) => s,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup in memory schema: {:?}", e);
|
|
|
|
return Err(());
|
|
|
|
}
|
|
|
|
};
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// Setup the be for the qs.
|
2020-06-24 13:17:46 +02:00
|
|
|
let be = match setup_backend(&config, &schema) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(be) => be,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to setup BE -> {:?}", e);
|
2020-06-05 06:01:20 +02:00
|
|
|
return Err(());
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
// Start the IDM server.
|
2021-04-25 03:35:02 +02:00
|
|
|
let (_qs, idms, mut idms_delayed) = match setup_qs_idms(&mut audit, be, schema, &config) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to setup query server or idm server -> {:?}", e);
|
2020-06-05 06:01:20 +02:00
|
|
|
return Err(());
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
};
|
2020-06-10 04:07:43 +02:00
|
|
|
|
2021-05-26 08:11:00 +02:00
|
|
|
// Extract any configuration from the IDMS that we may need.
|
|
|
|
// For now we just do this per run, but we need to extract this from the db later.
|
|
|
|
let bundy_key = match bundy::hs512::HS512::generate_key() {
|
|
|
|
Ok(k) => k,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Unable to setup bundy -> {:?}", e);
|
|
|
|
return Err(());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// Any pre-start tasks here.
|
|
|
|
match &config.integration_test_config {
|
|
|
|
Some(itc) => {
|
2020-09-06 00:44:35 +02:00
|
|
|
let mut idms_prox_write =
|
|
|
|
task::block_on(idms.proxy_write_async(duration_from_epoch_now()));
|
2021-06-02 01:30:37 +02:00
|
|
|
match idms_prox_write.recover_account(&mut audit, "admin", Some(&itc.admin_password)) {
|
2020-03-07 01:49:39 +01:00
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!(
|
|
|
|
"Unable to configure INTERGATION TEST admin account -> {:?}",
|
|
|
|
e
|
|
|
|
);
|
2020-06-05 06:01:20 +02:00
|
|
|
return Err(());
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
match idms_prox_write.commit(&mut audit) {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
2020-06-05 06:01:20 +02:00
|
|
|
audit.write_log();
|
2020-03-07 01:49:39 +01:00
|
|
|
error!("Unable to commit INTERGATION TEST setup -> {:?}", e);
|
2020-06-05 06:01:20 +02:00
|
|
|
return Err(());
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
2020-06-10 04:07:43 +02:00
|
|
|
|
|
|
|
let ldap = match LdapServer::new(&mut audit, &idms) {
|
|
|
|
Ok(l) => l,
|
|
|
|
Err(e) => {
|
|
|
|
audit.write_log();
|
|
|
|
error!("Unable to start LdapServer -> {:?}", e);
|
|
|
|
return Err(());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
log_tx.send(audit).unwrap_or_else(|_| {
|
2020-06-05 06:01:20 +02:00
|
|
|
error!("CRITICAL: UNABLE TO COMMIT LOGS");
|
|
|
|
});
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-10 04:07:43 +02:00
|
|
|
// Arc the idms and ldap
|
2020-03-07 01:49:39 +01:00
|
|
|
let idms_arc = Arc::new(idms);
|
2020-06-10 04:07:43 +02:00
|
|
|
let ldap_arc = Arc::new(ldap);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
|
|
|
// Pass it to the actor for threading.
|
|
|
|
// Start the read query server with the given be path: future config
|
2020-09-06 00:44:35 +02:00
|
|
|
let server_read_ref = QueryServerReadV1::start_static(
|
2020-06-10 04:07:43 +02:00
|
|
|
log_tx.clone(),
|
2020-06-18 02:30:42 +02:00
|
|
|
config.log_level,
|
2020-06-10 04:07:43 +02:00
|
|
|
idms_arc.clone(),
|
|
|
|
ldap_arc.clone(),
|
|
|
|
);
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
// Create the server async write entry point.
|
2021-04-25 03:35:02 +02:00
|
|
|
let server_write_ref =
|
|
|
|
QueryServerWriteV1::start_static(log_tx.clone(), config.log_level, idms_arc.clone());
|
2020-09-06 00:44:35 +02:00
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
idms_delayed.process_all(server_write_ref).await;
|
|
|
|
});
|
2020-08-24 04:15:21 +02:00
|
|
|
|
2020-03-07 01:49:39 +01:00
|
|
|
// Setup timed events associated to the write thread
|
2020-09-06 00:44:35 +02:00
|
|
|
IntervalActor::start(server_write_ref);
|
2021-07-31 09:13:46 +02:00
|
|
|
// Setup timed events associated to the read thread
|
|
|
|
match &config.online_backup {
|
|
|
|
Some(cfg) => {
|
2021-09-15 00:24:37 +02:00
|
|
|
IntervalActor::start_online_backup(server_read_ref, cfg)?;
|
2021-07-31 09:13:46 +02:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
debug!("Online backup not requested, skipping");
|
|
|
|
}
|
|
|
|
};
|
2020-03-07 01:49:39 +01:00
|
|
|
|
2020-06-10 04:07:43 +02:00
|
|
|
// If we have been requested to init LDAP, configure it now.
|
|
|
|
match &config.ldapaddress {
|
|
|
|
Some(la) => {
|
|
|
|
let opt_ldap_tls_params = match setup_tls(&config) {
|
|
|
|
Ok(t) => t,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed to configure LDAP TLS parameters -> {:?}", e);
|
|
|
|
return Err(());
|
|
|
|
}
|
|
|
|
};
|
2020-09-06 00:44:35 +02:00
|
|
|
ldaps::create_ldap_server(la.as_str(), opt_ldap_tls_params, server_read_ref).await?;
|
2020-06-10 04:07:43 +02:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
debug!("LDAP not requested, skipping");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
// TODO: Remove these when we go to auth bearer!
|
2020-03-07 01:49:39 +01:00
|
|
|
// Copy the max size
|
2020-09-06 00:44:35 +02:00
|
|
|
let _secure_cookies = config.secure_cookies;
|
2020-03-07 01:49:39 +01:00
|
|
|
// domain will come from the qs now!
|
|
|
|
let cookie_key: [u8; 32] = config.cookie_key;
|
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
self::https::create_https_server(
|
|
|
|
config.address,
|
|
|
|
// opt_tls_params,
|
|
|
|
config.tls_config.as_ref(),
|
2021-05-06 12:58:22 +02:00
|
|
|
config.role,
|
2020-09-06 00:44:35 +02:00
|
|
|
&cookie_key,
|
2021-05-26 08:11:00 +02:00
|
|
|
&bundy_key,
|
2020-09-06 00:44:35 +02:00
|
|
|
status_ref,
|
|
|
|
server_write_ref,
|
|
|
|
server_read_ref,
|
2020-09-08 04:46:10 +02:00
|
|
|
)?;
|
2020-08-04 04:58:11 +02:00
|
|
|
|
|
|
|
info!("ready to rock! 🧱");
|
2020-06-05 06:01:20 +02:00
|
|
|
|
2020-09-06 00:44:35 +02:00
|
|
|
Ok(())
|
2020-03-07 01:49:39 +01:00
|
|
|
}
|