306 command complete ()

Fixes  adding command line autocompletion. These are generated to: CARGO_TARGET_DIR/item-hash/out/. These will need to be packaged for distros later, it's unclear how we could use cargo install with these as cargo doesn't support arbitrary artefacts like this (yet?).
This commit is contained in:
Firstyear 2021-02-13 13:46:22 +10:00 committed by GitHub
parent c416bc19df
commit 6c79914395
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 671 additions and 546 deletions

View file

@ -45,3 +45,6 @@ zxcvbn = "2.0"
webauthn-authenticator-rs = "^0.3.0-alpha.6"
# webauthn-authenticator-rs = { path = "../../webauthn-authenticator-rs" }
[build-dependencies]
structopt = { version = "0.3", default-features = false }

37
kanidm_tools/build.rs Normal file
View file

@ -0,0 +1,37 @@
use std::env;
use std::path::PathBuf;
use structopt::clap::Shell;
use structopt::StructOpt;
include!("src/opt/ssh_authorizedkeys.rs");
include!("src/opt/badlist_preprocess.rs");
include!("src/opt/kanidm.rs");
fn main() {
let outdir = match env::var_os("OUT_DIR") {
None => return,
Some(outdir) => outdir,
};
SshAuthorizedOpt::clap().gen_completions(
"kanidm_ssh_authorizedkeys_direct",
Shell::Bash,
outdir.clone(),
);
SshAuthorizedOpt::clap().gen_completions(
"kanidm_ssh_authorizedkeys_direct",
Shell::Zsh,
outdir.clone(),
);
BadlistProcOpt::clap().gen_completions(
"kanidm_badlist_preprocess",
Shell::Bash,
outdir.clone(),
);
BadlistProcOpt::clap().gen_completions("kanidm_badlist_preprocess", Shell::Zsh, outdir.clone());
KanidmClientOpt::clap().gen_completions("kanidm", Shell::Bash, outdir.clone());
KanidmClientOpt::clap().gen_completions("kanidm", Shell::Zsh, outdir);
}

View file

