From d42437abba4518ddb7abaf2a580f7d541af83f95 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 2 May 2023 19:41:26 +0200 Subject: [PATCH] feat: add cli for scaffolding a new challenge Refs: #555 --- cli/Cargo.toml | 7 +++++++ cli/README.md | 42 ++++++++++++++++++++++++++++++++++++++++ cli/src/enums.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ cli/src/main.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 cli/Cargo.toml create mode 100644 cli/README.md create mode 100644 cli/src/enums.rs create mode 100644 cli/src/main.rs diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 000000000..54d2a1877 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "challenge-cli" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.2.5", features = ["derive"] } diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 000000000..b8207742a --- /dev/null +++ b/cli/README.md @@ -0,0 +1,42 @@ +# CLI for WrongSecrets + +## Introduction + +At the moment the CLI only serves one purpose: creating a new challenge. In the future more options can be added. + +## Usage + +```shell +./challenge-cli +``` + +will print: + +```shell +A CLI for WrongSecrets + +Usage: challenge-cli + +Commands: + challenge Create a new challenge + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +``` + +## Building + +First install [Rust](https://www.rust-lang.org/tools/install). Then open a terminal and type: + +```shell +cd cli +cargo build +target/debug/challenge-cli +``` + +## Todo + +- Add option to pass in the project directory +- Create the directory structure for a new challenge +- Add GitHub actions to build binary for the different platforms diff --git a/cli/src/enums.rs b/cli/src/enums.rs new file mode 100644 index 000000000..d1e983902 --- /dev/null +++ b/cli/src/enums.rs @@ -0,0 +1,50 @@ +// Later on we can read this from the Github repository to make it more flexible +// cache the values locally and add a flag `--force` to force reading the values again +// Other option is to include a text file attached in a zip file. This makes it a bit more +// error prone as we need to have that file in the same directory. +// Other option is to have these files as part of the source code of wrongsecrets as you need +// to pass the project folder anyway. Otherwise generating a new challenge makes no sense ;-) + +use std::fmt; + +#[derive(clap::ValueEnum, Clone, Debug)] +pub enum Technology { + Git, + Docker, + ConfigMaps, + Secrets, + Vault, + Logging, + Terraform, + CSI, + CICD, + PasswordManager, + Cryptography, + Binary, + Frontend, + IAM, + Web3, + Documentation, +} + +#[derive(clap::ValueEnum, Clone, Debug)] +pub enum Difficulty { + Easy, + Normal, + Hard, + Expert, + Master, +} + +impl fmt::Display for Difficulty { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl fmt::Display for Technology { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 000000000..9bbaab79a --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,48 @@ +use clap::{arg, Command}; + +use crate::enums::{Difficulty, Technology}; + +mod enums; + +fn cli() -> Command { + Command::new("cli") + .about("A CLI for WrongSecrets") + .subcommand_required(true) + .arg_required_else_help(true) + .allow_external_subcommands(true) + .subcommand( + Command::new("challenge") + .about("Create a new challenge") + .arg_required_else_help(true) + .arg( + arg!(--"difficulty" ) + .short('d') + .num_args(0..=1) + .value_parser(clap::builder::EnumValueParser::::new()) + .num_args(0..=1) + .default_value("easy") + ) + .arg( + arg!(--"technology" ) + .short('t') + .value_parser(clap::builder::EnumValueParser::::new()) + .num_args(0..=1) + .require_equals(true) + .default_value("git") + ) + ) +} + +fn main() { + let matches = cli().get_matches(); + + match matches.subcommand() { + Some(("challenge", sub_matches)) => { + println!( + "Create new challenge with difficulty: {}", + sub_matches.get_one::("difficulty").expect("") + ); + } + _ => unreachable!() + } +}