From 66954213db0484eb6e73ff36fe6f70c17c6e6ab2 Mon Sep 17 00:00:00 2001 From: James Hodgkinson Date: Thu, 8 Sep 2022 13:37:03 +1000 Subject: [PATCH] #896 kanidm_unixd UX updoots (#1024) --- examples/config_localhost | 5 + examples/unixd.macos | 12 ++ kanidm_client/src/lib.rs | 21 +++ kanidm_proto/src/constants.rs | 6 + kanidm_proto/src/lib.rs | 1 + kanidm_tools/src/cli/common.rs | 9 +- kanidm_tools/src/ssh_authorizedkeys.rs | 7 +- kanidm_unix_int/Cargo.toml | 2 +- kanidm_unix_int/src/cache_clear.rs | 2 +- kanidm_unix_int/src/cache_invalidate.rs | 2 +- kanidm_unix_int/src/daemon.rs | 200 ++++++++++++++-------- kanidm_unix_int/src/daemon_status.rs | 2 +- kanidm_unix_int/src/ssh_authorizedkeys.rs | 2 +- kanidm_unix_int/src/test_auth.rs | 6 +- kanidm_unix_int/src/unix_config.rs | 60 ++++++- kanidmd/idm/benches/scaling_10k.rs | 3 +- kanidmd/idm/src/be/mod.rs | 1 - kanidmd/idm/src/idm/server.rs | 6 +- kanidmd/idm/src/macros.rs | 3 - kanidmd/idm/src/repl/entry.rs | 2 +- kanidmd/idm/src/schema.rs | 1 - 21 files changed, 255 insertions(+), 98 deletions(-) create mode 100644 examples/config_localhost create mode 100644 examples/unixd.macos create mode 100644 kanidm_proto/src/constants.rs diff --git a/examples/config_localhost b/examples/config_localhost new file mode 100644 index 000000000..59b9aa2cb --- /dev/null +++ b/examples/config_localhost @@ -0,0 +1,5 @@ +# This should be at /etc/kanidm/config or ~/.config/kanidm, and configures the kanidm command line tool +# to point at the local dev server and ignore TLS security. +uri = "https://localhost:8443" +verify_ca = false +verify_hostnames = false diff --git a/examples/unixd.macos b/examples/unixd.macos new file mode 100644 index 000000000..021edc7ce --- /dev/null +++ b/examples/unixd.macos @@ -0,0 +1,12 @@ +# this example configures kanidm-unixd for testing on macos +db_path = "/tmp/kanidm-unixd" +sock_path = "/tmp/kanimd_unixd.sock" +task_sock_path = "/tmp/kanimd_unidx_task.sock" +# some documentation is here: https://github.com/kanidm/kanidm/blob/master/kanidm_book/src/pam_and_nsswitch.md +pam_allowed_login_groups = ["posix_group"] +# default_shell = "/bin/sh" +# home_prefix = "/home/" +# home_attr = "uuid" +# home_alias = "spn" +# uid_attr_map = "spn" +# gid_attr_map = "spn" \ No newline at end of file diff --git a/kanidm_client/src/lib.rs b/kanidm_client/src/lib.rs index 038c93d79..7700fa353 100644 --- a/kanidm_client/src/lib.rs +++ b/kanidm_client/src/lib.rs @@ -18,6 +18,7 @@ use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Serialize; use serde_json::error::Error as SerdeJsonError; +use std::fmt::{Display, Formatter}; use std::fs::File; #[cfg(target_family = "unix")] // not needed for windows builds use std::fs::{metadata, Metadata}; @@ -81,6 +82,26 @@ pub struct KanidmClientBuilder { use_system_proxies: bool, } +impl Display for KanidmClientBuilder { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self.address { + Some(value) => writeln!(f, "address: {}", value)?, + None => writeln!(f, "address: unset")?, + } + writeln!(f, "verify_ca: {}", self.verify_ca)?; + writeln!(f, "verify_hostnames: {}", self.verify_hostnames)?; + match &self.ca { + Some(value) => writeln!(f, "ca: {:#?}", value)?, + None => writeln!(f, "ca: unset")?, + } + match self.connect_timeout { + Some(value) => writeln!(f, "connect_timeout: {}", value)?, + None => writeln!(f, "connect_timeout: unset")?, + } + writeln!(f, "use_system_proxies: {}", self.use_system_proxies) + } +} + #[derive(Debug)] pub struct KanidmClient { pub(crate) client: reqwest::Client, diff --git a/kanidm_proto/src/constants.rs b/kanidm_proto/src/constants.rs new file mode 100644 index 000000000..2a24239a5 --- /dev/null +++ b/kanidm_proto/src/constants.rs @@ -0,0 +1,6 @@ +/// Because consistency is great! + +/// The "system" path for Kanidm client config +pub const DEFAULT_CLIENT_CONFIG_PATH: &str = "/etc/kanidm/config"; +/// The user-owned path for Kanidm client config +pub const DEFAULT_CLIENT_CONFIG_PATH_HOME: &str = "~/.config/kanidm"; diff --git a/kanidm_proto/src/lib.rs b/kanidm_proto/src/lib.rs index 86cad766f..936a166c0 100644 --- a/kanidm_proto/src/lib.rs +++ b/kanidm_proto/src/lib.rs @@ -8,6 +8,7 @@ #![deny(clippy::needless_pass_by_value)] #![deny(clippy::trivially_copy_pass_by_ref)] +pub mod constants; pub mod messages; pub mod oauth2; pub mod utils; diff --git a/kanidm_tools/src/cli/common.rs b/kanidm_tools/src/cli/common.rs index 68a4fab3e..9c81d9357 100644 --- a/kanidm_tools/src/cli/common.rs +++ b/kanidm_tools/src/cli/common.rs @@ -3,23 +3,24 @@ use crate::CommonOpt; use compact_jwt::{Jws, JwsUnverified}; use dialoguer::{theme::ColorfulTheme, Select}; use kanidm_client::{KanidmClient, KanidmClientBuilder}; +use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use kanidm_proto::v1::UserAuthToken; use std::str::FromStr; impl CommonOpt { pub fn to_unauth_client(&self) -> KanidmClient { - let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned(); + let config_path: String = shellexpand::tilde(DEFAULT_CLIENT_CONFIG_PATH_HOME).into_owned(); let client_builder = KanidmClientBuilder::new() - .read_options_from_optional_config("/etc/kanidm/config") + .read_options_from_optional_config(DEFAULT_CLIENT_CONFIG_PATH) .and_then(|cb| cb.read_options_from_optional_config(&config_path)) .unwrap_or_else(|e| { error!("Failed to parse config (if present) -- {:?}", e); std::process::exit(1); }); debug!( - "Successfully loaded configuration, looked in /etc/kanidm/config and {} - client builder state: {:?}", - &config_path, &client_builder + "Successfully loaded configuration, looked in {} and {} - client builder state: {:?}", + DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME, &client_builder ); let client_builder = match &self.addr { diff --git a/kanidm_tools/src/ssh_authorizedkeys.rs b/kanidm_tools/src/ssh_authorizedkeys.rs index 48e260507..3de10f740 100644 --- a/kanidm_tools/src/ssh_authorizedkeys.rs +++ b/kanidm_tools/src/ssh_authorizedkeys.rs @@ -13,6 +13,7 @@ use std::path::PathBuf; use clap::Parser; use kanidm_client::{ClientError, KanidmClientBuilder}; +use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use tracing::{debug, error}; include!("opt/ssh_authorizedkeys.rs"); @@ -29,10 +30,10 @@ async fn main() { } tracing_subscriber::fmt::init(); - let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned(); - debug!("Attempting to use config {}", "/etc/kanidm/config"); + let config_path: String = shellexpand::tilde(DEFAULT_CLIENT_CONFIG_PATH_HOME).into_owned(); + debug!("Attempting to use config {}", DEFAULT_CLIENT_CONFIG_PATH); let client_builder = KanidmClientBuilder::new() - .read_options_from_optional_config("/etc/kanidm/config") + .read_options_from_optional_config(DEFAULT_CLIENT_CONFIG_PATH) .and_then(|cb| { debug!("Attempting to use config {}", config_path); cb.read_options_from_optional_config(config_path) diff --git a/kanidm_unix_int/Cargo.toml b/kanidm_unix_int/Cargo.toml index 630848e7b..36144560f 100644 --- a/kanidm_unix_int/Cargo.toml +++ b/kanidm_unix_int/Cargo.toml @@ -61,7 +61,7 @@ bytes = "^1.1.0" libc = "^0.2.127" serde = { version = "^1.0.142", features = ["derive"] } serde_json = "^1.0.83" -clap = { version = "^3.2", features = ["derive"] } +clap = { version = "^3.2", features = ["derive", "env"] } libsqlite3-sys = "0.25.0" rusqlite = "^0.28.0" diff --git a/kanidm_unix_int/src/cache_clear.rs b/kanidm_unix_int/src/cache_clear.rs index fcf9bf248..3101a7ea0 100644 --- a/kanidm_unix_int/src/cache_clear.rs +++ b/kanidm_unix_int/src/cache_clear.rs @@ -38,7 +38,7 @@ async fn main() { { Ok(c) => c, Err(_e) => { - error!("Failed to parse /etc/kanidm/unixd"); + error!("Failed to parse {}", DEFAULT_CONFIG_PATH); std::process::exit(1); } }; diff --git a/kanidm_unix_int/src/cache_invalidate.rs b/kanidm_unix_int/src/cache_invalidate.rs index cd950d2b3..c6edf0200 100644 --- a/kanidm_unix_int/src/cache_invalidate.rs +++ b/kanidm_unix_int/src/cache_invalidate.rs @@ -38,7 +38,7 @@ async fn main() { { Ok(c) => c, Err(_e) => { - error!("Failed to parse /etc/kanidm/unixd"); + error!("Failed to parse {}", DEFAULT_CONFIG_PATH); std::process::exit(1); } }; diff --git a/kanidm_unix_int/src/daemon.rs b/kanidm_unix_int/src/daemon.rs index 6a9bc05e3..7701b882e 100644 --- a/kanidm_unix_int/src/daemon.rs +++ b/kanidm_unix_int/src/daemon.rs @@ -10,39 +10,35 @@ #![deny(clippy::needless_pass_by_value)] #![deny(clippy::trivially_copy_pass_by_ref)] -use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; - +use bytes::{BufMut, BytesMut}; +use clap::{Arg, ArgAction, Command}; +use futures::SinkExt; +use futures::StreamExt; +use kanidm::utils::file_permissions_readonly; +use kanidm_client::KanidmClientBuilder; +use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH; +use kanidm_unix_common::cache::CacheLayer; +use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; +use kanidm_unix_common::unix_config::KanidmUnixdConfig; +use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse}; +use libc::umask; +use sketching::tracing_forest::{self, traits::*, util::*}; +use std::error::Error; use std::fs::metadata; +use std::io; use std::io::Error as IoError; use std::io::ErrorKind; use std::os::unix::fs::MetadataExt; use std::path::{Path, PathBuf}; - -use bytes::{BufMut, BytesMut}; -use futures::SinkExt; -use futures::StreamExt; -use libc::umask; -use sketching::tracing_forest::{self, traits::*, util::*}; -use std::error::Error; -use std::io; use std::sync::Arc; use std::time::Duration; - use tokio::net::{UnixListener, UnixStream}; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::oneshot; use tokio::time; use tokio_util::codec::Framed; use tokio_util::codec::{Decoder, Encoder}; - -use kanidm_client::KanidmClientBuilder; - -use kanidm_unix_common::cache::CacheLayer; -use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; -use kanidm_unix_common::unix_config::KanidmUnixdConfig; -use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse}; - -use kanidm::utils::file_permissions_readonly; +use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; //=== the codec @@ -124,6 +120,7 @@ impl TaskCodec { } } +/// Pass this a file path and it'll look for the file and remove it if it's there. fn rm_if_exist(p: &str) { if Path::new(p).exists() { debug!("Removing requested file {:?}", p); @@ -305,8 +302,7 @@ async fn handle_client( .await { Ok(()) => { - // Now wait for the other end OR - // timeout. + // Now wait for the other end OR timeout. match time::timeout_at( time::Instant::now() + Duration::from_millis(1000), rx, @@ -374,9 +370,63 @@ async fn main() { let cgid = get_current_gid(); let cegid = get_effective_gid(); - if cuid == 0 || ceuid == 0 || cgid == 0 || cegid == 0 { - eprintln!("Refusing to run - this process must not operate as root."); - std::process::exit(1); + let clap_args = Command::new("kanidm_unixd") + .version(env!("CARGO_PKG_VERSION")) + .about("Kanidm Unix daemon") + .arg( + Arg::new("skip-root-check") + .help("Allow running as root. Don't use this in production as it is risky!") + .short('r') + .long("skip-root-check") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("debug") + .help("Show extra debug information") + .short('d') + .long("debug") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("configtest") + .help("Display the configuration and exit") + .short('t') + .long("configtest") + .action(ArgAction::SetTrue), + ) + .arg( + Arg::new("unixd-config") + .takes_value(true) + .help("Set the unixd config file path") + .short('u') + .long("unixd-config") + .default_value(DEFAULT_CONFIG_PATH) + .env("KANIDM_UNIX_CONFIG") + .action(ArgAction::StoreValue), + ) + .arg( + Arg::new("client-config") + .takes_value(true) + .help("Set the client config file path") + .short('c') + .long("client-config") + .default_value(DEFAULT_CLIENT_CONFIG_PATH) + .env("KANIDM_CLIENT_CONFIG") + .action(ArgAction::StoreValue), + ) + .get_matches(); + + if clap_args.get_flag("skip-root-check") { + warn!("Skipping root user check, if you're running this for testing, ensure you clean up temporary files.") + // TODO: this wording is not great m'kay. + } else { + if cuid == 0 || ceuid == 0 || cgid == 0 || cegid == 0 { + error!("Refusing to run - this process must not operate as root."); + return; + } + }; + if clap_args.get_flag("debug") { + std::env::set_var("RUST_LOG", "debug"); } tracing_forest::worker_task() @@ -393,29 +443,24 @@ async fn main() { debug!("Profile -> {}", env!("KANIDM_PROFILE_NAME")); debug!("CPU Flags -> {}", env!("KANIDM_CPU_FLAGS")); - let cfg_path = Path::new("/etc/kanidm/config"); - let cfg_path_str = match cfg_path.to_str() { - Some(cps) => cps, - None => { - error!("Unable to turn cfg_path to str"); - std::process::exit(1); - } - }; + + #[allow(clippy::expect_used)] + let cfg_path_str = clap_args.get_one::("client-config").expect("Failed to pull the client config path"); + let cfg_path: PathBuf = PathBuf::from(cfg_path_str); + if !cfg_path.exists() { // there's no point trying to start up if we can't read a usable config! error!( "Client config missing from {} - cannot start up. Quitting.", cfg_path_str ); - std::process::exit(1); - } - - if cfg_path.exists() { + return + } else { let cfg_meta = match metadata(&cfg_path) { Ok(v) => v, Err(e) => { error!("Unable to read metadata for {} - {:?}", cfg_path_str, e); - std::process::exit(1); + return } }; if !file_permissions_readonly(&cfg_meta) { @@ -431,27 +476,23 @@ async fn main() { } } - let unixd_path = Path::new(DEFAULT_CONFIG_PATH); - let unixd_path_str = match unixd_path.to_str() { - Some(cps) => cps, - None => { - error!("Unable to turn unixd_path to str"); - std::process::exit(1); - } - }; + #[allow(clippy::expect_used)] + let unixd_path_str = clap_args.get_one::("unixd-config").expect("Failed to pull the unixd config path"); + let unixd_path = PathBuf::from(unixd_path_str); + if !unixd_path.exists() { // there's no point trying to start up if we can't read a usable config! error!( "unixd config missing from {} - cannot start up. Quitting.", unixd_path_str ); - std::process::exit(1); + return } else { let unixd_meta = match metadata(&unixd_path) { Ok(v) => v, Err(e) => { error!("Unable to read metadata for {} - {:?}", unixd_path_str, e); - std::process::exit(1); + return } }; if !file_permissions_readonly(&unixd_meta) { @@ -467,37 +508,40 @@ async fn main() { } // setup - let cb = match KanidmClientBuilder::new().read_options_from_optional_config(cfg_path) { + let cb = match KanidmClientBuilder::new().read_options_from_optional_config(&cfg_path) { Ok(v) => v, Err(_) => { error!("Failed to parse {}", cfg_path_str); - std::process::exit(1); + return } }; - let cfg = match KanidmUnixdConfig::new().read_options_from_optional_config(unixd_path) { + let cfg = match KanidmUnixdConfig::new().read_options_from_optional_config(&unixd_path) { Ok(v) => v, Err(_) => { error!("Failed to parse {}", unixd_path_str); - std::process::exit(1); + return } }; + if clap_args.get_flag("configtest") { + eprintln!("###################################"); + eprintln!("Dumping configs:\n###################################"); + eprintln!("kanidm_unixd config (from {:#?})", &unixd_path); + eprintln!("{}", cfg); + eprintln!("###################################"); + eprintln!("Client config (from {:#?})", &cfg_path); + eprintln!("{}", cb); + return; + } + debug!("🧹 Cleaning up sockets from previous invocations"); rm_if_exist(cfg.sock_path.as_str()); rm_if_exist(cfg.task_sock_path.as_str()); - let cb = cb.connect_timeout(cfg.conn_timeout); - let rsclient = match cb.build() { - Ok(rsc) => rsc, - Err(_e) => { - error!("Failed to build async client"); - std::process::exit(1); - } - }; - // Check the pb path will be okay. + // Check the db path will be okay. if cfg.db_path != "" { let db_path = PathBuf::from(cfg.db_path.as_str()); // We only need to check the parent folder path permissions as the db itself may not exist yet. @@ -509,7 +553,7 @@ async fn main() { .to_str() .unwrap_or_else(|| "") ); - std::process::exit(1); + return } let db_par_path_buf = db_parent_path.to_path_buf(); @@ -524,7 +568,7 @@ async fn main() { .unwrap_or_else(|| ""), e ); - std::process::exit(1); + return } }; @@ -535,7 +579,7 @@ async fn main() { .to_str() .unwrap_or_else(|| "") ); - std::process::exit(1); + return } if !file_permissions_readonly(&i_meta) { warn!("WARNING: DB folder permissions on {} indicate it may not be RW. This could cause the server start up to fail!", db_par_path_buf.to_str() @@ -557,7 +601,7 @@ async fn main() { "Refusing to run - DB path {} already exists and is not a file.", db_path.to_str().unwrap_or_else(|| "") ); - std::process::exit(1); + return }; match metadata(&db_path) { @@ -568,13 +612,24 @@ async fn main() { db_path.to_str().unwrap_or_else(|| ""), e ); - std::process::exit(1); + return } }; // TODO: permissions dance to enumerate the user's ability to write to the file? ref #456 - r2d2 will happily keep trying to do things without bailing. }; } + let cb = cb.connect_timeout(cfg.conn_timeout); + + let rsclient = match cb.build() { + Ok(rsc) => rsc, + Err(_e) => { + error!("Failed to build async client"); + return + } + }; + + let cl_inner = match CacheLayer::new( cfg.db_path.as_str(), // The sqlite db path cfg.cache_timeout, @@ -592,7 +647,7 @@ async fn main() { Ok(c) => c, Err(_e) => { error!("Failed to build cache layer."); - std::process::exit(1); + return } }; @@ -603,8 +658,8 @@ async fn main() { let listener = match UnixListener::bind(cfg.sock_path.as_str()) { Ok(l) => l, Err(_e) => { - error!("Failed to bind unix socket."); - std::process::exit(1); + error!("Failed to bind UNIX socket at {}", cfg.sock_path.as_str()); + return } }; // Setup the root-only socket. Take away all others. @@ -612,8 +667,8 @@ async fn main() { let task_listener = match UnixListener::bind(cfg.task_sock_path.as_str()) { Ok(l) => l, Err(_e) => { - error!("Failed to bind unix socket."); - std::process::exit(1); + error!("Failed to bind UNIX socket {}", cfg.sock_path.as_str()); + return } }; @@ -677,7 +732,7 @@ async fn main() { }); } Err(err) => { - error!("Accept error -> {:?}", err); + error!("Error while handling connection -> {:?}", err); } } } @@ -688,4 +743,5 @@ async fn main() { server.await; }) .await; + // TODO: can we catch signals to clean up sockets etc, especially handy when running as root } diff --git a/kanidm_unix_int/src/daemon_status.rs b/kanidm_unix_int/src/daemon_status.rs index a7a69b48a..afc9cf4bc 100644 --- a/kanidm_unix_int/src/daemon_status.rs +++ b/kanidm_unix_int/src/daemon_status.rs @@ -39,7 +39,7 @@ fn main() { { Ok(c) => c, Err(_e) => { - error!("Failed to parse /etc/kanidm/unixd"); + error!("Failed to parse {}", DEFAULT_CONFIG_PATH); std::process::exit(1); } }; diff --git a/kanidm_unix_int/src/ssh_authorizedkeys.rs b/kanidm_unix_int/src/ssh_authorizedkeys.rs index 2e9aba2dd..7aca8d673 100644 --- a/kanidm_unix_int/src/ssh_authorizedkeys.rs +++ b/kanidm_unix_int/src/ssh_authorizedkeys.rs @@ -39,7 +39,7 @@ async fn main() { { Ok(c) => c, Err(e) => { - error!("Failed to parse /etc/kanidm/unixd: {:?}", e); + error!("Failed to parse {}: {:?}", DEFAULT_CONFIG_PATH, e); std::process::exit(1); } }; diff --git a/kanidm_unix_int/src/test_auth.rs b/kanidm_unix_int/src/test_auth.rs index adb84a75f..1cb3fa5d3 100644 --- a/kanidm_unix_int/src/test_auth.rs +++ b/kanidm_unix_int/src/test_auth.rs @@ -27,13 +27,13 @@ async fn main() { } sketching::tracing_subscriber::fmt::init(); - debug!("Starting pam auth tester tool ..."); + debug!("Starting PAM auth tester tool ..."); let cfg = KanidmUnixdConfig::new() .read_options_from_optional_config(DEFAULT_CONFIG_PATH) - .expect("Failed to parse /etc/kanidm/unixd"); + .expect(&format!("Failed to parse {}", DEFAULT_CONFIG_PATH)); - let password = rpassword::prompt_password("Enter unix password: ").unwrap(); + let password = rpassword::prompt_password("Enter Unix password: ").unwrap(); let req = ClientRequest::PamAuthenticate(opt.account_id.clone(), password); let sereq = ClientRequest::PamAccountAllowed(opt.account_id); diff --git a/kanidm_unix_int/src/unix_config.rs b/kanidm_unix_int/src/unix_config.rs index 497f07b5e..d7c9d0df6 100644 --- a/kanidm_unix_int/src/unix_config.rs +++ b/kanidm_unix_int/src/unix_config.rs @@ -4,6 +4,8 @@ use crate::constants::{ DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP, }; use serde::Deserialize; +use std::env; +use std::fmt::{Display, Formatter}; use std::fs::File; use std::io::{ErrorKind, Read}; use std::path::Path; @@ -31,12 +33,39 @@ pub enum HomeAttr { Name, } +impl Display for HomeAttr { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + HomeAttr::Uuid => "UUID", + HomeAttr::Spn => "SPN", + HomeAttr::Name => "Name", + } + ) + } +} + #[derive(Debug, Copy, Clone)] pub enum UidAttr { Name, Spn, } +impl Display for UidAttr { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + UidAttr::Name => "Name", + UidAttr::Spn => "SPN", + } + ) + } +} + #[derive(Debug)] pub struct KanidmUnixdConfig { pub db_path: String, @@ -59,10 +88,39 @@ impl Default for KanidmUnixdConfig { } } +impl Display for KanidmUnixdConfig { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "db_path: {}", &self.db_path)?; + writeln!(f, "sock_path: {}", self.sock_path)?; + writeln!(f, "task_sock_path: {}", self.task_sock_path)?; + writeln!(f, "conn_timeout: {}", self.conn_timeout)?; + writeln!(f, "cache_timeout: {}", self.cache_timeout)?; + writeln!( + f, + "pam_allowed_login_groups: {:#?}", + self.pam_allowed_login_groups + )?; + writeln!(f, "default_shell: {}", self.default_shell)?; + writeln!(f, "home_prefix: {}", self.home_prefix)?; + writeln!(f, "home_attr: {}", self.home_attr)?; + match self.home_alias { + Some(val) => writeln!(f, "home_alias: {}", val)?, + None => writeln!(f, "home_alias: unset")?, + } + + writeln!(f, "uid_attr_map: {}", self.uid_attr_map)?; + writeln!(f, "gid_attr_map: {}", self.gid_attr_map) + } +} + impl KanidmUnixdConfig { pub fn new() -> Self { + let db_path = match env::var("KANIDM_DB_PATH") { + Ok(val) => val, + Err(_) => DEFAULT_DB_PATH.into(), + }; KanidmUnixdConfig { - db_path: DEFAULT_DB_PATH.to_string(), + db_path, sock_path: DEFAULT_SOCK_PATH.to_string(), task_sock_path: DEFAULT_TASK_SOCK_PATH.to_string(), conn_timeout: DEFAULT_CONN_TIMEOUT, diff --git a/kanidmd/idm/benches/scaling_10k.rs b/kanidmd/idm/benches/scaling_10k.rs index 1d201262e..f0aa25e3c 100644 --- a/kanidmd/idm/benches/scaling_10k.rs +++ b/kanidmd/idm/benches/scaling_10k.rs @@ -6,6 +6,7 @@ use kanidm; use kanidm::entry::{Entry, EntryInit, EntryNew}; use kanidm::entry_init; use kanidm::idm::server::{IdmServer, IdmServerDelayed}; +use kanidm::macros::run_idm_test_no_logging; use kanidm::server::QueryServer; use kanidm::utils::duration_from_epoch_now; use kanidm::value::Value; @@ -28,7 +29,7 @@ pub fn scaling_user_create_single(c: &mut Criterion) { println!("iters, size -> {:?}, {:?}", iters, size); for _i in 0..iters { - kanidm::macros::run_idm_test_no_logging( + run_idm_test_no_logging( |_qs: &QueryServer, idms: &IdmServer, _idms_delayed: &IdmServerDelayed| { let ct = duration_from_epoch_now(); diff --git a/kanidmd/idm/src/be/mod.rs b/kanidmd/idm/src/be/mod.rs index 16920d63e..680e0d544 100644 --- a/kanidmd/idm/src/be/mod.rs +++ b/kanidmd/idm/src/be/mod.rs @@ -98,7 +98,6 @@ impl BackendConfig { } } - #[cfg(test)] pub(crate) fn new_test() -> Self { BackendConfig { pool_size: 1, diff --git a/kanidmd/idm/src/idm/server.rs b/kanidmd/idm/src/idm/server.rs index 133c44846..e6cdfbe9e 100644 --- a/kanidmd/idm/src/idm/server.rs +++ b/kanidmd/idm/src/idm/server.rs @@ -47,9 +47,9 @@ use tokio::sync::Semaphore; use async_std::task; -#[cfg(test)] +// #[cfg(any(test,bench))] use core::task::{Context, Poll}; -#[cfg(test)] +// #[cfg(any(test,bench))] use futures::task as futures_task; use concread::{ @@ -362,7 +362,7 @@ impl IdmServer { } impl IdmServerDelayed { - #[cfg(test)] + // #[cfg(any(test,bench))] pub(crate) fn check_is_empty_or_panic(&mut self) { let waker = futures_task::noop_waker(); let mut cx = Context::from_waker(&waker); diff --git a/kanidmd/idm/src/macros.rs b/kanidmd/idm/src/macros.rs index b2da58793..88d16bccf 100644 --- a/kanidmd/idm/src/macros.rs +++ b/kanidmd/idm/src/macros.rs @@ -1,4 +1,3 @@ -#[cfg(test)] macro_rules! setup_test { () => {{ let _ = sketching::test_init(); @@ -126,7 +125,6 @@ macro_rules! entry_str_to_account { }}; } -#[cfg(test)] macro_rules! run_idm_test_inner { ($test_fn:expr) => {{ #[allow(unused_imports)] @@ -168,7 +166,6 @@ macro_rules! run_idm_test { }}; } -#[cfg(test)] pub fn run_idm_test_no_logging(mut test_fn: F) where F: FnMut( diff --git a/kanidmd/idm/src/repl/entry.rs b/kanidmd/idm/src/repl/entry.rs index 655a908a7..e2dc5e057 100644 --- a/kanidmd/idm/src/repl/entry.rs +++ b/kanidmd/idm/src/repl/entry.rs @@ -205,8 +205,8 @@ impl EntryChangelog { EntryChangelog { anchors, changes } } + // TODO: work out if the below comment about uncommenting is still valid // Uncomment this once we have a real on-disk storage of the changelog - // #[cfg(test)] pub fn new_without_schema(cid: Cid, attrs: Eattrs) -> Self { // I think we need to reduce the attrs based on what is / is not replicated.? diff --git a/kanidmd/idm/src/schema.rs b/kanidmd/idm/src/schema.rs index b51703bf4..350a6170e 100644 --- a/kanidmd/idm/src/schema.rs +++ b/kanidmd/idm/src/schema.rs @@ -1590,7 +1590,6 @@ impl Schema { } } - #[cfg(test)] pub(crate) fn write_blocking(&self) -> SchemaWriteTransaction<'_> { self.write() }