@ -20,20 +20,10 @@ use log::{debug, error, info};
use rayon::prelude::*;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(short = "m", long = "modlist")]
modlist: bool,
#[structopt(short = "o", long = "output")]
outfile: PathBuf,
#[structopt(parse(from_os_str))]
password_list: Vec<PathBuf>,
}
include!("opt/badlist_preprocess.rs");
fn main() {
let opt = ClientOpt::from_args();
let opt = BadlistProcOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -1,182 +1,14 @@
use crate::common::CommonOpt;
use crate::password_prompt;
use crate::{
AccountCredential, AccountOpt, AccountPosix, AccountRadius, AccountSsh, AccountValidity,
};
use qrcode::render::unicode;
use qrcode::QrCode;
use std::io;
use structopt::StructOpt;
use time::OffsetDateTime;
use webauthn_authenticator_rs::{u2fhid::U2FHid, WebauthnAuthenticator};
#[derive(Debug, StructOpt)]
pub struct AccountCommonOpt {
#[structopt()]
account_id: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountCredentialSet {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedExpireDateTimeOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "datetime")]
/// An rfc3339 time of the format "YYYY-MM-DDTHH:MM:SS+TZ", "2020-09-25T11:22:02+10:00"
/// or the word "never", "clear" to remove account expiry.
datetime: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedValidDateTimeOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "datetime")]
/// An rfc3339 time of the format "YYYY-MM-DDTHH:MM:SS+TZ", "2020-09-25T11:22:02+10:00"
/// or the word "any", "clear" to remove valid from enforcement.
datetime: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedTagOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "tag")]
tag: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedTagPKOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "tag")]
tag: String,
#[structopt(name = "pubkey")]
pubkey: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountCreateOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(name = "display_name")]
display_name: String,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum AccountCredential {
#[structopt(name = "set_password")]
SetPassword(AccountCredentialSet),
#[structopt(name = "generate_password")]
GeneratePassword(AccountCredentialSet),
#[structopt(name = "register_webauthn")]
RegisterWebauthn(AccountNamedTagOpt),
/// Set the TOTP credential of the account. If a TOTP already exists, on a successful
/// registration, this will replace it.
#[structopt(name = "set_totp")]
RegisterTOTP(AccountNamedTagOpt),
/// Remove TOTP from the account. If no TOTP exists, no action is taken.
#[structopt(name = "remove_totp")]
RemoveTOTP(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountRadius {
#[structopt(name = "show_secret")]
Show(AccountNamedOpt),
#[structopt(name = "generate_secret")]
Generate(AccountNamedOpt),
#[structopt(name = "delete_secret")]
Delete(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub struct AccountPosixOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(long = "gidnumber")]
gidnumber: Option<u32>,
#[structopt(long = "shell")]
shell: Option<String>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum AccountPosix {
#[structopt(name = "show")]
Show(AccountNamedOpt),
#[structopt(name = "set")]
Set(AccountPosixOpt),
#[structopt(name = "set_password")]
SetPassword(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountSsh {
#[structopt(name = "list_publickeys")]
List(AccountNamedOpt),
#[structopt(name = "add_publickey")]
Add(AccountNamedTagPKOpt),
#[structopt(name = "delete_publickey")]
Delete(AccountNamedTagOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountValidity {
#[structopt(name = "show")]
Show(AccountNamedOpt),
#[structopt(name = "expire_at")]
ExpireAt(AccountNamedExpireDateTimeOpt),
#[structopt(name = "begin_from")]
BeginFrom(AccountNamedValidDateTimeOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountOpt {
#[structopt(name = "credential")]
Credential(AccountCredential),
#[structopt(name = "radius")]
Radius(AccountRadius),
#[structopt(name = "posix")]
Posix(AccountPosix),
#[structopt(name = "ssh")]
Ssh(AccountSsh),
#[structopt(name = "list")]
List(CommonOpt),
#[structopt(name = "get")]
Get(AccountNamedOpt),
#[structopt(name = "create")]
Create(AccountCreateOpt),
#[structopt(name = "delete")]
Delete(AccountNamedOpt),
#[structopt(name = "validity")]
Validity(AccountValidity),
}
impl AccountOpt {
pub fn debug(&self) -> bool {
match self {

View file

@ -1,27 +1,6 @@
use crate::login::read_tokens;
use crate::CommonOpt;
use kanidm_client::{KanidmClient, KanidmClientBuilder};
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct Named {
#[structopt()]
pub name: String,
#[structopt(flatten)]
pub copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct CommonOpt {
#[structopt(short = "d", long = "debug")]
pub debug: bool,
#[structopt(short = "H", long = "url")]
pub addr: Option<String>,
#[structopt(short = "D", long = "name")]
pub username: Option<String>,
#[structopt(parse(from_os_str), short = "C", long = "ca")]
pub ca_path: Option<PathBuf>,
}
impl CommonOpt {
pub fn to_unauth_client(&self) -> KanidmClient {

View file

@ -1,55 +1,4 @@
use crate::common::{CommonOpt, Named};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct GroupNamedMembers {
#[structopt()]
name: String,
#[structopt()]
members: Vec<String>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct GroupPosixOpt {
#[structopt()]
name: String,
#[structopt(long = "gidnumber")]
gidnumber: Option<u32>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum GroupPosix {
#[structopt(name = "show")]
Show(Named),
#[structopt(name = "set")]
Set(GroupPosixOpt),
}
#[derive(Debug, StructOpt)]
pub enum GroupOpt {
#[structopt(name = "list")]
List(CommonOpt),
#[structopt(name = "get")]
Get(Named),
#[structopt(name = "create")]
Create(Named),
#[structopt(name = "delete")]
Delete(Named),
#[structopt(name = "list_members")]
ListMembers(Named),
#[structopt(name = "set_members")]
SetMembers(GroupNamedMembers),
#[structopt(name = "purge_members")]
PurgeMembers(Named),
#[structopt(name = "add_members")]
AddMembers(GroupNamedMembers),
#[structopt(name = "posix")]
Posix(GroupPosix),
}
use crate::{GroupOpt, GroupPosix};
impl GroupOpt {
pub fn debug(&self) -> bool {

View file

@ -10,8 +10,11 @@
#[macro_use]
extern crate log;
use std::path::PathBuf;
use structopt::StructOpt;
include!("../opt/kanidm.rs");
pub mod account;
pub mod common;
pub mod group;
@ -19,23 +22,6 @@ pub mod login;
pub mod raw;
pub mod recycle;
use crate::account::AccountOpt;
use crate::common::CommonOpt;
use crate::group::GroupOpt;
use crate::login::LoginOpt;
use crate::raw::RawOpt;
use crate::recycle::RecycleOpt;
#[derive(Debug, StructOpt)]
pub enum SelfOpt {
#[structopt(name = "whoami")]
/// Show the current authenticated user's identity
Whoami(CommonOpt),
#[structopt(name = "set_password")]
/// Set the current user's password
SetPassword(CommonOpt),
}
impl SelfOpt {
pub fn debug(&self) -> bool {
match self {
@ -80,49 +66,26 @@ impl SelfOpt {
}
}
#[derive(Debug, StructOpt)]
#[structopt(about = "Kanidm Client Utility")]
pub enum ClientOpt {
#[structopt(name = "login")]
/// Login to an account to use with future cli operations
Login(LoginOpt),
#[structopt(name = "self")]
/// Actions for the current authenticated account
CSelf(SelfOpt),
#[structopt(name = "account")]
/// Account operations
Account(AccountOpt),
#[structopt(name = "group")]
/// Group operations
Group(GroupOpt),
#[structopt(name = "recycle_bin")]
/// Recycle Bin operations
Recycle(RecycleOpt),
#[structopt(name = "raw")]
/// Unsafe - low level, raw database operations.
Raw(RawOpt),
}
impl ClientOpt {
impl KanidmClientOpt {
pub fn debug(&self) -> bool {
match self {
ClientOpt::Raw(ropt) => ropt.debug(),
ClientOpt::Login(lopt) => lopt.debug(),
ClientOpt::CSelf(csopt) => csopt.debug(),
ClientOpt::Account(aopt) => aopt.debug(),
ClientOpt::Group(gopt) => gopt.debug(),
ClientOpt::Recycle(ropt) => ropt.debug(),
KanidmClientOpt::Raw(ropt) => ropt.debug(),
KanidmClientOpt::Login(lopt) => lopt.debug(),
KanidmClientOpt::CSelf(csopt) => csopt.debug(),
KanidmClientOpt::Account(aopt) => aopt.debug(),
KanidmClientOpt::Group(gopt) => gopt.debug(),
KanidmClientOpt::Recycle(ropt) => ropt.debug(),
}
}
pub fn exec(&self) {
match self {
ClientOpt::Raw(ropt) => ropt.exec(),
ClientOpt::Login(lopt) => lopt.exec(),
ClientOpt::CSelf(csopt) => csopt.exec(),
ClientOpt::Account(aopt) => aopt.exec(),
ClientOpt::Group(gopt) => gopt.exec(),
ClientOpt::Recycle(ropt) => ropt.exec(),
KanidmClientOpt::Raw(ropt) => ropt.exec(),
KanidmClientOpt::Login(lopt) => lopt.exec(),
KanidmClientOpt::CSelf(csopt) => csopt.exec(),
KanidmClientOpt::Account(aopt) => aopt.exec(),
KanidmClientOpt::Group(gopt) => gopt.exec(),
KanidmClientOpt::Recycle(ropt) => ropt.exec(),
}
}
}

View file

@ -1,4 +1,4 @@
use crate::common::CommonOpt;
use crate::LoginOpt;
use kanidm_client::{ClientError, KanidmClient};
use kanidm_proto::v1::{AuthAllowed, AuthResponse, AuthState};
use libc::umask;
@ -6,7 +6,6 @@ use std::collections::BTreeMap;
use std::fs::{create_dir, File};
use std::io::{self, BufReader, BufWriter};
use std::path::PathBuf;
use structopt::StructOpt;
use webauthn_authenticator_rs::{u2fhid::U2FHid, RequestChallengeResponse, WebauthnAuthenticator};
static TOKEN_DIR: &str = "~/.cache";
@ -102,14 +101,6 @@ fn get_index_choice(len: usize) -> Result<u8, ClientError> {
}
}
#[derive(Debug, StructOpt)]
pub struct LoginOpt {
#[structopt(flatten)]
pub copt: CommonOpt,
#[structopt(short = "w", long = "webauthn")]
pub webauthn: bool,
}
impl LoginOpt {
pub fn debug(&self) -> bool {
self.copt.debug

View file

@ -8,11 +8,11 @@
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use kanidm_cli::ClientOpt;
use kanidm_cli::KanidmClientOpt;
use structopt::StructOpt;
fn main() {
let opt = ClientOpt::from_args();
let opt = KanidmClientOpt::from_args();
if opt.debug() {
::std::env::set_var(

View file

@ -1,54 +1,14 @@
use crate::common::CommonOpt;
use crate::RawOpt;
use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList};
use std::collections::BTreeMap;
use structopt::StructOpt;
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
use std::path::PathBuf;
use serde::de::DeserializeOwned;
#[derive(Debug, StructOpt)]
pub struct FilterOpt {
#[structopt()]
filter: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct CreateOpt {
#[structopt(parse(from_os_str))]
file: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct ModifyOpt {
#[structopt(flatten)]
commonopts: CommonOpt,
#[structopt()]
filter: String,
#[structopt(parse(from_os_str))]
file: PathBuf,
}
#[derive(Debug, StructOpt)]
pub enum RawOpt {
#[structopt(name = "search")]
Search(FilterOpt),
#[structopt(name = "create")]
Create(CreateOpt),
#[structopt(name = "modify")]
Modify(ModifyOpt),
#[structopt(name = "delete")]
Delete(FilterOpt),
}
fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
let f = File::open(path)?;
let r = BufReader::new(f);

View file

@ -1,18 +1,4 @@
use crate::common::{CommonOpt, Named};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub enum RecycleOpt {
#[structopt(name = "list")]
/// List objects that are in the recycle bin
List(CommonOpt),
#[structopt(name = "get")]
/// Display an object from the recycle bin
Get(Named),
#[structopt(name = "revive")]
/// Revive a recycled object into a live (accessible) state - this is the opposite of "delete"
Revive(Named),
}
use crate::RecycleOpt;
impl RecycleOpt {
pub fn debug(&self) -> bool {

View file

@ -0,0 +1,12 @@
#[derive(Debug, StructOpt)]
struct BadlistProcOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(short = "m", long = "modlist")]
modlist: bool,
#[structopt(short = "o", long = "output")]
outfile: PathBuf,
#[structopt(parse(from_os_str))]
password_list: Vec<PathBuf>,
}

View file

@ -0,0 +1,333 @@
#[derive(Debug, StructOpt)]
pub struct Named {
#[structopt()]
pub name: String,
#[structopt(flatten)]
pub copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct CommonOpt {
#[structopt(short = "d", long = "debug")]
pub debug: bool,
#[structopt(short = "H", long = "url")]
pub addr: Option<String>,
#[structopt(short = "D", long = "name")]
pub username: Option<String>,
#[structopt(parse(from_os_str), short = "C", long = "ca")]
pub ca_path: Option<PathBuf>,
}
#[derive(Debug, StructOpt)]
pub struct GroupNamedMembers {
#[structopt()]
name: String,
#[structopt()]
members: Vec<String>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct GroupPosixOpt {
#[structopt()]
name: String,
#[structopt(long = "gidnumber")]
gidnumber: Option<u32>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum GroupPosix {
#[structopt(name = "show")]
Show(Named),
#[structopt(name = "set")]
Set(GroupPosixOpt),
}
#[derive(Debug, StructOpt)]
pub enum GroupOpt {
#[structopt(name = "list")]
List(CommonOpt),
#[structopt(name = "get")]
Get(Named),
#[structopt(name = "create")]
Create(Named),
#[structopt(name = "delete")]
Delete(Named),
#[structopt(name = "list_members")]
ListMembers(Named),
#[structopt(name = "set_members")]
SetMembers(GroupNamedMembers),
#[structopt(name = "purge_members")]
PurgeMembers(Named),
#[structopt(name = "add_members")]
AddMembers(GroupNamedMembers),
#[structopt(name = "posix")]
Posix(GroupPosix),
}
#[derive(Debug, StructOpt)]
pub struct AccountCommonOpt {
#[structopt()]
account_id: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountCredentialSet {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedExpireDateTimeOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "datetime")]
/// An rfc3339 time of the format "YYYY-MM-DDTHH:MM:SS+TZ", "2020-09-25T11:22:02+10:00"
/// or the word "never", "clear" to remove account expiry.
datetime: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedValidDateTimeOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "datetime")]
/// An rfc3339 time of the format "YYYY-MM-DDTHH:MM:SS+TZ", "2020-09-25T11:22:02+10:00"
/// or the word "any", "clear" to remove valid from enforcement.
datetime: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedTagOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "tag")]
tag: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountNamedTagPKOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(flatten)]
copt: CommonOpt,
#[structopt(name = "tag")]
tag: String,
#[structopt(name = "pubkey")]
pubkey: String,
}
#[derive(Debug, StructOpt)]
pub struct AccountCreateOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(name = "display_name")]
display_name: String,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum AccountCredential {
#[structopt(name = "set_password")]
SetPassword(AccountCredentialSet),
#[structopt(name = "generate_password")]
GeneratePassword(AccountCredentialSet),
#[structopt(name = "register_webauthn")]
RegisterWebauthn(AccountNamedTagOpt),
/// Set the TOTP credential of the account. If a TOTP already exists, on a successful
/// registration, this will replace it.
#[structopt(name = "set_totp")]
RegisterTOTP(AccountNamedTagOpt),
/// Remove TOTP from the account. If no TOTP exists, no action is taken.
#[structopt(name = "remove_totp")]
RemoveTOTP(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountRadius {
#[structopt(name = "show_secret")]
Show(AccountNamedOpt),
#[structopt(name = "generate_secret")]
Generate(AccountNamedOpt),
#[structopt(name = "delete_secret")]
Delete(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub struct AccountPosixOpt {
#[structopt(flatten)]
aopts: AccountCommonOpt,
#[structopt(long = "gidnumber")]
gidnumber: Option<u32>,
#[structopt(long = "shell")]
shell: Option<String>,
#[structopt(flatten)]
copt: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub enum AccountPosix {
#[structopt(name = "show")]
Show(AccountNamedOpt),
#[structopt(name = "set")]
Set(AccountPosixOpt),
#[structopt(name = "set_password")]
SetPassword(AccountNamedOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountSsh {
#[structopt(name = "list_publickeys")]
List(AccountNamedOpt),
#[structopt(name = "add_publickey")]
Add(AccountNamedTagPKOpt),
#[structopt(name = "delete_publickey")]
Delete(AccountNamedTagOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountValidity {
#[structopt(name = "show")]
Show(AccountNamedOpt),
#[structopt(name = "expire_at")]
ExpireAt(AccountNamedExpireDateTimeOpt),
#[structopt(name = "begin_from")]
BeginFrom(AccountNamedValidDateTimeOpt),
}
#[derive(Debug, StructOpt)]
pub enum AccountOpt {
#[structopt(name = "credential")]
Credential(AccountCredential),
#[structopt(name = "radius")]
Radius(AccountRadius),
#[structopt(name = "posix")]
Posix(AccountPosix),
#[structopt(name = "ssh")]
Ssh(AccountSsh),
#[structopt(name = "list")]
List(CommonOpt),
#[structopt(name = "get")]
Get(AccountNamedOpt),
#[structopt(name = "create")]
Create(AccountCreateOpt),
#[structopt(name = "delete")]
Delete(AccountNamedOpt),
#[structopt(name = "validity")]
Validity(AccountValidity),
}
#[derive(Debug, StructOpt)]
pub enum RecycleOpt {
#[structopt(name = "list")]
/// List objects that are in the recycle bin
List(CommonOpt),
#[structopt(name = "get")]
/// Display an object from the recycle bin
Get(Named),
#[structopt(name = "revive")]
/// Revive a recycled object into a live (accessible) state - this is the opposite of "delete"
Revive(Named),
}
#[derive(Debug, StructOpt)]
pub struct LoginOpt {
#[structopt(flatten)]
pub copt: CommonOpt,
#[structopt(short = "w", long = "webauthn")]
pub webauthn: bool,
}
#[derive(Debug, StructOpt)]
pub struct FilterOpt {
#[structopt()]
filter: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct CreateOpt {
#[structopt(parse(from_os_str))]
file: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
pub struct ModifyOpt {
#[structopt(flatten)]
commonopts: CommonOpt,
#[structopt()]
filter: String,
#[structopt(parse(from_os_str))]
file: PathBuf,
}
#[derive(Debug, StructOpt)]
pub enum RawOpt {
#[structopt(name = "search")]
Search(FilterOpt),
#[structopt(name = "create")]
Create(CreateOpt),
#[structopt(name = "modify")]
Modify(ModifyOpt),
#[structopt(name = "delete")]
Delete(FilterOpt),
}
#[derive(Debug, StructOpt)]
pub enum SelfOpt {
#[structopt(name = "whoami")]
/// Show the current authenticated user's identity
Whoami(CommonOpt),
#[structopt(name = "set_password")]
/// Set the current user's password
SetPassword(CommonOpt),
}
#[derive(Debug, StructOpt)]
#[structopt(about = "Kanidm Client Utility")]
pub enum KanidmClientOpt {
#[structopt(name = "login")]
/// Login to an account to use with future cli operations
Login(LoginOpt),
#[structopt(name = "self")]
/// Actions for the current authenticated account
CSelf(SelfOpt),
#[structopt(name = "account")]
/// Account operations
Account(AccountOpt),
#[structopt(name = "group")]
/// Group operations
Group(GroupOpt),
#[structopt(name = "recycle_bin")]
/// Recycle Bin operations
Recycle(RecycleOpt),
#[structopt(name = "raw")]
/// Unsafe - low level, raw database operations.
Raw(RawOpt),
}

View file

@ -0,0 +1,14 @@
#[derive(Debug, StructOpt)]
struct SshAuthorizedOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(short = "H", long = "url")]
addr: Option<String>,
#[structopt(short = "D", long = "name")]
username: String,
#[structopt(parse(from_os_str), short = "C", long = "ca")]
ca_path: Option<PathBuf>,
#[structopt()]
account_id: String,
}

View file

@ -8,33 +8,20 @@
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use std::path::PathBuf;
use kanidm_client::KanidmClientBuilder;
use std::path::PathBuf;
use log::{debug, error};
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(short = "H", long = "url")]
addr: Option<String>,
#[structopt(short = "D", long = "name")]
username: String,
#[structopt(parse(from_os_str), short = "C", long = "ca")]
ca_path: Option<PathBuf>,
#[structopt()]
account_id: String,
}
include!("opt/ssh_authorizedkeys.rs");
// For now we lift a few things from the main.rs to use.
//
// usage: AuthorizedKeysCommand /usr/sbin/kanidm_ssh_authorizedkeys %u -H URL -D anonymous -C /etc/kanidm/ca.pem
//
fn main() {
let opt = ClientOpt::from_args();
let opt = SshAuthorizedOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -75,3 +75,7 @@ lru = "0.6"
[dev-dependencies]
kanidm = { path = "../kanidmd" }
[build-dependencies]
structopt = { version = "0.3", default-features = false }

44
kanidm_unix_int/build.rs Normal file
View file

@ -0,0 +1,44 @@
use std::env;
use structopt::clap::Shell;
use structopt::StructOpt;
include!("src/opt/ssh_authorizedkeys.rs");
include!("src/opt/cache_invalidate.rs");
include!("src/opt/cache_clear.rs");
include!("src/opt/unixd_status.rs");
fn main() {
let outdir = match env::var_os("OUT_DIR") {
None => return,
Some(outdir) => outdir,
};
SshAuthorizedOpt::clap().gen_completions(
"kanidm_ssh_authorizedkeys",
Shell::Bash,
outdir.clone(),
);
SshAuthorizedOpt::clap().gen_completions(
"kanidm_ssh_authorizedkeys",
Shell::Zsh,
outdir.clone(),
);
CacheInvalidateOpt::clap().gen_completions(
"kanidm_cache_invalidate",
Shell::Bash,
outdir.clone(),
);
CacheInvalidateOpt::clap().gen_completions(
"kanidm_cache_invalidate",
Shell::Zsh,
outdir.clone(),
);
CacheClearOpt::clap().gen_completions("kanidm_cache_clear", Shell::Bash, outdir.clone());
CacheClearOpt::clap().gen_completions("kanidm_cache_clear", Shell::Zsh, outdir.clone());
UnixdStatusOpt::clap().gen_completions("kanidm_unixd_status", Shell::Bash, outdir.clone());
UnixdStatusOpt::clap().gen_completions("kanidm_unixd_status", Shell::Zsh, outdir);
}

View file

@ -20,17 +20,11 @@ use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(long = "really")]
really: bool,
}
include!("./opt/cache_clear.rs");
#[tokio::main]
async fn main() {
let opt = ClientOpt::from_args();
let opt = CacheClearOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -20,15 +20,11 @@ use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
}
include!("./opt/cache_invalidate.rs");
#[tokio::main]
async fn main() {
let opt = ClientOpt::from_args();
let opt = CacheInvalidateOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -20,15 +20,11 @@ use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
}
include!("./opt/unixd_status.rs");
#[tokio::main]
async fn main() {
let opt = ClientOpt::from_args();
let opt = UnixdStatusOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -0,0 +1,9 @@
#[derive(Debug, StructOpt)]
struct CacheClearOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt(long = "really")]
really: bool,
}

View file

@ -0,0 +1,7 @@
#[derive(Debug, StructOpt)]
struct CacheInvalidateOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
}

View file

@ -0,0 +1,8 @@
#[derive(Debug, StructOpt)]
struct SshAuthorizedOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt()]
account_id: String,
}

View file

@ -0,0 +1,6 @@
#[derive(Debug, StructOpt)]
struct UnixdStatusOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
}

View file

@ -20,17 +20,11 @@ use kanidm_unix_common::client::call_daemon;
use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
#[derive(Debug, StructOpt)]
struct ClientOpt {
#[structopt(short = "d", long = "debug")]
debug: bool,
#[structopt()]
account_id: String,
}
include!("./opt/ssh_authorizedkeys.rs");
#[tokio::main]
async fn main() {
let opt = ClientOpt::from_args();
let opt = SshAuthorizedOpt::from_args();
if opt.debug {
::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug");
} else {

View file

@ -111,3 +111,9 @@ webauthn-authenticator-rs = "0.3.0-alpha.5"
version = "1"
default-features = false # Disable features which are enabled by default
features = ["precommit-hook", "run-cargo-fmt"]
[build-dependencies]
structopt = { version = "0.3", default-features = false }
serde = "1.0"
serde_derive = "1.0"

21
kanidmd/build.rs Normal file
View file

@ -0,0 +1,21 @@
#[macro_use]
extern crate serde_derive;
use std::env;
use std::path::PathBuf;
use structopt::clap::Shell;
use structopt::StructOpt;
include!("src/lib/audit_loglevel.rs");
include!("src/server/opt.rs");
fn main() {
let outdir = match env::var_os("OUT_DIR") {
None => return,
Some(outdir) => outdir,
};
KanidmdOpt::clap().gen_completions("kanidmd", Shell::Bash, outdir.clone());
KanidmdOpt::clap().gen_completions("kanidmd", Shell::Zsh, outdir);
}

View file

@ -8,7 +8,7 @@ use chrono::offset::Utc;
use chrono::DateTime;
use uuid::Uuid;
use std::str::FromStr;
include!("./audit_loglevel.rs");
pub const AUDIT_LINE_SIZE: usize = 512;
@ -38,41 +38,6 @@ pub enum LogTag {
Trace = 0x8000_0000,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(u32)]
pub enum LogLevel {
// Errors only
Quiet = 0x0000_1111,
// All Error, All Security, Request and Admin Warning,
Default = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x1000_0000,
// Default + Filter Plans
Filter = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x0000_4000 | 0x1000_0000,
// All Error, All Warning, All Info, Filter and Request Tracing
Verbose = 0x0000_ffff | 0x1000_0000,
// Default + PerfCoarse
PerfBasic = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x3000_0000,
// Default + PerfCoarse ? PerfTrace
PerfFull = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x7000_0000,
// Yolo
FullTrace = 0xffff_ffff,
}
impl FromStr for LogLevel {
type Err = &'static str;
fn from_str(l: &str) -> Result<Self, Self::Err> {
match l.to_lowercase().as_str() {
"quiet" => Ok(LogLevel::Quiet),
"default" => Ok(LogLevel::Default),
"filter" => Ok(LogLevel::Filter),
"verbose" => Ok(LogLevel::Verbose),
"perfbasic" => Ok(LogLevel::PerfBasic),
"perffull" => Ok(LogLevel::PerfFull),
"fulltrace" => Ok(LogLevel::FullTrace),
_ => Err("Could not parse loglevel"),
}
}
}
impl fmt::Display for LogTag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {

View file

@ -0,0 +1,35 @@
use std::str::FromStr;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[repr(u32)]
pub enum LogLevel {
// Errors only
Quiet = 0x0000_1111,
// All Error, All Security, Request and Admin Warning,
Default = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x1000_0000,
// Default + Filter Plans
Filter = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x0000_4000 | 0x1000_0000,
// All Error, All Warning, All Info, Filter and Request Tracing
Verbose = 0x0000_ffff | 0x1000_0000,
// Default + PerfCoarse
PerfBasic = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x3000_0000,
// Default + PerfCoarse ? PerfTrace
PerfFull = 0x0000_1111 | 0x0000_0f00 | 0x0000_0022 | 0x7000_0000,
// Yolo
FullTrace = 0xffff_ffff,
}
impl FromStr for LogLevel {
type Err = &'static str;
fn from_str(l: &str) -> Result<Self, Self::Err> {
match l.to_lowercase().as_str() {
"quiet" => Ok(LogLevel::Quiet),
"default" => Ok(LogLevel::Default),
"filter" => Ok(LogLevel::Filter),
"verbose" => Ok(LogLevel::Verbose),
"perfbasic" => Ok(LogLevel::PerfBasic),
"perffull" => Ok(LogLevel::PerfFull),
"fulltrace" => Ok(LogLevel::FullTrace),
_ => Err("Could not parse loglevel"),
}
}
}

View file

@ -27,6 +27,8 @@ use kanidm::core::{
use structopt::StructOpt;
include!("./opt.rs");
#[derive(Debug, Deserialize)]
struct ServerConfig {
pub bindaddress: Option<String>,
@ -55,87 +57,16 @@ impl ServerConfig {
}
}
#[derive(Debug, StructOpt)]
struct CommonOpt {
#[structopt(short = "d", long = "debug")]
/// Logging level. quiet, default, filter, verbose, perffull
debug: Option<LogLevel>,
#[structopt(parse(from_os_str), short = "c", long = "config")]
/// Path to the server's configuration file. If it does not exist, it will be created.
config_path: PathBuf,
}
#[derive(Debug, StructOpt)]
struct BackupOpt {
#[structopt(parse(from_os_str))]
/// Output path for the backup content.
path: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct RestoreOpt {
#[structopt(parse(from_os_str))]
/// Restore from this path. Should be created with "backupu".
path: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct RecoverAccountOpt {
#[structopt(short)]
/// The account name to recover credentials for.
name: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct DomainOpt {
#[structopt(short)]
/// The new domain name.
new_domain_name: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
enum Opt {
#[structopt(name = "server")]
/// Start the IDM Server
Server(CommonOpt),
#[structopt(name = "backup")]
/// Backup the database content (offline)
Backup(BackupOpt),
#[structopt(name = "restore")]
/// Restore the database content (offline)
Restore(RestoreOpt),
#[structopt(name = "verify")]
/// Verify database and entity consistency.
Verify(CommonOpt),
#[structopt(name = "recover_account")]
/// Recover an account's password
RecoverAccount(RecoverAccountOpt),
// #[structopt(name = "reset_server_id")]
// ResetServerId(CommonOpt),
#[structopt(name = "reindex")]
/// Reindex the database (offline)
Reindex(CommonOpt),
#[structopt(name = "domain_name_change")]
/// Change the IDM domain name
DomainChange(DomainOpt),
}
impl Opt {
impl KanidmdOpt {
fn commonopt(&self) -> &CommonOpt {
match self {
Opt::Server(sopt) | Opt::Verify(sopt) | Opt::Reindex(sopt) => &sopt,
Opt::Backup(bopt) => &bopt.commonopts,
Opt::Restore(ropt) => &ropt.commonopts,
Opt::RecoverAccount(ropt) => &ropt.commonopts,
Opt::DomainChange(dopt) => &dopt.commonopts,
KanidmdOpt::Server(sopt) | KanidmdOpt::Verify(sopt) | KanidmdOpt::Reindex(sopt) => {
&sopt
}
KanidmdOpt::Backup(bopt) => &bopt.commonopts,
KanidmdOpt::Restore(ropt) => &ropt.commonopts,
KanidmdOpt::RecoverAccount(ropt) => &ropt.commonopts,
KanidmdOpt::DomainChange(dopt) => &dopt.commonopts,
}
}
}
@ -175,7 +106,7 @@ async fn main() {
}
// Read cli args, determine if we should backup/restore
let opt = Opt::from_args();
let opt = KanidmdOpt::from_args();
let mut config = Configuration::new();
// Check the permissions are sane.
@ -295,7 +226,7 @@ async fn main() {
.init();
match opt {
Opt::Server(_sopt) => {
KanidmdOpt::Server(_sopt) => {
eprintln!("Running in server mode ...");
/*
@ -323,7 +254,7 @@ async fn main() {
}
}
}
Opt::Backup(bopt) => {
KanidmdOpt::Backup(bopt) => {
eprintln!("Running in backup mode ...");
// config.update_db_path(&bopt.commonopts.db_path);
@ -337,7 +268,7 @@ async fn main() {
};
backup_server_core(&config, p);
}
Opt::Restore(ropt) => {
KanidmdOpt::Restore(ropt) => {
eprintln!("Running in restore mode ...");
// config.update_db_path(&ropt.commonopts.db_path);
@ -351,13 +282,13 @@ async fn main() {
};
restore_server_core(&config, p);
}
Opt::Verify(_vopt) => {
KanidmdOpt::Verify(_vopt) => {
eprintln!("Running in db verification mode ...");
// config.update_db_path(&vopt.db_path);
verify_server_core(&config);
}
Opt::RecoverAccount(raopt) => {
KanidmdOpt::RecoverAccount(raopt) => {
eprintln!("Running account recovery ...");
let password = match rpassword::prompt_password_stderr("new password: ") {
@ -372,20 +303,20 @@ async fn main() {
recover_account_core(&config, &raopt.name, &password);
}
/*
Opt::ResetServerId(vopt) => {
KanidmdOpt::ResetServerId(vopt) => {
eprintln!("Resetting server id. THIS WILL BREAK REPLICATION");
config.update_db_path(&vopt.db_path);
reset_sid_core(config);
}
*/
Opt::Reindex(_copt) => {
KanidmdOpt::Reindex(_copt) => {
eprintln!("Running in reindex mode ...");
// config.update_db_path(&copt.db_path);
reindex_server_core(&config);
}
Opt::DomainChange(dopt) => {
KanidmdOpt::DomainChange(dopt) => {
eprintln!("Running in domain name change mode ... this may take a long time ...");
// config.update_db_path(&dopt.commonopts.db_path);

73
kanidmd/src/server/opt.rs Normal file
View file

@ -0,0 +1,73 @@
#[derive(Debug, StructOpt)]
struct CommonOpt {
#[structopt(short = "d", long = "debug")]
/// Logging level. quiet, default, filter, verbose, perffull
debug: Option<LogLevel>,
#[structopt(parse(from_os_str), short = "c", long = "config")]
/// Path to the server's configuration file. If it does not exist, it will be created.
config_path: PathBuf,
}
#[derive(Debug, StructOpt)]
struct BackupOpt {
#[structopt(parse(from_os_str))]
/// Output path for the backup content.
path: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct RestoreOpt {
#[structopt(parse(from_os_str))]
/// Restore from this path. Should be created with "backupu".
path: PathBuf,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct RecoverAccountOpt {
#[structopt(short)]
/// The account name to recover credentials for.
name: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
struct DomainOpt {
#[structopt(short)]
/// The new domain name.
new_domain_name: String,
#[structopt(flatten)]
commonopts: CommonOpt,
}
#[derive(Debug, StructOpt)]
enum KanidmdOpt {
#[structopt(name = "server")]
/// Start the IDM Server
Server(CommonOpt),
#[structopt(name = "backup")]
/// Backup the database content (offline)
Backup(BackupOpt),
#[structopt(name = "restore")]
/// Restore the database content (offline)
Restore(RestoreOpt),
#[structopt(name = "verify")]
/// Verify database and entity consistency.
Verify(CommonOpt),
#[structopt(name = "recover_account")]
/// Recover an account's password
RecoverAccount(RecoverAccountOpt),
// #[structopt(name = "reset_server_id")]
// ResetServerId(CommonOpt),
#[structopt(name = "reindex")]
/// Reindex the database (offline)
Reindex(CommonOpt),
#[structopt(name = "domain_name_change")]
/// Change the IDM domain name
DomainChange(DomainOpt),
}