summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..b88da88
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,90 @@
+use clap::Parser;
+use kanidm_client::{ClientError, KanidmClient, KanidmClientBuilder};
+use std::{path::PathBuf, process::ExitCode, sync::OnceLock};
+
+#[derive(Parser, Debug)]
+#[command(version, about)]
+struct Args {
+ #[arg(short, long)]
+ config: Option<PathBuf>,
+
+ #[arg(name = "USERNAME", required = true)]
+ username: String,
+
+ #[arg(name = "PASSWORD")]
+ password: Option<String>,
+}
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> ExitCode {
+ let args = Args::parse();
+ let client = match get_client(&args) {
+ Ok(c) => c,
+ Err(e) => {
+ eprintln!("Failed to create client: {e:?}");
+ return ExitCode::FAILURE;
+ }
+ };
+
+ let password = args.password.unwrap_or_else(get_password);
+
+ if let Err(e) = client.auth_anonymous().await {
+ eprintln!("Failed to authenticate: {e:?}");
+ return ExitCode::FAILURE;
+ }
+
+ let token = match client
+ .idm_account_unix_cred_verify(&args.username, &password)
+ .await
+ {
+ Ok(t) => t,
+ Err(e) => {
+ eprintln!("Failed to get token: {e:?}");
+ return ExitCode::FAILURE;
+ }
+ };
+
+ if token.is_some() {
+ ExitCode::SUCCESS
+ } else {
+ ExitCode::FAILURE
+ }
+}
+
+fn config_paths() -> &'static [&'static str] {
+ const DEFAULT_CONFIG_PATHS: &[&str] = &["/etc/kanidm/config"];
+
+ static CONFIG_PATHS: OnceLock<&[&str]> = OnceLock::new();
+
+ CONFIG_PATHS.get_or_init(|| {
+ let mut paths = DEFAULT_CONFIG_PATHS.to_vec();
+ if let Ok(mut home) = std::env::var("HOME") {
+ home.push_str("/.config/kanidm");
+ paths.push(String::leak(home))
+ }
+ Vec::leak(paths)
+ })
+}
+
+fn get_client(args: &Args) -> Result<KanidmClient, ClientError> {
+ let mut builder = KanidmClientBuilder::new();
+
+ if let Some(cfg_path) = &args.config {
+ builder = builder.read_options_from_optional_config(cfg_path)?;
+ } else {
+ for path in config_paths() {
+ builder = builder.read_options_from_optional_config(path)?;
+ }
+ }
+
+ builder.build()
+}
+
+fn get_password() -> String {
+ // Check KANIDM_PASSWORD first
+ if let Ok(password) = std::env::var("KANIDM_PASSWORD") {
+ return password;
+ };
+
+ rpassword::read_password().unwrap()
+}