Consolidate unix tools (#1566)

This commit is contained in:
Firstyear 2023-04-24 19:47:52 +10:00 committed by GitHub
parent 9286d3780a
commit ade1591554
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 281 additions and 383 deletions

View file

@ -92,19 +92,19 @@ when first created. Defaults to false.
You can then check the communication status of the daemon: You can then check the communication status of the daemon:
```bash ```bash
kanidm_unixd_status kanidm-unix status
``` ```
If the daemon is working, you should see: If the daemon is working, you should see:
``` ```
[2020-02-14T05:58:37Z INFO kanidm_unixd_status] working! working!
``` ```
If it is not working, you will see an error message: If it is not working, you will see an error message:
``` ```
[2020-02-14T05:58:10Z ERROR kanidm_unixd_status] Error -> [2020-02-14T05:58:10Z ERROR kanidm-unix] Error ->
Os { code: 111, kind: ConnectionRefused, message: "Connection refused" } Os { code: 111, kind: ConnectionRefused, message: "Connection refused" }
``` ```
@ -473,13 +473,13 @@ cache_timeout = 60
You can invalidate the kanidm_unixd cache with: You can invalidate the kanidm_unixd cache with:
```bash ```bash
kanidm_cache_invalidate kanidm-unix cache-invalidate
``` ```
You can clear (wipe) the cache with: You can clear (wipe) the cache with:
```bash ```bash
kanidm_cache_clear kanidm-unix cache-clear
``` ```
There is an important distinction between these two - invalidated cache items may still be yielded There is an important distinction between these two - invalidated cache items may still be yielded

View file

@ -31,23 +31,8 @@ path = "src/ssh_authorizedkeys.rs"
required-features = ["unix"] required-features = ["unix"]
[[bin]] [[bin]]
name = "kanidm_cache_invalidate" name = "kanidm-unix"
path = "src/cache_invalidate.rs" path = "src/tool.rs"
required-features = ["unix"]
[[bin]]
name = "kanidm_cache_clear"
path = "src/cache_clear.rs"
required-features = ["unix"]
[[bin]]
name = "kanidm_unixd_status"
path = "src/daemon_status.rs"
required-features = ["unix"]
[[bin]]
name = "kanidm_test_auth"
path = "src/test_auth.rs"
required-features = ["unix"] required-features = ["unix"]
[lib] [lib]

View file

@ -6,9 +6,7 @@ use clap::{IntoApp, Parser};
use clap_complete::{generate_to, Shell}; use clap_complete::{generate_to, Shell};
include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/ssh_authorizedkeys.rs");
include!("src/opt/cache_invalidate.rs"); include!("src/opt/tool.rs");
include!("src/opt/cache_clear.rs");
include!("src/opt/unixd_status.rs");
fn main() { fn main() {
profiles::apply_profile(); profiles::apply_profile();
@ -45,46 +43,16 @@ fn main() {
generate_to( generate_to(
Shell::Zsh, Shell::Zsh,
&mut CacheInvalidateOpt::command(), &mut KanidmUnixParser::command(),
"kanidm_cache_invalidate", "kanidm_unix",
comp_dir.clone(), comp_dir.clone(),
) )
.ok(); .ok();
generate_to( generate_to(
Shell::Bash, Shell::Bash,
&mut CacheInvalidateOpt::command(), &mut KanidmUnixParser::command(),
"kanidm_cache_invalidate", "kanidm_unix",
comp_dir.clone(), comp_dir.clone(),
) )
.ok(); .ok();
generate_to(
Shell::Bash,
&mut CacheClearOpt::command(),
"kanidm_cache_clear",
comp_dir.clone(),
)
.ok();
generate_to(
Shell::Zsh,
&mut CacheClearOpt::command(),
"kanidm_cache_clear",
comp_dir.clone(),
)
.ok();
generate_to(
Shell::Bash,
&mut UnixdStatusOpt::command(),
"kanidm_unixd_status",
comp_dir.clone(),
)
.ok();
generate_to(
Shell::Zsh,
&mut UnixdStatusOpt::command(),
"kanidm_unixd_status",
comp_dir,
)
.ok();
} }

View file

@ -1,69 +0,0 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::todo)]
#![deny(clippy::unimplemented)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate tracing;
use std::process::ExitCode;
use clap::Parser;
use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
include!("./opt/cache_clear.rs");
#[tokio::main]
async fn main() -> ExitCode {
let opt = CacheClearOpt::parse();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
}
if opt.version {
println!("{}", kanidm_proto::utils::get_version("kanidm_cache_clear"));
return ExitCode::SUCCESS;
}
sketching::tracing_subscriber::fmt::init();
debug!("Starting cache invalidate tool ...");
let cfg = match KanidmUnixdConfig::new().read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE;
}
};
if !opt.really {
error!("Are you sure you want to proceed? If so use --really");
return ExitCode::SUCCESS;
}
let req = ClientRequest::ClearCache;
match block_on(call_daemon(cfg.sock_path.as_str(), req)) {
Ok(r) => match r {
ClientResponse::Ok => info!("success"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
ExitCode::SUCCESS
}

View file

@ -1,67 +0,0 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::todo)]
#![deny(clippy::unimplemented)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate tracing;
use std::process::ExitCode;
use clap::Parser;
use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
include!("./opt/cache_invalidate.rs");
#[tokio::main]
async fn main() -> ExitCode {
let opt = CacheInvalidateOpt::parse();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
}
if opt.version {
println!(
"{}",
kanidm_proto::utils::get_version("kanidm_cache_invalidate")
);
return ExitCode::SUCCESS;
}
sketching::tracing_subscriber::fmt::init();
debug!("Starting cache invalidate tool ...");
let cfg = match KanidmUnixdConfig::new().read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE;
}
};
let req = ClientRequest::InvalidateCache;
match block_on(call_daemon(cfg.sock_path.as_str(), req)) {
Ok(r) => match r {
ClientResponse::Ok => info!("success"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
ExitCode::SUCCESS
}

View file

@ -1,73 +0,0 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::todo)]
#![deny(clippy::unimplemented)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate tracing;
use std::path::PathBuf;
use clap::Parser;
// use futures::executor::block_on;
use kanidm_unix_common::client_sync::call_daemon_blocking;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
include!("./opt/unixd_status.rs");
fn main() {
let opt = UnixdStatusOpt::parse();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
}
if opt.version {
println!(
"{}",
kanidm_proto::utils::get_version("kanidm_unixd_status")
);
std::process::exit(0);
}
sketching::tracing_subscriber::fmt::init();
trace!("Starting cache status tool ...");
let cfg = match KanidmUnixdConfig::new().read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
std::process::exit(1);
}
};
let req = ClientRequest::Status;
let spath = PathBuf::from(cfg.sock_path.as_str());
if !spath.exists() {
error!(
"kanidm_unixd socket {} does not exist - is the service running?",
cfg.sock_path
)
} else {
match call_daemon_blocking(cfg.sock_path.as_str(), &req, cfg.unix_sock_timeout) {
Ok(r) => match r {
ClientResponse::Ok => println!("working!"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
}
}
}

View file

@ -1,9 +0,0 @@
#[derive(Debug, Parser)]
struct CacheClearOpt {
#[clap(short, long)]
debug: bool,
#[clap(short, long, action = clap::ArgAction::SetTrue)]
version: bool,
#[clap(long)]
really: bool,
}

View file

@ -1,7 +0,0 @@
#[derive(Debug, Parser)]
struct CacheInvalidateOpt {
#[clap(short, long)]
debug: bool,
#[clap(short, long, action = clap::ArgAction::SetTrue)]
version: bool,
}

View file

@ -0,0 +1,49 @@
use clap::Subcommand;
#[derive(Debug, Subcommand)]
#[clap(about = "Kanidm Unixd Management Utility")]
pub enum KanidmUnixOpt {
/// Test authentication of a user via the unixd resolver "pam" channel. This does not
/// test that your pam configuration is correct - only that unixd is correctly processing
/// and validating authentications.
AuthTest {
#[clap(short, long)]
debug: bool,
#[clap(short = 'D', long = "name")]
account_id: String,
},
/// Erase the content of the unixd resolver cache. You should probably use `invalidate`
/// instead.
CacheClear {
#[clap(short, long)]
debug: bool,
#[clap(long)]
really: bool,
},
/// Invalidate, but don't erase the content of the unixd resolver cache. This will force
/// the unixd daemon to refresh all user and group content immediately. If the connection
/// is offline, entries will still be available and will be refreshed as soon as the daemon
/// is online again.
CacheInvalidate {
#[clap(short, long)]
debug: bool,
},
/// Check that the unixd daemon is online and able to connect correctly to the kanidmd server.
Status {
#[clap(short, long)]
debug: bool,
},
/// Show the version of this tool.
Version {
#[clap(short, long)]
debug: bool,
}
}
#[derive(Debug, clap::Parser)]
#[clap(about = "Kanidm Unixd Management Utility")]
pub struct KanidmUnixParser {
#[clap(subcommand)]
pub commands: KanidmUnixOpt,
}

View file

@ -1,7 +0,0 @@
#[derive(Debug, Parser)]
struct UnixdStatusOpt {
#[clap(short, long)]
debug: bool,
#[clap(short, long, action = clap::ArgAction::SetTrue)]
version: bool,
}

View file

@ -1,92 +0,0 @@
#![deny(warnings)]
#[macro_use]
extern crate tracing;
use std::process::ExitCode;
use clap::Parser;
use futures::executor::block_on;
use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
#[derive(Debug, Parser)]
struct ClientOpt {
#[clap(short, long)]
debug: bool,
#[clap(short = 'D', long = "name")]
account_id: String,
}
#[tokio::main]
async fn main() -> ExitCode {
let opt = ClientOpt::parse();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
}
sketching::tracing_subscriber::fmt::init();
debug!("Starting PAM auth tester tool ...");
let Ok(cfg) = KanidmUnixdConfig::new()
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
else {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE
};
let password = match rpassword::prompt_password("Enter Unix password: ") {
Ok(p) => p,
Err(e) => {
error!("Problem getting input password: {}", e);
return ExitCode::FAILURE;
}
};
let req = ClientRequest::PamAuthenticate(opt.account_id.clone(), password);
let sereq = ClientRequest::PamAccountAllowed(opt.account_id);
match block_on(call_daemon(cfg.sock_path.as_str(), req)) {
Ok(r) => match r {
ClientResponse::PamStatus(Some(true)) => {
info!("auth success!");
}
ClientResponse::PamStatus(Some(false)) => {
info!("auth failed!");
}
ClientResponse::PamStatus(None) => {
info!("user unknown");
}
_ => {
// unexpected response.
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
match block_on(call_daemon(cfg.sock_path.as_str(), sereq)) {
Ok(r) => match r {
ClientResponse::PamStatus(Some(true)) => {
info!("auth success!");
}
ClientResponse::PamStatus(Some(false)) => {
info!("auth failed!");
}
ClientResponse::PamStatus(None) => {
info!("user unknown");
}
_ => {
// unexpected response.
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
ExitCode::SUCCESS
}

View file

@ -0,0 +1,220 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]
#![deny(clippy::todo)]
#![deny(clippy::unimplemented)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
#![deny(clippy::panic)]
#![deny(clippy::unreachable)]
#![deny(clippy::await_holding_lock)]
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
#[macro_use]
extern crate tracing;
use std::process::ExitCode;
use clap::Parser;
use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::client_sync::call_daemon_blocking;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
use std::path::PathBuf;
include!("./opt/tool.rs");
#[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode {
let opt = KanidmUnixParser::parse();
let debug = match opt.commands {
KanidmUnixOpt::AuthTest {
debug,
account_id: _,
} => debug,
KanidmUnixOpt::CacheClear { debug, really: _ } => debug,
KanidmUnixOpt::CacheInvalidate { debug } => debug,
KanidmUnixOpt::Status { debug } => debug,
KanidmUnixOpt::Version { debug } => debug,
};
if debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
}
sketching::tracing_subscriber::fmt::init();
match opt.commands {
KanidmUnixOpt::AuthTest {
debug: _,
account_id,
} => {
debug!("Starting PAM auth tester tool ...");
let Ok(cfg) = KanidmUnixdConfig::new()
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
else {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE
};
let password = match rpassword::prompt_password("Enter Unix password: ") {
Ok(p) => p,
Err(e) => {
error!("Problem getting input password: {}", e);
return ExitCode::FAILURE;
}
};
let req = ClientRequest::PamAuthenticate(account_id.clone(), password);
let sereq = ClientRequest::PamAccountAllowed(account_id);
match call_daemon(cfg.sock_path.as_str(), req).await {
Ok(r) => match r {
ClientResponse::PamStatus(Some(true)) => {
println!("auth success!");
}
ClientResponse::PamStatus(Some(false)) => {
println!("auth failed!");
}
ClientResponse::PamStatus(None) => {
println!("auth user unknown");
}
_ => {
// unexpected response.
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
match call_daemon(cfg.sock_path.as_str(), sereq).await {
Ok(r) => match r {
ClientResponse::PamStatus(Some(true)) => {
println!("account success!");
}
ClientResponse::PamStatus(Some(false)) => {
println!("account failed!");
}
ClientResponse::PamStatus(None) => {
println!("account user unknown");
}
_ => {
// unexpected response.
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
ExitCode::SUCCESS
}
KanidmUnixOpt::CacheClear { debug: _, really } => {
debug!("Starting cache clear tool ...");
let cfg = match KanidmUnixdConfig::new()
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE;
}
};
if !really {
error!("Are you sure you want to proceed? If so use --really");
return ExitCode::SUCCESS;
}
let req = ClientRequest::ClearCache;
match call_daemon(cfg.sock_path.as_str(), req).await {
Ok(r) => match r {
ClientResponse::Ok => info!("success"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
println!("success");
ExitCode::SUCCESS
}
KanidmUnixOpt::CacheInvalidate { debug: _ } => {
debug!("Starting cache invalidate tool ...");
let cfg = match KanidmUnixdConfig::new()
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE;
}
};
let req = ClientRequest::InvalidateCache;
match call_daemon(cfg.sock_path.as_str(), req).await {
Ok(r) => match r {
ClientResponse::Ok => info!("success"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
};
println!("success");
ExitCode::SUCCESS
}
KanidmUnixOpt::Status { debug: _ } => {
trace!("Starting cache status tool ...");
let cfg = match KanidmUnixdConfig::new()
.read_options_from_optional_config(DEFAULT_CONFIG_PATH)
{
Ok(c) => c,
Err(_e) => {
error!("Failed to parse {}", DEFAULT_CONFIG_PATH);
return ExitCode::FAILURE;
}
};
let req = ClientRequest::Status;
let spath = PathBuf::from(cfg.sock_path.as_str());
if !spath.exists() {
error!(
"kanidm_unixd socket {} does not exist - is the service running?",
cfg.sock_path
)
} else {
match call_daemon_blocking(cfg.sock_path.as_str(), &req, cfg.unix_sock_timeout) {
Ok(r) => match r {
ClientResponse::Ok => println!("working!"),
_ => {
error!("Error: unexpected response -> {:?}", r);
}
},
Err(e) => {
error!("Error -> {:?}", e);
}
}
}
ExitCode::SUCCESS
}
KanidmUnixOpt::Version { debug: _ } => {
println!("{}", kanidm_proto::utils::get_version("kanidm-unix"));
ExitCode::SUCCESS
}
}
}