From d42437abba4518ddb7abaf2a580f7d541af83f95 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Tue, 2 May 2023 19:41:26 +0200 Subject: [PATCH 1/5] 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!() + } +} From 5ad18a7179631115b273d7eaadfca68ed6d4521d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 2 May 2023 17:44:07 +0000 Subject: [PATCH 2/5] [pre-commit.ci lite] apply automatic fixes --- cli/README.md | 2 +- cli/src/enums.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cli/README.md b/cli/README.md index b8207742a..2bb7ae55e 100644 --- a/cli/README.md +++ b/cli/README.md @@ -7,7 +7,7 @@ At the moment the CLI only serves one purpose: creating a new challenge. In the ## Usage ```shell -./challenge-cli +./challenge-cli ``` will print: diff --git a/cli/src/enums.rs b/cli/src/enums.rs index d1e983902..ee0100524 100644 --- a/cli/src/enums.rs +++ b/cli/src/enums.rs @@ -47,4 +47,3 @@ impl fmt::Display for Technology { write!(f, "{:?}", self) } } - From 26bd277ab5ce9e062aca503ec598ab913fac585c Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Fri, 5 May 2023 15:34:15 +0200 Subject: [PATCH 3/5] feat: add cli for scaffolding a new challenge create the class file and asciidoc file Refs: #555 --- .gitignore | 1 + cli/Cargo.toml | 3 + cli/README.md | 12 +++- cli/src/challenge.rs | 80 +++++++++++++++++++++++ cli/src/enums.rs | 15 ++++- cli/src/main.rs | 106 ++++++++++++++++++++----------- src/main/resources/challenge.hbs | 75 ++++++++++++++++++++++ 7 files changed, 251 insertions(+), 41 deletions(-) create mode 100644 cli/src/challenge.rs create mode 100644 src/main/resources/challenge.hbs diff --git a/.gitignore b/.gitignore index 3404c21f4..b10508117 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ js/node/ js/node_modules/ node_modules .npm +/cli/Cargo.lock diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 54d2a1877..1d2859b8d 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -5,3 +5,6 @@ edition = "2021" [dependencies] clap = { version = "4.2.5", features = ["derive"] } +walkdir = "2" +regex = "1.8.1" +handlebars = "3" diff --git a/cli/README.md b/cli/README.md index 2bb7ae55e..f15c93ba3 100644 --- a/cli/README.md +++ b/cli/README.md @@ -35,8 +35,16 @@ cargo build target/debug/challenge-cli ``` +## Running in IntelliJ + +On `main.rs` right click and select `Run 'main'`. This will run the CLI in the terminal window of IntelliJ. +When passing command line arguments you need to add them to the run configuration. In IntelliJ go to `Run` -> `Edit Configurations...` and add the arguments to the `Command` field. You need to add `--` before the arguments. For example: + +```shell +run --package challenge-cli --bin challenge-cli -- challenge -d easy -t git ../ +``` + ## Todo -- Add option to pass in the project directory -- Create the directory structure for a new challenge +- Fix templating (not everything is present yet) - Add GitHub actions to build binary for the different platforms diff --git a/cli/src/challenge.rs b/cli/src/challenge.rs new file mode 100644 index 000000000..21332921b --- /dev/null +++ b/cli/src/challenge.rs @@ -0,0 +1,80 @@ +use std::collections::BTreeMap; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +use handlebars::Handlebars; +use walkdir::WalkDir; + +use crate::{Difficulty, Platform, Technology}; + +pub struct Challenge { + pub number: u8, + pub technology: Technology, + pub difficulty: Difficulty, + pub project_directory: PathBuf, + pub platform: Platform, +} + +impl std::fmt::Display for Challenge { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Technology: {}, Difficulty: {}", self.technology, self.difficulty) + } +} + +pub fn create_challenge(challenge: &Challenge) { + let challenge_number = &challenge.number.to_string(); + let challenge_name = String::from("Challenge") + challenge_number + ".java"; + let challenge_exists = check_challenge_exists(challenge); + + if challenge_exists { + panic!("{:?} already exists", challenge_name); + } + + println!("Creating challenge {} in {}", challenge_number, challenge.project_directory.display()); + create_challenge_class_file(challenge, challenge_number, challenge_name); + create_documentation_files(challenge, challenge_number); +} + +fn create_documentation_files(challenge: &Challenge, challenge_number: &String) { + let challenge_documentation_path = challenge.project_directory.join("src/main/resources/explanations/"); + create_documentation_file(challenge_documentation_path.join(format!("challenge{}.adoc", challenge_number))); + create_documentation_file(challenge_documentation_path.join(format!("challenge{}_hint.adoc", challenge_number))); + create_documentation_file(challenge_documentation_path.join(format!("challenge{}_explanation.adoc", challenge_number))); +} + +fn create_documentation_file(filename: PathBuf) { + File::create(filename).expect("Unable to create challenge documentation file"); +} + +fn create_challenge_class_file(challenge: &Challenge, challenge_number: &String, challenge_name: String) { + const CHALLENGE_TEMPLATE: &str = "src/main/resources/challenge.hbs"; + let challenge_source_path = challenge.project_directory.join("src/main/java/org/owasp/wrongsecrets/challenges"); + + let mut handlebars = Handlebars::new(); + handlebars.register_template_file("challenge", challenge.project_directory.join(CHALLENGE_TEMPLATE)).unwrap(); + let mut data = BTreeMap::new(); + data.insert("challenge_number".to_string(), challenge_number); + let challenge_source_content = handlebars.render("challenge", &data).expect("Unable to render challenge template"); + let mut class_file = File::create(challenge_source_path.join(challenge.platform.to_string()).join(challenge_name)).expect("Unable to create challenge source file"); + class_file.write(challenge_source_content.as_bytes()).expect("Unable to write challenge source file"); +} + +//File API has `create_new` but it is still experimental in the nightly build, let loop and check if it exists for now +fn check_challenge_exists(challenge: &Challenge) -> bool { + let challenges_directory = challenge.project_directory.join("src/main/java/org/owasp/wrongsecrets/challenges"); + let challenge_name = String::from("Challenge") + &challenge.number.to_string() + ".java"; + + let challenge_exists = WalkDir::new(challenges_directory) + .into_iter() + .filter_map(|e| e.ok()) + .any(|e| { + match e.file_name().to_str() { + None => { false } + Some(name) => { + name.eq(challenge_name.as_str()) + } + } + }); + challenge_exists +} diff --git a/cli/src/enums.rs b/cli/src/enums.rs index ee0100524..6c202bbb4 100644 --- a/cli/src/enums.rs +++ b/cli/src/enums.rs @@ -27,7 +27,7 @@ pub enum Technology { Documentation, } -#[derive(clap::ValueEnum, Clone, Debug)] +#[derive(clap::ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] pub enum Difficulty { Easy, Normal, @@ -36,6 +36,13 @@ pub enum Difficulty { Master, } +#[derive(clap::ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] +pub enum Platform { + Cloud, + Docker, + Kubernetes +} + impl fmt::Display for Difficulty { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self) @@ -47,3 +54,9 @@ impl fmt::Display for Technology { write!(f, "{:?}", self) } } + +impl fmt::Display for Platform { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 9bbaab79a..d8b96901d 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,48 +1,78 @@ -use clap::{arg, Command}; +use std::path::PathBuf; -use crate::enums::{Difficulty, Technology}; +use clap::arg; +use clap::{Parser, Subcommand}; + +use crate::challenge::Challenge; +use crate::enums::{Difficulty, Platform, Technology}; mod enums; +mod challenge; -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") - ) - ) +#[derive(Debug, Parser)] +#[command(name = "cli")] +#[command(about = "A CLI for WrongSecrets", long_about = None)] +struct Cli { + #[command(subcommand)] + command: Commands, } -fn main() { - let matches = cli().get_matches(); +#[derive(Debug, Subcommand)] +enum Commands { + #[command(arg_required_else_help = true, name = "challenge", about = "Create a new challenge")] + ChallengeCommand { + //We could infer this from the directory structure but another PR could already have added the challenge with this number + #[arg( + long, + short, + value_name = "NUMBER")] + number: u8, + #[arg( + long, + short, + value_name = "DIFFICULTY", + num_args = 0..=1, + default_value_t = Difficulty::Easy, + default_missing_value = "easy", + value_enum + )] + difficulty: Difficulty, + #[arg( + long, + short, + value_name = "TECHNOLOGY", + num_args = 0..=1, + default_value_t = Technology::Git, + default_missing_value = "git", + value_enum + )] + technology: Technology, + #[arg( + long, + short, + value_name = "PLATFORM", + num_args = 0..=1, + value_enum + )] + platform: Platform, + #[arg(required = true)] + project_directory: PathBuf, + } +} - match matches.subcommand() { - Some(("challenge", sub_matches)) => { - println!( - "Create new challenge with difficulty: {}", - sub_matches.get_one::("difficulty").expect("") - ); +fn main() { + let args = Cli::parse(); + match args.command { + Commands::ChallengeCommand { + number, + difficulty, + technology, + platform, + project_directory + } => { + project_directory.try_exists().expect("Unable to find project directory"); + let challenge = Challenge { number, difficulty, technology, platform, project_directory }; + challenge::create_challenge(&challenge); } - _ => unreachable!() } } diff --git a/src/main/resources/challenge.hbs b/src/main/resources/challenge.hbs new file mode 100644 index 000000000..76b459c3a --- /dev/null +++ b/src/main/resources/challenge.hbs @@ -0,0 +1,75 @@ +package org.owasp.wrongsecrets.challenges.{{platform}}; + +import org.owasp.wrongsecrets.RuntimeEnvironment; +import org.owasp.wrongsecrets.ScoreCard; +import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.Difficulty; +import org.owasp.wrongsecrets.challenges.Spoiler; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +{{ +extra_imports +}} + +@Component +@Order(0) +public class Challenge{{challenge_number}} extends Challenge { + + public Challenge{{challenge_number}}(ScoreCard scoreCard) { + super(scoreCard); + } + + /** + * {@inheritDoc} + */ + @Override + public Spoiler spoiler() { + return new Spoiler(getData()); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean answerCorrect(String answer) { + return getData().equals(answer); + } + + @Override + /** + * {@inheritDoc} + */ + public List supportedRuntimeEnvironments() { + return List.of(DOCKER); + } + + /** + * {@inheritDoc} + */ + @Override + public int difficulty() { + return Difficulty.{{difficulty}}; + } + + @Override + public String getTech() { + return ChallengeTechnology.Tech{{technology}}.id; + } + + @Override + public boolean isLimitedWhenOnlineHosted() { + return false; + } + + @Override + public boolean canRunInCTFMode() { + return true; + } + + private String getData() { + return "<>"; + } +} From 28840b09921e78e188d41f90907a539b00fed31c Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Wed, 17 May 2023 08:40:23 +0200 Subject: [PATCH 4/5] feat: add handlebars template to generate Java code. Refs: #555 --- cli/Cargo.toml | 2 +- cli/src/challenge.rs | 110 ++++++++++++++++++++----------- cli/src/enums.rs | 2 +- cli/src/main.rs | 32 +++++---- src/main/resources/challenge.hbs | 5 +- 5 files changed, 95 insertions(+), 56 deletions(-) diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 1d2859b8d..3e49a1b7c 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [dependencies] clap = { version = "4.2.5", features = ["derive"] } walkdir = "2" -regex = "1.8.1" handlebars = "3" + diff --git a/cli/src/challenge.rs b/cli/src/challenge.rs index 21332921b..b9656230f 100644 --- a/cli/src/challenge.rs +++ b/cli/src/challenge.rs @@ -8,73 +8,103 @@ use walkdir::WalkDir; use crate::{Difficulty, Platform, Technology}; +#[derive(Debug)] pub struct Challenge { pub number: u8, pub technology: Technology, pub difficulty: Difficulty, - pub project_directory: PathBuf, pub platform: Platform, } -impl std::fmt::Display for Challenge { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "Technology: {}, Difficulty: {}", self.technology, self.difficulty) +impl Challenge { + fn create_java_sources(&self, project_directory: &PathBuf) { + let challenge_source_path = + project_directory + .join("src/main/java/org/owasp/wrongsecrets/challenges"); + + let (handlebars, data) = self.init_handlebars(project_directory); + let challenge_source_content = handlebars + .render("challenge", &data) + .expect("Unable to render challenge template"); + let mut class_file = File::create( + challenge_source_path + .join(self.platform.to_string()) + .join(format!("Challenge{}.java", &self.number.to_string())) + ) + .expect("Unable to create challenge source file"); + class_file + .write(challenge_source_content.as_bytes()) + .expect("Unable to write challenge source file"); } -} -pub fn create_challenge(challenge: &Challenge) { - let challenge_number = &challenge.number.to_string(); - let challenge_name = String::from("Challenge") + challenge_number + ".java"; - let challenge_exists = check_challenge_exists(challenge); + fn init_handlebars(&self, project_directory: &PathBuf) -> (Handlebars, BTreeMap) { + const CHALLENGE_TEMPLATE: &str = "src/main/resources/challenge.hbs"; + let mut handlebars = Handlebars::new(); + handlebars + .register_template_file( + "challenge", + project_directory.join(CHALLENGE_TEMPLATE), + ) + .unwrap(); + let mut data: BTreeMap = BTreeMap::new(); + data.insert("challenge_number".to_string(), self.number.to_string()); + data.insert("platform".to_string(), self.platform.to_string().to_lowercase()); + data.insert("difficulty".to_string(), self.difficulty.to_string().to_uppercase()); + data.insert("technology".to_string(), self.technology.to_string().to_uppercase()); - if challenge_exists { - panic!("{:?} already exists", challenge_name); + (handlebars, data) } - println!("Creating challenge {} in {}", challenge_number, challenge.project_directory.display()); - create_challenge_class_file(challenge, challenge_number, challenge_name); - create_documentation_files(challenge, challenge_number); -} - -fn create_documentation_files(challenge: &Challenge, challenge_number: &String) { - let challenge_documentation_path = challenge.project_directory.join("src/main/resources/explanations/"); - create_documentation_file(challenge_documentation_path.join(format!("challenge{}.adoc", challenge_number))); - create_documentation_file(challenge_documentation_path.join(format!("challenge{}_hint.adoc", challenge_number))); - create_documentation_file(challenge_documentation_path.join(format!("challenge{}_explanation.adoc", challenge_number))); + fn create_documentation(&self, project_directory: &PathBuf) { + let challenge_documentation_path = + project_directory + .join("src/main/resources/explanations/"); + create_documentation_file( + challenge_documentation_path.join(format!("challenge{}.adoc", self.number.to_string())), + ); + create_documentation_file( + challenge_documentation_path.join(format!("challenge{}_hint.adoc", self.number.to_string())), + ); + create_documentation_file( + challenge_documentation_path + .join(format!("challenge{}_explanation.adoc", self.number.to_string())), + ); + } } fn create_documentation_file(filename: PathBuf) { File::create(filename).expect("Unable to create challenge documentation file"); } -fn create_challenge_class_file(challenge: &Challenge, challenge_number: &String, challenge_name: String) { - const CHALLENGE_TEMPLATE: &str = "src/main/resources/challenge.hbs"; - let challenge_source_path = challenge.project_directory.join("src/main/java/org/owasp/wrongsecrets/challenges"); +pub fn create_challenge(challenge: &Challenge, project_directory: &PathBuf) { + let challenge_exists = check_challenge_exists(challenge, &project_directory); - let mut handlebars = Handlebars::new(); - handlebars.register_template_file("challenge", challenge.project_directory.join(CHALLENGE_TEMPLATE)).unwrap(); - let mut data = BTreeMap::new(); - data.insert("challenge_number".to_string(), challenge_number); - let challenge_source_content = handlebars.render("challenge", &data).expect("Unable to render challenge template"); - let mut class_file = File::create(challenge_source_path.join(challenge.platform.to_string()).join(challenge_name)).expect("Unable to create challenge source file"); - class_file.write(challenge_source_content.as_bytes()).expect("Unable to write challenge source file"); + if challenge_exists { + panic!("{:?} already exists", &challenge); + } + + println!( + "Creating {:?}", + &challenge + ); + challenge.create_java_sources(project_directory); + challenge.create_documentation(project_directory); } + //File API has `create_new` but it is still experimental in the nightly build, let loop and check if it exists for now -fn check_challenge_exists(challenge: &Challenge) -> bool { - let challenges_directory = challenge.project_directory.join("src/main/java/org/owasp/wrongsecrets/challenges"); +fn check_challenge_exists(challenge: &Challenge, project_directory: &PathBuf) -> bool { + let challenges_directory = + project_directory + .join("src/main/java/org/owasp/wrongsecrets/challenges"); let challenge_name = String::from("Challenge") + &challenge.number.to_string() + ".java"; let challenge_exists = WalkDir::new(challenges_directory) .into_iter() .filter_map(|e| e.ok()) - .any(|e| { - match e.file_name().to_str() { - None => { false } - Some(name) => { - name.eq(challenge_name.as_str()) - } - } + .any(|e| match e.file_name().to_str() { + None => false, + Some(name) => name.eq(challenge_name.as_str()), }); challenge_exists } diff --git a/cli/src/enums.rs b/cli/src/enums.rs index 6c202bbb4..7256cca09 100644 --- a/cli/src/enums.rs +++ b/cli/src/enums.rs @@ -40,7 +40,7 @@ pub enum Difficulty { pub enum Platform { Cloud, Docker, - Kubernetes + Kubernetes, } impl fmt::Display for Difficulty { diff --git a/cli/src/main.rs b/cli/src/main.rs index d8b96901d..99058bfa5 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,13 +1,13 @@ use std::path::PathBuf; -use clap::arg; use clap::{Parser, Subcommand}; +use clap::arg; use crate::challenge::Challenge; use crate::enums::{Difficulty, Platform, Technology}; -mod enums; mod challenge; +mod enums; #[derive(Debug, Parser)] #[command(name = "cli")] @@ -19,13 +19,14 @@ struct Cli { #[derive(Debug, Subcommand)] enum Commands { - #[command(arg_required_else_help = true, name = "challenge", about = "Create a new challenge")] + #[command( + arg_required_else_help = true, + name = "challenge", + about = "Create a new challenge" + )] ChallengeCommand { //We could infer this from the directory structure but another PR could already have added the challenge with this number - #[arg( - long, - short, - value_name = "NUMBER")] + #[arg(long, short, value_name = "NUMBER")] number: u8, #[arg( long, @@ -57,7 +58,7 @@ enum Commands { platform: Platform, #[arg(required = true)] project_directory: PathBuf, - } + }, } fn main() { @@ -68,11 +69,18 @@ fn main() { difficulty, technology, platform, - project_directory + project_directory, } => { - project_directory.try_exists().expect("Unable to find project directory"); - let challenge = Challenge { number, difficulty, technology, platform, project_directory }; - challenge::create_challenge(&challenge); + project_directory + .try_exists() + .expect("Unable to find project directory"); + let challenge = Challenge { + number, + difficulty, + technology, + platform, + }; + challenge::create_challenge(&challenge, &project_directory); } } } diff --git a/src/main/resources/challenge.hbs b/src/main/resources/challenge.hbs index 76b459c3a..28772ef6a 100644 --- a/src/main/resources/challenge.hbs +++ b/src/main/resources/challenge.hbs @@ -3,6 +3,7 @@ package org.owasp.wrongsecrets.challenges.{{platform}}; import org.owasp.wrongsecrets.RuntimeEnvironment; import org.owasp.wrongsecrets.ScoreCard; import org.owasp.wrongsecrets.challenges.Challenge; +import org.owasp.wrongsecrets.challenges.ChallengeTechnology; import org.owasp.wrongsecrets.challenges.Difficulty; import org.owasp.wrongsecrets.challenges.Spoiler; import org.springframework.core.annotation.Order; @@ -43,7 +44,7 @@ public class Challenge{{challenge_number}} extends Challenge { * {@inheritDoc} */ public List supportedRuntimeEnvironments() { - return List.of(DOCKER); + return List.of(RuntimeEnvironment.Environment.{{environment}}); } /** @@ -56,7 +57,7 @@ public class Challenge{{challenge_number}} extends Challenge { @Override public String getTech() { - return ChallengeTechnology.Tech{{technology}}.id; + return ChallengeTechnology.Tech.{{technology}}.id; } @Override From 96180beb0594a783099629a92f192373586a874e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 06:42:12 +0000 Subject: [PATCH 5/5] [pre-commit.ci lite] apply automatic fixes --- cli/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 3e49a1b7c..4e3ab5a30 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" clap = { version = "4.2.5", features = ["derive"] } walkdir = "2" handlebars = "3" -