diff --git a/.gitignore b/.gitignore index 2cb02c26c..80f2cbb95 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ vendor.tar.* orca/example_profiles/small/orca-edited.toml docs/ kanidm_unix_int/pam_tester/Cargo.lock +.vscode/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 232926b45..f358192f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,17 +152,16 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c290043c9a95b05d45e952fb6383c67bcb61471f60cfa21e890dba6654234f43" +checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880" dependencies = [ "async-channel", "async-executor", "async-io", - "async-mutex", + "async-lock", "blocking", "futures-lite", - "num_cpus", "once_cell", "tokio", ] @@ -185,9 +184,9 @@ dependencies = [ [[package]] name = "async-io" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" +checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" dependencies = [ "concurrent-queue", "futures-lite", @@ -211,15 +210,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - [[package]] name = "async-process" version = "1.4.0" @@ -321,9 +311,9 @@ checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" [[package]] name = "async-trait" -version = "0.1.53" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", "quote", @@ -531,9 +521,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "byte-tools" @@ -622,10 +612,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "bitflags", - "textwrap", + "textwrap 0.11.0", "unicode-width", ] +[[package]] +name = "clap" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim", + "termcolor", + "textwrap 0.15.0", +] + +[[package]] +name = "clap_complete" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4" +dependencies = [ + "clap 3.1.18", +] + +[[package]] +name = "clap_derive" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "compact_jwt" version = "0.2.2" @@ -798,7 +836,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools 0.10.3", @@ -970,11 +1008,12 @@ dependencies = [ name = "daemon" version = "1.1.0-alpha.8" dependencies = [ + "clap 3.1.18", + "clap_complete", "kanidm", "profiles", "score", "serde", - "structopt", "tikv-jemallocator", "tokio", "toml", @@ -1016,16 +1055,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if 1.0.0", - "num_cpus", -] - [[package]] name = "derive_builder" version = "0.11.2" @@ -1215,9 +1244,9 @@ dependencies = [ [[package]] name = "femme" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2997b612abb06bc299486c807e68c5fd12e7618e69cf34c5958ca6b575674403" +checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1684,12 +1713,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -1738,14 +1764,14 @@ checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa 1.0.2", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -1754,13 +1780,12 @@ dependencies = [ [[package]] name = "http-client" -version = "6.5.1" +version = "6.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea880b03c18a7e981d7fb3608b8904a98425d53c440758fcebf7d934aa56547c" +checksum = "e023af341b797ce2c039f7c6e1d347b68d0f7fd0bc7ac234fe69cfadcca1f89a" dependencies = [ "async-trait", "cfg-if 1.0.0", - "dashmap", "http-types", "log", ] @@ -1801,9 +1826,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ "bytes", "futures-channel", @@ -1814,7 +1839,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.1", + "itoa 1.0.2", "pin-project-lite 0.2.9", "socket2", "tokio", @@ -1878,9 +1903,9 @@ checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", "hashbrown 0.11.2", @@ -1933,9 +1958,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "joinery" @@ -2042,6 +2067,8 @@ dependencies = [ name = "kanidm_tools" version = "1.1.0-alpha.8" dependencies = [ + "clap 3.1.18", + "clap_complete", "compact_jwt", "dialoguer", "kanidm_client", @@ -2053,7 +2080,6 @@ dependencies = [ "serde", "serde_json", "shellexpand", - "structopt", "time 0.2.27", "tokio", "tracing", @@ -2068,6 +2094,8 @@ name = "kanidm_unix_int" version = "1.1.0-alpha.8" dependencies = [ "bytes", + "clap 3.1.18", + "clap_complete", "futures", "kanidm", "kanidm_client", @@ -2084,7 +2112,6 @@ dependencies = [ "score", "serde", "serde_json", - "structopt", "tokio", "tokio-util", "toml", @@ -2468,9 +2495,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" [[package]] name = "oncemutex" @@ -2530,9 +2557,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" dependencies = [ "autocfg", "cc", @@ -2545,6 +2572,7 @@ dependencies = [ name = "orca" version = "1.1.0-alpha.8" dependencies = [ + "clap 3.1.18", "crossbeam", "csv", "dialoguer", @@ -2558,7 +2586,6 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "structopt", "tikv-jemallocator", "tokio", "tokio-openssl", @@ -2569,6 +2596,12 @@ dependencies = [ "uuid 1.1.1", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "pam_kanidm" version = "1.1.0-alpha.8" @@ -2592,7 +2625,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -2609,6 +2652,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "paste" version = "0.1.18" @@ -2804,11 +2860,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -2878,7 +2934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" dependencies = [ "log", - "parking_lot", + "parking_lot 0.11.2", "scheduled-thread-pool", ] @@ -2977,9 +3033,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3158,9 +3214,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "saffron" @@ -3183,21 +3239,21 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi", + "windows-sys", ] [[package]] name = "scheduled-thread-pool" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" dependencies = [ - "parking_lot", + "parking_lot 0.12.1", ] [[package]] @@ -3346,7 +3402,7 @@ version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "itoa 1.0.1", + "itoa 1.0.2", "ryu", "serde", ] @@ -3378,7 +3434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa 1.0.2", "ryu", "serde", ] @@ -3454,9 +3510,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" dependencies = [ "libc", "signal-hook-registry", @@ -3518,12 +3574,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca642ba17f8b2995138b1d7711829c92e98c0a25ea019de790f4f09279c4e296" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", - "windows-sys", + "winapi", ] [[package]] @@ -3607,30 +3663,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "subtle" version = "2.4.1" @@ -3648,13 +3680,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.92" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -3683,6 +3715,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -3702,6 +3743,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.31" @@ -3878,9 +3925,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.1" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ "bytes", "libc", @@ -3897,9 +3944,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", @@ -4056,6 +4103,12 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -4065,12 +4118,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-width" version = "0.1.9" diff --git a/kanidm_tools/Cargo.toml b/kanidm_tools/Cargo.toml index d8c2ee428..6733f4d5c 100644 --- a/kanidm_tools/Cargo.toml +++ b/kanidm_tools/Cargo.toml @@ -34,7 +34,7 @@ kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" } tracing = "^0.1.34" tracing-subscriber = { version = "^0.3.11", features = ["env-filter", "fmt"] } rpassword = "^6.0.1" -structopt = { version = "^0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive", "env"] } libc = "^0.2.126" serde = { version = "^1.0.137", features = ["derive"] } serde_json = "^1.0.80" @@ -53,4 +53,5 @@ tokio = { version = "^1.19.1", features = ["rt", "macros"] } url = { version = "^2.2.2", features = ["serde"] } [build-dependencies] -structopt = { version = "^0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive"] } +clap_complete = { version = "^3.1.4"} diff --git a/kanidm_tools/build.rs b/kanidm_tools/build.rs index 438c070e4..f18a21647 100644 --- a/kanidm_tools/build.rs +++ b/kanidm_tools/build.rs @@ -3,8 +3,8 @@ use std::env; use std::path::PathBuf; -use structopt::clap::Shell; -use structopt::StructOpt; +use clap::{CommandFactory, Parser}; +use clap_complete::{generate_to, Shell}; include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/badlist_preprocess.rs"); @@ -26,28 +26,48 @@ fn main() { std::fs::create_dir(&comp_dir).expect("Unable to create completions dir"); } - SshAuthorizedOpt::clap().gen_completions( - "kanidm_ssh_authorizedkeys_direct", + generate_to( Shell::Bash, - comp_dir.clone(), - ); - SshAuthorizedOpt::clap().gen_completions( + &mut SshAuthorizedOpt::command(), "kanidm_ssh_authorizedkeys_direct", - Shell::Zsh, comp_dir.clone(), - ); + ) + .ok(); + generate_to( + Shell::Zsh, + &mut SshAuthorizedOpt::command(), + "kanidm_ssh_authorizedkeys_direct", + comp_dir.clone(), + ) + .ok(); - BadlistProcOpt::clap().gen_completions( - "kanidm_badlist_preprocess", + generate_to( Shell::Bash, - comp_dir.clone(), - ); - BadlistProcOpt::clap().gen_completions( + &mut BadlistProcOpt::command(), "kanidm_badlist_preprocess", - Shell::Zsh, comp_dir.clone(), - ); + ) + .ok(); + generate_to( + Shell::Zsh, + &mut BadlistProcOpt::command(), + "kanidm_badlist_preprocess", + comp_dir.clone(), + ) + .ok(); - KanidmClientOpt::clap().gen_completions("kanidm", Shell::Bash, comp_dir.clone()); - KanidmClientOpt::clap().gen_completions("kanidm", Shell::Zsh, comp_dir); + generate_to( + Shell::Bash, + &mut KanidmClientParser::command(), + "kanidm", + comp_dir.clone(), + ) + .ok(); + generate_to( + Shell::Zsh, + &mut KanidmClientParser::command(), + "kanidm", + comp_dir, + ) + .ok(); } diff --git a/kanidm_tools/src/badlist_preprocess.rs b/kanidm_tools/src/badlist_preprocess.rs index 23804efa0..68e238853 100644 --- a/kanidm_tools/src/badlist_preprocess.rs +++ b/kanidm_tools/src/badlist_preprocess.rs @@ -16,14 +16,14 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use kanidm_proto::v1::Modify; +use clap::Parser; use rayon::prelude::*; -use structopt::StructOpt; use tracing::{debug, error, info}; include!("opt/badlist_preprocess.rs"); fn main() { - let opt = BadlistProcOpt::from_args(); + let opt = BadlistProcOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_tools/src/cli/account.rs b/kanidm_tools/src/cli/account.rs index 9854f5e27..2521fe10f 100644 --- a/kanidm_tools/src/cli/account.rs +++ b/kanidm_tools/src/cli/account.rs @@ -24,22 +24,22 @@ use url::Url; impl AccountOpt { pub fn debug(&self) -> bool { match self { - AccountOpt::Credential(acopt) => acopt.debug(), - AccountOpt::Radius(acopt) => match acopt { + AccountOpt::Credential { commands } => commands.debug(), + AccountOpt::Radius { commands } => match commands { AccountRadius::Show(aro) => aro.copt.debug, AccountRadius::Generate(aro) => aro.copt.debug, AccountRadius::Delete(aro) => aro.copt.debug, }, - AccountOpt::Posix(apopt) => match apopt { + AccountOpt::Posix { commands } => match commands { AccountPosix::Show(apo) => apo.copt.debug, AccountPosix::Set(apo) => apo.copt.debug, AccountPosix::SetPassword(apo) => apo.copt.debug, }, - AccountOpt::Person(apopt) => match apopt { + AccountOpt::Person { commands } => match commands { AccountPerson::Extend(apo) => apo.copt.debug, AccountPerson::Set(apo) => apo.copt.debug, }, - AccountOpt::Ssh(asopt) => match asopt { + AccountOpt::Ssh { commands } => match commands { AccountSsh::List(ano) => ano.copt.debug, AccountSsh::Add(ano) => ano.copt.debug, AccountSsh::Delete(ano) => ano.copt.debug, @@ -48,7 +48,7 @@ impl AccountOpt { AccountOpt::Get(aopt) => aopt.copt.debug, AccountOpt::Delete(aopt) => aopt.copt.debug, AccountOpt::Create(aopt) => aopt.copt.debug, - AccountOpt::Validity(avopt) => match avopt { + AccountOpt::Validity { commands } => match commands { AccountValidity::Show(ano) => ano.copt.debug, AccountValidity::ExpireAt(ano) => ano.copt.debug, AccountValidity::BeginFrom(ano) => ano.copt.debug, @@ -59,8 +59,8 @@ impl AccountOpt { pub async fn exec(&self) { match self { // id/cred/primary/set - AccountOpt::Credential(acopt) => acopt.exec().await, - AccountOpt::Radius(aropt) => match aropt { + AccountOpt::Credential { commands } => commands.exec().await, + AccountOpt::Radius { commands } => match commands { AccountRadius::Show(aopt) => { let client = aopt.copt.to_client().await; @@ -95,7 +95,7 @@ impl AccountOpt { } } }, // end AccountOpt::Radius - AccountOpt::Posix(apopt) => match apopt { + AccountOpt::Posix { commands } => match commands { AccountPosix::Show(aopt) => { let client = aopt.copt.to_client().await; match client @@ -142,7 +142,7 @@ impl AccountOpt { } } }, // end AccountOpt::Posix - AccountOpt::Person(apopt) => match apopt { + AccountOpt::Person { commands } => match commands { AccountPerson::Extend(aopt) => { let client = aopt.copt.to_client().await; if let Err(e) = client @@ -170,7 +170,7 @@ impl AccountOpt { } } }, // end AccountOpt::Person - AccountOpt::Ssh(asopt) => match asopt { + AccountOpt::Ssh { commands } => match commands { AccountSsh::List(aopt) => { let client = aopt.copt.to_client().await; @@ -246,7 +246,7 @@ impl AccountOpt { error!("Error -> {:?}", e) } } - AccountOpt::Validity(avopt) => match avopt { + AccountOpt::Validity { commands } => match commands { AccountValidity::Show(ano) => { let client = ano.copt.to_client().await; diff --git a/kanidm_tools/src/cli/group.rs b/kanidm_tools/src/cli/group.rs index 3ea72fba8..20f9ce464 100644 --- a/kanidm_tools/src/cli/group.rs +++ b/kanidm_tools/src/cli/group.rs @@ -12,7 +12,7 @@ impl GroupOpt { GroupOpt::RemoveMembers(gcopt) => gcopt.copt.debug, GroupOpt::SetMembers(gcopt) => gcopt.copt.debug, GroupOpt::PurgeMembers(gcopt) => gcopt.copt.debug, - GroupOpt::Posix(gpopt) => match gpopt { + GroupOpt::Posix { commands } => match commands { GroupPosix::Show(gcopt) => gcopt.copt.debug, GroupPosix::Set(gcopt) => gcopt.copt.debug, }, @@ -107,7 +107,7 @@ impl GroupOpt { Ok(_) => println!("Successfully set members for group {}", gcopt.name.as_str()), } } - GroupOpt::Posix(gpopt) => match gpopt { + GroupOpt::Posix { commands } => match commands { GroupPosix::Show(gcopt) => { let client = gcopt.copt.to_client().await; match client.idm_group_unix_token_get(gcopt.name.as_str()).await { diff --git a/kanidm_tools/src/cli/lib.rs b/kanidm_tools/src/cli/lib.rs index a01a91dd8..dd6f0dbdd 100644 --- a/kanidm_tools/src/cli/lib.rs +++ b/kanidm_tools/src/cli/lib.rs @@ -14,7 +14,6 @@ extern crate tracing; use std::path::PathBuf; -use structopt::StructOpt; include!("../opt/kanidm.rs"); @@ -79,15 +78,15 @@ impl SelfOpt { impl SystemOpt { pub fn debug(&self) -> bool { match self { - SystemOpt::Oauth2(oopt) => oopt.debug(), - SystemOpt::Domain(dopt) => dopt.debug(), + SystemOpt::Oauth2 { commands } => commands.debug(), + SystemOpt::Domain { commands } => commands.debug(), } } pub async fn exec(&self) { match self { - SystemOpt::Oauth2(oopt) => oopt.exec().await, - SystemOpt::Domain(dopt) => dopt.exec().await, + SystemOpt::Oauth2 { commands } => commands.exec().await, + SystemOpt::Domain { commands } => commands.exec().await, } } } @@ -95,29 +94,29 @@ impl SystemOpt { impl KanidmClientOpt { pub fn debug(&self) -> bool { match self { - KanidmClientOpt::Raw(ropt) => ropt.debug(), + KanidmClientOpt::Raw { commands } => commands.debug(), KanidmClientOpt::Login(lopt) => lopt.debug(), KanidmClientOpt::Logout(lopt) => lopt.debug(), - KanidmClientOpt::Session(sopt) => sopt.debug(), - KanidmClientOpt::CSelf(csopt) => csopt.debug(), - KanidmClientOpt::Account(aopt) => aopt.debug(), - KanidmClientOpt::Group(gopt) => gopt.debug(), - KanidmClientOpt::System(sopt) => sopt.debug(), - KanidmClientOpt::Recycle(ropt) => ropt.debug(), + KanidmClientOpt::Session { commands } => commands.debug(), + KanidmClientOpt::CSelf { commands } => commands.debug(), + KanidmClientOpt::Account { commands } => commands.debug(), + KanidmClientOpt::Group { commands } => commands.debug(), + KanidmClientOpt::System { commands } => commands.debug(), + KanidmClientOpt::Recycle { commands } => commands.debug(), } } pub async fn exec(&self) { match self { - KanidmClientOpt::Raw(ropt) => ropt.exec().await, + KanidmClientOpt::Raw { commands } => commands.exec().await, KanidmClientOpt::Login(lopt) => lopt.exec().await, KanidmClientOpt::Logout(lopt) => lopt.exec().await, - KanidmClientOpt::Session(sopt) => sopt.exec().await, - KanidmClientOpt::CSelf(csopt) => csopt.exec().await, - KanidmClientOpt::Account(aopt) => aopt.exec().await, - KanidmClientOpt::Group(gopt) => gopt.exec().await, - KanidmClientOpt::System(sopt) => sopt.exec().await, - KanidmClientOpt::Recycle(ropt) => ropt.exec().await, + KanidmClientOpt::Session { commands } => commands.exec().await, + KanidmClientOpt::CSelf { commands } => commands.exec().await, + KanidmClientOpt::Account { commands } => commands.exec().await, + KanidmClientOpt::Group { commands } => commands.exec().await, + KanidmClientOpt::System { commands } => commands.exec().await, + KanidmClientOpt::Recycle { commands } => commands.exec().await, } } } diff --git a/kanidm_tools/src/cli/main.rs b/kanidm_tools/src/cli/main.rs index 718bfecf9..db643ac54 100644 --- a/kanidm_tools/src/cli/main.rs +++ b/kanidm_tools/src/cli/main.rs @@ -10,19 +10,19 @@ #![deny(clippy::needless_pass_by_value)] #![deny(clippy::trivially_copy_pass_by_ref)] -use kanidm_cli::KanidmClientOpt; -use structopt::StructOpt; +use clap::Parser; +use kanidm_cli::KanidmClientParser; use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; #[tokio::main(flavor = "current_thread")] async fn main() { - let opt = KanidmClientOpt::from_args(); + let opt = KanidmClientParser::parse(); let fmt_layer = fmt::layer().with_writer(std::io::stderr); - let filter_layer = if opt.debug() { + let filter_layer = if opt.commands.debug() { match EnvFilter::try_new("kanidm=debug,kanidm_client=debug,webauthn=debug,kanidm_cli=debug") { Ok(f) => f, @@ -43,5 +43,5 @@ async fn main() { .with(fmt_layer) .init(); - opt.exec().await + opt.commands.exec().await } diff --git a/kanidm_tools/src/opt/badlist_preprocess.rs b/kanidm_tools/src/opt/badlist_preprocess.rs index ef50ccc3b..fa9e4c210 100644 --- a/kanidm_tools/src/opt/badlist_preprocess.rs +++ b/kanidm_tools/src/opt/badlist_preprocess.rs @@ -1,12 +1,11 @@ - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct BadlistProcOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, - #[structopt(short = "m", long = "modlist")] + #[clap(short, long)] modlist: bool, - #[structopt(short = "o", long = "output")] + #[clap(short, long = "output")] outfile: PathBuf, - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] password_list: Vec, } diff --git a/kanidm_tools/src/opt/kanidm.rs b/kanidm_tools/src/opt/kanidm.rs index 957cedd34..088ae92e8 100644 --- a/kanidm_tools/src/opt/kanidm.rs +++ b/kanidm_tools/src/opt/kanidm.rs @@ -1,502 +1,547 @@ -#[derive(Debug, StructOpt)] +use clap::{Args, Subcommand}; + +#[derive(Debug, Args)] pub struct Named { - #[structopt()] pub name: String, - #[structopt(flatten)] + #[clap(flatten)] pub copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct DebugOpt { - #[structopt(short = "d", long = "debug", env = "KANIDM_DEBUG")] + #[clap(short, long, env = "KANIDM_DEBUG")] pub debug: bool, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct CommonOpt { - #[structopt(short = "d", long = "debug", env = "KANIDM_DEBUG")] + #[clap(short, long, env = "KANIDM_DEBUG")] pub debug: bool, - #[structopt(short = "H", long = "url", env = "KANIDM_URL")] + #[clap(short = 'H', long = "url", env = "KANIDM_URL")] pub addr: Option, - #[structopt(short = "D", long = "name", env = "KANIDM_NAME")] + #[clap(short = 'D', long = "name", env = "KANIDM_NAME")] pub username: Option, - #[structopt(parse(from_os_str), short = "C", long = "ca", env = "KANIDM_CA_PATH")] + #[clap(parse(from_os_str), short = 'C', long = "ca", env = "KANIDM_CA_PATH")] pub ca_path: Option, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct GroupNamedMembers { - #[structopt()] name: String, - #[structopt()] members: Vec, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct GroupPosixOpt { - #[structopt()] name: String, - #[structopt(long = "gidnumber")] + #[clap(long)] gidnumber: Option, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum GroupPosix { - #[structopt(name = "show")] + #[clap(name = "show")] Show(Named), - #[structopt(name = "set")] + #[clap(name = "set")] Set(GroupPosixOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum GroupOpt { - #[structopt(name = "list")] + #[clap(name = "list")] List(CommonOpt), - #[structopt(name = "get")] + #[clap(name = "get")] Get(Named), - #[structopt(name = "create")] + #[clap(name = "create")] Create(Named), - #[structopt(name = "delete")] + #[clap(name = "delete")] Delete(Named), - #[structopt(name = "list_members")] + #[clap(name = "list_members")] ListMembers(Named), - #[structopt(name = "set_members")] + #[clap(name = "set_members")] SetMembers(GroupNamedMembers), - #[structopt(name = "purge_members")] + #[clap(name = "purge_members")] PurgeMembers(Named), - #[structopt(name = "add_members")] + #[clap(name = "add_members")] AddMembers(GroupNamedMembers), - #[structopt(name = "remove_members")] + #[clap(name = "remove_members")] RemoveMembers(GroupNamedMembers), - #[structopt(name = "posix")] - Posix(GroupPosix), + #[clap(name = "posix")] + Posix { + #[clap(subcommand)] + commands: GroupPosix, + }, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountCommonOpt { - #[structopt()] + #[clap()] account_id: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountNamedOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountNamedExpireDateTimeOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, - #[structopt(name = "datetime")] + #[clap(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)] +#[derive(Debug, Args)] pub struct AccountNamedValidDateTimeOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, - #[structopt(name = "datetime")] + #[clap(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)] +#[derive(Debug, Args)] pub struct AccountNamedTagOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, - #[structopt(name = "tag")] + #[clap(name = "tag")] tag: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountNamedTagPkOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, - #[structopt(name = "tag")] + #[clap(name = "tag")] tag: String, - #[structopt(name = "pubkey")] + #[clap(name = "pubkey")] pubkey: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AnonTokenOpt { - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, - #[structopt(name = "token")] + #[clap(name = "token")] token: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountCreateOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(name = "display_name")] + #[clap(name = "display_name")] display_name: String, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountCredential { /// Interactively update and change the content of the credentials of an account - #[structopt(name = "update")] + #[clap(name = "update")] Update(AccountNamedOpt), /// Given a reset token, interactively perform a credential reset - #[structopt(name = "reset")] + #[clap(name = "reset")] Reset(AnonTokenOpt), /// Create a reset link (token) that can be given to another person so they can /// recover or reset their account credentials. - #[structopt(name = "create_reset_link")] + #[clap(name = "create_reset_link")] CreateResetLink(AccountNamedOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountRadius { - #[structopt(name = "show_secret")] + #[clap(name = "show_secret")] Show(AccountNamedOpt), - #[structopt(name = "generate_secret")] + #[clap(name = "generate_secret")] Generate(AccountNamedOpt), - #[structopt(name = "delete_secret")] + #[clap(name = "delete_secret")] Delete(AccountNamedOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountPosixOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(long = "gidnumber")] + #[clap(long = "gidnumber")] gidnumber: Option, - #[structopt(long = "shell")] + #[clap(long = "shell")] shell: Option, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountPosix { - #[structopt(name = "show")] + #[clap(name = "show")] Show(AccountNamedOpt), - #[structopt(name = "set")] + #[clap(name = "set")] Set(AccountPosixOpt), - #[structopt(name = "set_password")] + #[clap(name = "set_password")] SetPassword(AccountNamedOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct AccountPersonOpt { - #[structopt(flatten)] + #[clap(flatten)] aopts: AccountCommonOpt, - #[structopt(long = "mail")] + #[clap(long = "mail")] mail: Option>, - #[structopt(long = "legalname")] + #[clap(long = "legalname")] legalname: Option, - #[structopt(flatten)] + #[clap(flatten)] copt: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountPerson { - #[structopt(name = "extend")] + #[clap(name = "extend")] Extend(AccountPersonOpt), - #[structopt(name = "set")] + #[clap(name = "set")] Set(AccountPersonOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountSsh { - #[structopt(name = "list_publickeys")] + #[clap(name = "list_publickeys")] List(AccountNamedOpt), - #[structopt(name = "add_publickey")] + #[clap(name = "add_publickey")] Add(AccountNamedTagPkOpt), - #[structopt(name = "delete_publickey")] + #[clap(name = "delete_publickey")] Delete(AccountNamedTagOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountValidity { - #[structopt(name = "show")] + #[clap(name = "show")] Show(AccountNamedOpt), - #[structopt(name = "expire_at")] + #[clap(name = "expire_at")] ExpireAt(AccountNamedExpireDateTimeOpt), - #[structopt(name = "begin_from")] + #[clap(name = "begin_from")] BeginFrom(AccountNamedValidDateTimeOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum AccountOpt { - #[structopt(name = "credential")] - Credential(AccountCredential), - #[structopt(name = "radius")] - Radius(AccountRadius), - #[structopt(name = "posix")] - Posix(AccountPosix), - #[structopt(name = "person")] - Person(AccountPerson), - #[structopt(name = "ssh")] - Ssh(AccountSsh), - #[structopt(name = "list")] + #[clap(name = "credential")] + Credential { + #[clap(subcommand)] + commands: AccountCredential, + }, + #[clap(name = "radius")] + Radius { + #[clap(subcommand)] + commands: AccountRadius, + }, + #[clap(name = "posix")] + Posix { + #[clap(subcommand)] + commands: AccountPosix, + }, + #[clap(name = "person")] + Person { + #[clap(subcommand)] + commands: AccountPerson, + }, + #[clap(name = "ssh")] + Ssh { + #[clap(subcommand)] + commands: AccountSsh, + }, + #[clap(name = "list")] List(CommonOpt), - #[structopt(name = "get")] + #[clap(name = "get")] Get(AccountNamedOpt), - #[structopt(name = "create")] + #[clap(name = "create")] Create(AccountCreateOpt), - #[structopt(name = "delete")] + #[clap(name = "delete")] Delete(AccountNamedOpt), - #[structopt(name = "validity")] - Validity(AccountValidity), + #[clap(name = "validity")] + Validity { + #[clap(subcommand)] + commands: AccountValidity, + }, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum RecycleOpt { - #[structopt(name = "list")] + #[clap(name = "list")] /// List objects that are in the recycle bin List(CommonOpt), - #[structopt(name = "get")] + #[clap(name = "get")] /// Display an object from the recycle bin Get(Named), - #[structopt(name = "revive")] + #[clap(name = "revive")] /// Revive a recycled object into a live (accessible) state - this is the opposite of "delete" Revive(Named), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct LoginOpt { - #[structopt(flatten)] - pub copt: CommonOpt, - #[structopt(short = "w", long = "webauthn")] - pub webauthn: bool, + #[clap(flatten)] + copt: CommonOpt, + #[clap(short, long)] + webauthn: bool, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct LogoutOpt { - #[structopt(short = "d", long = "debug", env = "KANIDM_DEBUG")] + #[clap(short, long, env = "KANIDM_DEBUG")] pub debug: bool, - #[structopt(short = "H", long = "url", env = "KANIDM_URL")] + #[clap(short = 'H', long = "url", env = "KANIDM_URL")] pub addr: Option, - #[structopt(parse(from_os_str), short = "C", long = "ca", env = "KANIDM_CA_PATH")] + #[clap(parse(from_os_str), short = 'C', long = "ca", env = "KANIDM_CA_PATH")] pub ca_path: Option, - #[structopt()] + #[clap()] pub username: Option, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum SessionOpt { - #[structopt(name = "list")] + #[clap(name = "list")] /// List current active sessions List(DebugOpt), - #[structopt(name = "cleanup")] + #[clap(name = "cleanup")] /// Remove sessions that have expired or are invalid. Cleanup(DebugOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct FilterOpt { - #[structopt()] + #[clap()] filter: String, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct CreateOpt { - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] file: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct ModifyOpt { - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, - #[structopt()] + #[clap()] filter: String, - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] file: PathBuf, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum RawOpt { - #[structopt(name = "search")] + #[clap(name = "search")] Search(FilterOpt), - #[structopt(name = "create")] + #[clap(name = "create")] Create(CreateOpt), - #[structopt(name = "modify")] + #[clap(name = "modify")] Modify(ModifyOpt), - #[structopt(name = "delete")] + #[clap(name = "delete")] Delete(FilterOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum SelfOpt { - #[structopt(name = "whoami")] /// Show the current authenticated user's identity Whoami(CommonOpt), - #[structopt(name = "set_password")] + #[clap(name = "set_password")] /// Set the current user's password SetPassword(CommonOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct Oauth2BasicCreateOpt { - #[structopt(flatten)] + #[clap(flatten)] nopt: Named, - #[structopt(name = "displayname")] + #[clap(name = "displayname")] displayname: String, - #[structopt(name = "origin")] + #[clap(name = "origin")] origin: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct Oauth2SetDisplayname { - #[structopt(flatten)] + #[clap(flatten)] nopt: Named, - #[structopt(name = "displayname")] + #[clap(name = "displayname")] displayname: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct Oauth2SetImplicitScopes { - #[structopt(flatten)] + #[clap(flatten)] nopt: Named, - #[structopt(name = "scopes")] + #[clap(name = "scopes")] scopes: Vec, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct Oauth2CreateScopeMapOpt { - #[structopt(flatten)] + #[clap(flatten)] nopt: Named, - #[structopt(name = "group")] + #[clap(name = "group")] group: String, - #[structopt(name = "scopes")] + #[clap(name = "scopes")] scopes: Vec, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] pub struct Oauth2DeleteScopeMapOpt { - #[structopt(flatten)] + #[clap(flatten)] nopt: Named, - #[structopt(name = "group")] + #[clap(name = "group")] group: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum Oauth2Opt { - #[structopt(name = "list")] + #[clap(name = "list")] /// List all configured oauth2 resource servers List(CommonOpt), - #[structopt(name = "get")] + #[clap(name = "get")] /// Display a selected oauth2 resource server Get(Named), - // #[structopt(name = "set")] + // #[clap(name = "set")] // /// Set options for a selected oauth2 resource server // Set(), - #[structopt(name = "create")] + #[clap(name = "create")] /// Create a new oauth2 resource server CreateBasic(Oauth2BasicCreateOpt), - #[structopt(name = "set_implicit_scopes")] + #[clap(name = "set_implicit_scopes")] /// Set the list of scopes that are granted to all valid accounts. SetImplictScopes(Oauth2SetImplicitScopes), - #[structopt(name = "create_scope_map")] + #[clap(name = "create_scope_map")] /// Add a new mapping from a group to what scopes it provides CreateScopeMap(Oauth2CreateScopeMapOpt), - #[structopt(name = "delete_scope_map")] + #[clap(name = "delete_scope_map")] /// Remove a mapping from groups to scopes DeleteScopeMap(Oauth2DeleteScopeMapOpt), - #[structopt(name = "reset_secrets")] + #[clap(name = "reset_secrets")] /// Reset the secrets associated to this resource server ResetSecrets(Named), - #[structopt(name = "delete")] + #[clap(name = "delete")] /// Delete a oauth2 resource server Delete(Named), /// Set a new displayname for a resource server - #[structopt(name = "set_displayname")] + #[clap(name = "set_displayname")] SetDisplayname(Oauth2SetDisplayname), - #[structopt(name = "enable_pkce")] + #[clap(name = "enable_pkce")] /// Enable PKCE on this oauth2 resource server. This defaults to being enabled. EnablePkce(Named), /// Disable PKCE on this oauth2 resource server to work around insecure clients that /// may not support it. You should request the client to enable PKCE! - #[structopt(name = "warning_insecure_client_disable_pkce")] + #[clap(name = "warning_insecure_client_disable_pkce")] DisablePkce(Named), - #[structopt(name = "warning_enable_legacy_crypto")] + #[clap(name = "warning_enable_legacy_crypto")] /// Enable legacy signing crypto on this oauth2 resource server. This defaults to being disabled. /// You only need to enable this for openid clients that do not support modern crytopgraphic /// operations. EnableLegacyCrypto(Named), /// Disable legacy signing crypto on this oauth2 resource server. This is the default. - #[structopt(name = "disable_legacy_crypto")] + #[clap(name = "disable_legacy_crypto")] DisableLegacyCrypto(Named), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum DomainOpt { - #[structopt(name = "show")] + #[clap(name = "show")] /// Show information about this systems domain Show(CommonOpt), - #[structopt(name = "reset_token_key")] + #[clap(name = "reset_token_key")] /// Reset this domain token signing key. This will cause all user sessions to be /// invalidated (logged out). ResetTokenKey(CommonOpt), } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub enum SystemOpt { - #[structopt(name = "oauth2")] + #[clap(name = "oauth2")] /// Configure and display oauth2/oidc resource server configuration - Oauth2(Oauth2Opt), - #[structopt(name = "domain")] + Oauth2 { + #[clap(subcommand)] + commands: Oauth2Opt, + }, + #[clap(name = "domain")] /// Configure and display domain configuration - Domain(DomainOpt), + Domain { + #[clap(subcommand)] + commands: DomainOpt, + }, } -#[derive(Debug, StructOpt)] -#[structopt(about = "Kanidm Client Utility")] +#[derive(Debug, Subcommand)] +#[clap(about = "Kanidm Client Utility")] pub enum KanidmClientOpt { - #[structopt(name = "login")] /// Login to an account to use with future cli operations Login(LoginOpt), - #[structopt(name = "logout")] /// Logout of an active cli session Logout(LogoutOpt), - #[structopt(name = "session")] /// Manage active cli sessions - Session(SessionOpt), - #[structopt(name = "self")] + Session { + #[clap(subcommand)] + commands: SessionOpt, + }, + #[clap(name = "self")] /// Actions for the current authenticated account - CSelf(SelfOpt), - #[structopt(name = "account")] + CSelf { + #[clap(subcommand)] + commands: SelfOpt, + }, /// Account operations - Account(AccountOpt), - #[structopt(name = "group")] + Account { + #[clap(subcommand)] + commands: AccountOpt, + }, /// Group operations - Group(GroupOpt), - #[structopt(name = "system")] + Group { + #[clap(subcommand)] + commands: GroupOpt, + }, /// System configuration operations - System(SystemOpt), - #[structopt(name = "recycle_bin")] + System { + #[clap(subcommand)] + commands: SystemOpt, + }, + #[clap(name = "recycle_bin")] /// Recycle Bin operations - Recycle(RecycleOpt), - #[structopt(name = "raw")] + Recycle { + #[clap(subcommand)] + commands: RecycleOpt, + }, /// Unsafe - low level, raw database operations. - Raw(RawOpt), + Raw { + #[clap(subcommand)] + commands: RawOpt, + }, +} + +#[derive(Debug, clap::Parser)] +#[clap(about = "Kanidm Client Utility")] +pub struct KanidmClientParser { + #[clap(subcommand)] + pub commands: KanidmClientOpt, } diff --git a/kanidm_tools/src/opt/ssh_authorizedkeys.rs b/kanidm_tools/src/opt/ssh_authorizedkeys.rs index 75972785e..fec375fcd 100644 --- a/kanidm_tools/src/opt/ssh_authorizedkeys.rs +++ b/kanidm_tools/src/opt/ssh_authorizedkeys.rs @@ -1,14 +1,12 @@ - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct SshAuthorizedOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long = "debug")] debug: bool, - #[structopt(short = "H", long = "url")] + #[clap(short = 'H', long = "url")] addr: Option, - #[structopt(short = "D", long = "name")] + #[clap(short = 'D', long = "name")] username: String, - #[structopt(parse(from_os_str), short = "C", long = "ca")] + #[clap(parse(from_os_str), short = 'C', long = "ca")] ca_path: Option, - #[structopt()] account_id: String, } diff --git a/kanidm_tools/src/ssh_authorizedkeys.rs b/kanidm_tools/src/ssh_authorizedkeys.rs index 8e6f9181c..64cde089c 100644 --- a/kanidm_tools/src/ssh_authorizedkeys.rs +++ b/kanidm_tools/src/ssh_authorizedkeys.rs @@ -10,9 +10,9 @@ use std::path::PathBuf; +use clap::Parser; use kanidm_client::{ClientError, KanidmClientBuilder}; -use structopt::StructOpt; use tracing::{debug, error}; include!("opt/ssh_authorizedkeys.rs"); @@ -23,7 +23,7 @@ include!("opt/ssh_authorizedkeys.rs"); // #[tokio::main(flavor = "current_thread")] async fn main() { - let opt = SshAuthorizedOpt::from_args(); + let opt = SshAuthorizedOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_unix_int/Cargo.toml b/kanidm_unix_int/Cargo.toml index c74990b6a..e30cb5dd3 100644 --- a/kanidm_unix_int/Cargo.toml +++ b/kanidm_unix_int/Cargo.toml @@ -61,7 +61,7 @@ bytes = "^1.1.0" libc = "^0.2.126" serde = { version = "^1.0.137", features = ["derive"] } serde_json = "^1.0.80" -structopt = { version = "0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive"] } libsqlite3-sys = "0.24.2" rusqlite = "^0.27.0" @@ -84,6 +84,7 @@ lru = "^0.7.6" score = { path = "../kanidmd/score" } [build-dependencies] -structopt = { version = "^0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive"] } +clap_complete = "^3.1.4" profiles = { path = "../profiles" } diff --git a/kanidm_unix_int/build.rs b/kanidm_unix_int/build.rs index 054a5a740..fef4ebf40 100644 --- a/kanidm_unix_int/build.rs +++ b/kanidm_unix_int/build.rs @@ -1,8 +1,8 @@ #![allow(dead_code)] use std::env; -use structopt::clap::Shell; -use structopt::StructOpt; +use clap::{IntoApp, Parser}; +use clap_complete::{generate_to, Shell}; use std::path::PathBuf; @@ -29,31 +29,63 @@ fn main() { std::fs::create_dir(&comp_dir).expect("Unable to create completions dir"); } - SshAuthorizedOpt::clap().gen_completions( - "kanidm_ssh_authorizedkeys", + generate_to( Shell::Bash, - comp_dir.clone(), - ); - SshAuthorizedOpt::clap().gen_completions( + &mut SshAuthorizedOpt::command(), "kanidm_ssh_authorizedkeys", - Shell::Zsh, comp_dir.clone(), - ); + ) + .ok(); + generate_to( + Shell::Zsh, + &mut SshAuthorizedOpt::command(), + "kanidm_ssh_authorizedkeys", + comp_dir.clone(), + ) + .ok(); - CacheInvalidateOpt::clap().gen_completions( + generate_to( + Shell::Zsh, + &mut CacheInvalidateOpt::command(), "kanidm_cache_invalidate", + comp_dir.clone(), + ) + .ok(); + generate_to( Shell::Bash, - comp_dir.clone(), - ); - CacheInvalidateOpt::clap().gen_completions( + &mut CacheInvalidateOpt::command(), "kanidm_cache_invalidate", - Shell::Zsh, comp_dir.clone(), - ); + ) + .ok(); - CacheClearOpt::clap().gen_completions("kanidm_cache_clear", Shell::Bash, comp_dir.clone()); - CacheClearOpt::clap().gen_completions("kanidm_cache_clear", Shell::Zsh, comp_dir.clone()); + 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(); - UnixdStatusOpt::clap().gen_completions("kanidm_unixd_status", Shell::Bash, comp_dir.clone()); - UnixdStatusOpt::clap().gen_completions("kanidm_unixd_status", Shell::Zsh, comp_dir); + 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.clone(), + ) + .ok(); } diff --git a/kanidm_unix_int/src/cache_clear.rs b/kanidm_unix_int/src/cache_clear.rs index cbb96909e..8486d34bf 100644 --- a/kanidm_unix_int/src/cache_clear.rs +++ b/kanidm_unix_int/src/cache_clear.rs @@ -13,7 +13,7 @@ #[macro_use] extern crate tracing; -use structopt::StructOpt; +use clap::Parser; use futures::executor::block_on; @@ -25,7 +25,7 @@ include!("./opt/cache_clear.rs"); #[tokio::main] async fn main() { - let opt = CacheClearOpt::from_args(); + let opt = CacheClearOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_unix_int/src/cache_invalidate.rs b/kanidm_unix_int/src/cache_invalidate.rs index b68a7b176..8bbaad7f8 100644 --- a/kanidm_unix_int/src/cache_invalidate.rs +++ b/kanidm_unix_int/src/cache_invalidate.rs @@ -13,7 +13,7 @@ #[macro_use] extern crate tracing; -use structopt::StructOpt; +use clap::Parser; use futures::executor::block_on; @@ -25,7 +25,7 @@ include!("./opt/cache_invalidate.rs"); #[tokio::main] async fn main() { - let opt = CacheInvalidateOpt::from_args(); + let opt = CacheInvalidateOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_unix_int/src/daemon_status.rs b/kanidm_unix_int/src/daemon_status.rs index ed8e82baa..74c55f756 100644 --- a/kanidm_unix_int/src/daemon_status.rs +++ b/kanidm_unix_int/src/daemon_status.rs @@ -13,8 +13,9 @@ #[macro_use] extern crate tracing; +use clap::Parser; + use std::path::PathBuf; -use structopt::StructOpt; // use futures::executor::block_on; @@ -25,7 +26,7 @@ use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse}; include!("./opt/unixd_status.rs"); fn main() { - let opt = UnixdStatusOpt::from_args(); + let opt = UnixdStatusOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_unix_int/src/opt/cache_clear.rs b/kanidm_unix_int/src/opt/cache_clear.rs index c0093b886..e407fee6e 100644 --- a/kanidm_unix_int/src/opt/cache_clear.rs +++ b/kanidm_unix_int/src/opt/cache_clear.rs @@ -1,9 +1,7 @@ -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct CacheClearOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, - #[structopt(long = "really")] + #[clap(long)] really: bool, } - - diff --git a/kanidm_unix_int/src/opt/cache_invalidate.rs b/kanidm_unix_int/src/opt/cache_invalidate.rs index 9ac254d1d..80b80bbfe 100644 --- a/kanidm_unix_int/src/opt/cache_invalidate.rs +++ b/kanidm_unix_int/src/opt/cache_invalidate.rs @@ -1,7 +1,5 @@ - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct CacheInvalidateOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, } - diff --git a/kanidm_unix_int/src/opt/ssh_authorizedkeys.rs b/kanidm_unix_int/src/opt/ssh_authorizedkeys.rs index 410d85079..0f7fe93d2 100644 --- a/kanidm_unix_int/src/opt/ssh_authorizedkeys.rs +++ b/kanidm_unix_int/src/opt/ssh_authorizedkeys.rs @@ -1,8 +1,7 @@ - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct SshAuthorizedOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, - #[structopt()] + #[clap()] account_id: String, } diff --git a/kanidm_unix_int/src/opt/unixd_status.rs b/kanidm_unix_int/src/opt/unixd_status.rs index cd341d1f8..05973bd7e 100644 --- a/kanidm_unix_int/src/opt/unixd_status.rs +++ b/kanidm_unix_int/src/opt/unixd_status.rs @@ -1,6 +1,5 @@ -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct UnixdStatusOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, } - diff --git a/kanidm_unix_int/src/ssh_authorizedkeys.rs b/kanidm_unix_int/src/ssh_authorizedkeys.rs index 64309bce1..fada9006a 100644 --- a/kanidm_unix_int/src/ssh_authorizedkeys.rs +++ b/kanidm_unix_int/src/ssh_authorizedkeys.rs @@ -13,8 +13,8 @@ #[macro_use] extern crate tracing; +use clap::Parser; use std::path::PathBuf; -use structopt::StructOpt; use futures::executor::block_on; @@ -26,7 +26,7 @@ include!("./opt/ssh_authorizedkeys.rs"); #[tokio::main] async fn main() { - let opt = SshAuthorizedOpt::from_args(); + let opt = SshAuthorizedOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidm_unix_int/src/test_auth.rs b/kanidm_unix_int/src/test_auth.rs index 11733e548..fcc7bb077 100644 --- a/kanidm_unix_int/src/test_auth.rs +++ b/kanidm_unix_int/src/test_auth.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate tracing; -use structopt::StructOpt; +use clap::Parser; use futures::executor::block_on; @@ -10,17 +10,17 @@ 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)] +#[derive(Debug, Parser)] struct ClientOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] debug: bool, - #[structopt(short = "D", long = "name")] + #[clap(short = 'D', long = "name")] account_id: String, } #[tokio::main] async fn main() { - let opt = ClientOpt::from_args(); + let opt = ClientOpt::parse(); if opt.debug { ::std::env::set_var("RUST_LOG", "kanidm=debug,kanidm_client=debug"); } diff --git a/kanidmd/daemon/Cargo.toml b/kanidmd/daemon/Cargo.toml index a9f2ed0d7..4ad197801 100644 --- a/kanidmd/daemon/Cargo.toml +++ b/kanidmd/daemon/Cargo.toml @@ -19,7 +19,7 @@ path = "src/main.rs" [dependencies] kanidm = { path = "../idm" } score = { path = "../score" } -structopt = { version = "^0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive"] } users = "^0.11.0" serde = { version = "^1.0.137", features = ["derive"] } tokio = { version = "^1.19.1", features = ["rt-multi-thread", "macros", "signal"] } @@ -30,5 +30,6 @@ tikv-jemallocator = "0.5" [build-dependencies] serde = { version = "1", features = ["derive"] } -structopt = { version = "0.3", default-features = false } +clap = { version = "^3.0", features = ["derive"] } +clap_complete = "^3.1.4" profiles = { path = "../../profiles" } diff --git a/kanidmd/daemon/build.rs b/kanidmd/daemon/build.rs index e5c75a8de..e04885924 100644 --- a/kanidmd/daemon/build.rs +++ b/kanidmd/daemon/build.rs @@ -1,10 +1,10 @@ #![allow(dead_code)] use std::env; - use std::path::PathBuf; -use structopt::clap::Shell; -use structopt::StructOpt; + +use clap::{Args, IntoApp, Parser, Subcommand}; +use clap_complete::{generate_to, Shell}; use serde::{Deserialize, Serialize}; @@ -31,6 +31,18 @@ fn main() { std::fs::create_dir(&comp_dir).expect("Unable to create completions dir"); } - KanidmdOpt::clap().gen_completions("kanidmd", Shell::Bash, comp_dir.clone()); - KanidmdOpt::clap().gen_completions("kanidmd", Shell::Zsh, comp_dir); + generate_to( + Shell::Bash, + &mut KanidmdParser::command(), + "kanidmd", + comp_dir.clone(), + ) + .ok(); + generate_to( + Shell::Zsh, + &mut KanidmdParser::command(), + "kanidmd", + comp_dir, + ) + .ok(); } diff --git a/kanidmd/daemon/src/main.rs b/kanidmd/daemon/src/main.rs index 2807b6f2c..f9cd77966 100644 --- a/kanidmd/daemon/src/main.rs +++ b/kanidmd/daemon/src/main.rs @@ -38,7 +38,7 @@ use score::{ vacuum_server_core, verify_server_core, }; -use structopt::StructOpt; +use clap::{Args, Parser, Subcommand}; include!("./opt.rs"); @@ -83,15 +83,25 @@ impl KanidmdOpt { | KanidmdOpt::Reindex(sopt) | KanidmdOpt::Vacuum(sopt) | KanidmdOpt::DomainChange(sopt) - | KanidmdOpt::DbScan(DbScanOpt::ListIndexes(sopt)) - | KanidmdOpt::DbScan(DbScanOpt::ListId2Entry(sopt)) - | KanidmdOpt::DbScan(DbScanOpt::ListIndexAnalysis(sopt)) => &sopt, + | KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndexes(sopt), + } + | KanidmdOpt::DbScan { + commands: DbScanOpt::ListId2Entry(sopt), + } + | KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndexAnalysis(sopt), + } => &sopt, KanidmdOpt::Backup(bopt) => &bopt.commonopts, KanidmdOpt::Restore(ropt) => &ropt.commonopts, KanidmdOpt::RecoverAccount(ropt) => &ropt.commonopts, - KanidmdOpt::DbScan(DbScanOpt::ListIndex(dopt)) => &dopt.commonopts, + KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndex(dopt), + } => &dopt.commonopts, // KanidmdOpt::DbScan(DbScanOpt::GetIndex(dopt)) => &dopt.commonopts, - KanidmdOpt::DbScan(DbScanOpt::GetId2Entry(dopt)) => &dopt.commonopts, + KanidmdOpt::DbScan { + commands: DbScanOpt::GetId2Entry(dopt), + } => &dopt.commonopts, } } } @@ -133,30 +143,30 @@ async fn main() { } // Read cli args, determine if we should backup/restore - let opt = KanidmdOpt::from_args(); + let opt = KanidmdParser::parse(); let mut config = Configuration::new(); // Check the permissions are sane. - let cfg_meta = read_file_metadata(&(opt.commonopt().config_path)); + let cfg_meta = read_file_metadata(&(opt.commands.commonopt().config_path)); if !file_permissions_readonly(&cfg_meta) { eprintln!("WARNING: permissions on {} may not be secure. Should be readonly to running uid. This could be a security risk ...", - opt.commonopt().config_path.to_str().unwrap_or("invalid file path")); + opt.commands.commonopt().config_path.to_str().unwrap_or("invalid file path")); } if cfg_meta.mode() & 0o007 != 0 { eprintln!("WARNING: {} has 'everyone' permission bits in the mode. This could be a security risk ...", - opt.commonopt().config_path.to_str().unwrap_or("invalid file path") + opt.commands.commonopt().config_path.to_str().unwrap_or("invalid file path") ); } if cfg_meta.uid() == cuid || cfg_meta.uid() == ceuid { eprintln!("WARNING: {} owned by the current uid, which may allow file permission changes. This could be a security risk ...", - opt.commonopt().config_path.to_str().unwrap_or("invalid file path") + opt.commands.commonopt().config_path.to_str().unwrap_or("invalid file path") ); } // Read our config - let sconfig = match ServerConfig::new(&(opt.commonopt().config_path)) { + let sconfig = match ServerConfig::new(&(opt.commands.commonopt().config_path)) { Ok(c) => c, Err(e) => { eprintln!("Config Parse failure {:?}", e); @@ -213,7 +223,7 @@ async fn main() { config.update_role(sconfig.role); // Apply any cli overrides, normally debug level. - if let Some(dll) = opt.commonopt().debug.as_ref() { + if let Some(dll) = opt.commands.commonopt().debug.as_ref() { config.update_log_level(Some(dll.clone() as u32)); } @@ -223,9 +233,9 @@ async fn main() { // .format_level(false) // .init(); - match &opt { + match &opt.commands { KanidmdOpt::Server(_sopt) | KanidmdOpt::ConfigTest(_sopt) => { - let config_test = matches!(&opt, KanidmdOpt::ConfigTest(_)); + let config_test = matches!(&opt.commands, KanidmdOpt::ConfigTest(_)); if config_test { eprintln!("Running in server configuration test mode ..."); } else { @@ -321,23 +331,33 @@ async fn main() { eprintln!("Running in domain name change mode ... this may take a long time ..."); domain_rename_core(&config); } - KanidmdOpt::DbScan(DbScanOpt::ListIndexes(_)) => { + KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndexes(_), + } => { eprintln!("👀 db scan - list indexes"); dbscan_list_indexes_core(&config); } - KanidmdOpt::DbScan(DbScanOpt::ListId2Entry(_)) => { + KanidmdOpt::DbScan { + commands: DbScanOpt::ListId2Entry(_), + } => { eprintln!("👀 db scan - list id2entry"); dbscan_list_id2entry_core(&config); } - KanidmdOpt::DbScan(DbScanOpt::ListIndexAnalysis(_)) => { + KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndexAnalysis(_), + } => { eprintln!("👀 db scan - list index analysis"); dbscan_list_index_analysis_core(&config); } - KanidmdOpt::DbScan(DbScanOpt::ListIndex(dopt)) => { + KanidmdOpt::DbScan { + commands: DbScanOpt::ListIndex(dopt), + } => { eprintln!("👀 db scan - list index content - {}", dopt.index_name); dbscan_list_index_core(&config, dopt.index_name.as_str()); } - KanidmdOpt::DbScan(DbScanOpt::GetId2Entry(dopt)) => { + KanidmdOpt::DbScan { + commands: DbScanOpt::GetId2Entry(dopt), + } => { eprintln!("👀 db scan - get id2 entry - {}", dopt.id); dbscan_get_id2entry_core(&config, dopt.id); } diff --git a/kanidmd/daemon/src/opt.rs b/kanidmd/daemon/src/opt.rs index 2ed2baca6..77023c17c 100644 --- a/kanidmd/daemon/src/opt.rs +++ b/kanidmd/daemon/src/opt.rs @@ -1,123 +1,131 @@ -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct CommonOpt { - #[structopt(short = "d", long = "debug", env = "KANIDM_DEBUG")] + #[clap(short, long, env = "KANIDM_DEBUG")] /// Logging level. quiet, default, filter, verbose, perffull debug: Option, - #[structopt(parse(from_os_str), short = "c", long = "config", env = "KANIDM_CONFIG")] + #[clap(parse(from_os_str), short, long = "config", env = "KANIDM_CONFIG")] /// Path to the server's configuration file. If it does not exist, it will be created. config_path: PathBuf, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct BackupOpt { - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] /// Output path for the backup content. path: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct RestoreOpt { - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] /// Restore from this path. Should be created with "backup". path: PathBuf, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct RecoverAccountOpt { - #[structopt(short)] + #[clap(short)] /// The account name to recover credentials for. name: String, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct DbScanListIndex { /// The name of the index to list index_name: String, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } /* -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct DbScanGetIndex { /// The name of the index to list index_name: String, /// The name of the index key to retrieve key: String, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } */ -#[derive(Debug, StructOpt)] +#[derive(Debug, Args)] struct DbScanGetId2Entry { /// The id of the entry to display id: u64, - #[structopt(flatten)] + #[clap(flatten)] commonopts: CommonOpt, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] enum DbScanOpt { - #[structopt(name = "list_all_indexes")] + #[clap(name = "list_all_indexes")] /// List all index tables that exist on the system. ListIndexes(CommonOpt), - #[structopt(name = "list_index")] + #[clap(name = "list_index")] /// List all content of a named index ListIndex(DbScanListIndex), // #[structopt(name = "get_index")] // /// Display the content of a single index key // GetIndex(DbScanGetIndex), - #[structopt(name = "list_id2entry")] + #[clap(name = "list_id2entry")] /// List all id2entry values with reduced entry content ListId2Entry(CommonOpt), - #[structopt(name = "get_id2entry")] + #[clap(name = "get_id2entry")] /// View the data of a specific entry from id2entry GetId2Entry(DbScanGetId2Entry), - #[structopt(name = "list_index_analysis")] + #[clap(name = "list_index_analysis")] /// List all content of index analysis ListIndexAnalysis(CommonOpt), } -#[derive(Debug, StructOpt)] -enum KanidmdOpt { - #[structopt(name = "server")] - /// Start the IDM Server - Server(CommonOpt), - #[structopt(name = "configtest")] - /// Test the IDM Server configuration, without starting network listeners. - ConfigTest(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 = "vacuum")] - /// Vacuum the database to reclaim space or change db_fs_type/page_size (offline) - Vacuum(CommonOpt), - #[structopt(name = "domain_name_change")] - /// Change the IDM domain name - DomainChange(CommonOpt), - #[structopt(name = "db_scan")] - /// Inspect the internal content of the database datastructures. - DbScan(DbScanOpt), +#[derive(Debug, Parser)] +struct KanidmdParser { + #[clap(subcommand)] + commands: KanidmdOpt, } +#[derive(Debug, Subcommand)] +enum KanidmdOpt { + #[clap(name = "server")] + /// Start the IDM Server + Server(CommonOpt), + #[clap(name = "configtest")] + /// Test the IDM Server configuration, without starting network listeners. + ConfigTest(CommonOpt), + #[clap(name = "backup")] + /// Backup the database content (offline) + Backup(BackupOpt), + #[clap(name = "restore")] + /// Restore the database content (offline) + Restore(RestoreOpt), + #[clap(name = "verify")] + /// Verify database and entity consistency. + Verify(CommonOpt), + #[clap(name = "recover_account")] + /// Recover an account's password + RecoverAccount(RecoverAccountOpt), + // #[clap(name = "reset_server_id")] + // ResetServerId(CommonOpt), + #[clap(name = "reindex")] + /// Reindex the database (offline) + Reindex(CommonOpt), + #[clap(name = "vacuum")] + /// Vacuum the database to reclaim space or change db_fs_type/page_size (offline) + Vacuum(CommonOpt), + #[clap(name = "domain_name_change")] + /// Change the IDM domain name + DomainChange(CommonOpt), + #[clap(name = "db_scan")] + /// Inspect the internal content of the database datastructures. + DbScan { + #[clap(subcommand)] + commands: DbScanOpt, + }, +} diff --git a/orca/Cargo.toml b/orca/Cargo.toml index 6b2b34536..c29b94038 100644 --- a/orca/Cargo.toml +++ b/orca/Cargo.toml @@ -19,7 +19,7 @@ path = "src/main.rs" tracing = "^0.1.34" tracing-subscriber = "^0.3.11" -structopt = { version = "^0.3.26", default-features = false } +clap = { version = "^3.0", features = ["derive"] } uuid = { version = "^1.1.1", features = ["serde", "v4" ] } csv = "1.1.6" diff --git a/orca/src/main.rs b/orca/src/main.rs index 6e8723b88..218b8d63d 100644 --- a/orca/src/main.rs +++ b/orca/src/main.rs @@ -17,10 +17,10 @@ extern crate tracing; use crate::ds::DirectoryServer; use crate::kani::{KaniHttpServer, KaniLdapServer}; +use clap::{Parser, Subcommand}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::time::{Duration, Instant}; -use structopt::StructOpt; use uuid::Uuid; mod data; @@ -177,7 +177,7 @@ impl TargetServer { #[tokio::main] async fn main() { - let opt = OrcaOpt::from_args(); + let opt = OrcaOpt::parse(); if opt.debug() { ::std::env::set_var( diff --git a/orca/src/opt.rs b/orca/src/opt.rs index 82266d468..eccf9d687 100644 --- a/orca/src/opt.rs +++ b/orca/src/opt.rs @@ -1,64 +1,62 @@ use std::str::FromStr; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct CommonOpt { - #[structopt(short = "d", long = "debug")] + #[clap(short, long)] /// Enable debug logging pub debug: bool, } - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct PreProcOpt { - #[structopt(flatten)] + #[clap(flatten)] pub copt: CommonOpt, - #[structopt(parse(from_os_str), short = "i", long = "input")] + #[clap(parse(from_os_str), short, long = "input")] /// Path to unprocessed data in json format. pub input_path: PathBuf, - #[structopt(parse(from_os_str), short = "o", long = "output")] + #[clap(parse(from_os_str), short, long = "output")] /// Path to write the processed output. pub output_path: PathBuf, } - -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct SetupOpt { - #[structopt(flatten)] + #[clap(flatten)] pub copt: CommonOpt, - #[structopt(name = "target")] + #[clap(name = "target")] /// Which service to target during this operation. /// Valid values are "ds" or "kanidm" pub target: TargetOpt, - #[structopt(parse(from_os_str), short = "p", long = "profile")] + #[clap(parse(from_os_str), short, long = "profile")] /// Path to the test profile. pub profile_path: PathBuf, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] struct RunOpt { - #[structopt(flatten)] + #[clap(flatten)] pub copt: CommonOpt, - #[structopt(name = "target")] + #[clap(name = "target")] /// Which service to target during this operation. /// Valid values are "ds" or "kanidm" pub target: TargetOpt, - #[structopt(name = "test_type")] + #[clap(name = "test_type")] /// Which type of test to run against this system pub test_type: TestTypeOpt, - #[structopt(parse(from_os_str), short = "p", long = "profile")] + #[clap(parse(from_os_str), short, long = "profile")] /// Path to the test profile. pub profile_path: PathBuf, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub(crate) enum TargetOpt { - #[structopt(name = "ds")] + #[clap(name = "ds")] /// Run against the ldap/ds profile Ds, - #[structopt(name = "kanidm")] + #[clap(name = "kanidm")] /// Run against the kanidm http profile Kanidm, - #[structopt(name = "kanidm_ldap")] + #[clap(name = "kanidm_ldap")] /// Run against the kanidm ldap profile KanidmLdap, } @@ -76,9 +74,9 @@ impl FromStr for TargetOpt { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Subcommand)] pub(crate) enum TestTypeOpt { - #[structopt(name = "search-basic")] + #[clap(name = "search-basic")] /// Perform a basic search-only test SearchBasic, } @@ -102,8 +100,10 @@ impl std::fmt::Display for TestTypeOpt { } } -#[derive(Debug, StructOpt)] -#[structopt(name="orca", about = "Orca Load Testing Utility +#[derive(Debug, Parser)] +#[clap( + name = "orca", + about = "Orca Load Testing Utility Orca works in a few steps. @@ -119,17 +119,16 @@ Orca works in a few steps. orca run -p example_profiles/small/orca.toml kanidm search-basic -")] +" +)] enum OrcaOpt { - #[structopt(name = "preprocess")] + #[clap(name = "preprocess")] /// Preprocess a dataset that can be used for testing PreProc(PreProcOpt), - #[structopt(name = "setup")] + #[clap(name = "setup")] /// Setup a server as defined by a test profile Setup(SetupOpt), - #[structopt(name = "run")] + #[clap(name = "run")] /// Run the load test as defined by the test profile Run(RunOpt), } - -