Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 215 additions & 21 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ void = "1"
futures = "0.3.30"
figment = { version = "0.10.19", features = ["env", "yaml", "test"] }
zip = { version = "2.2.2", default-features = false, features = ["deflate"] }
regex = "1.11.1"
inquire = "0.7.5"

# tracing
tracing = { version = "0.1.41", features = ["attributes"] }
Expand Down
46 changes: 46 additions & 0 deletions src/asset_files/rcds.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
flag_regex: {{ options.flag_regex }}

registry:
domain: {{ options.registry_domain }}
build:
user: {{ options.registry_build_user }}
pass: {{ options.registry_build_pass }}
cluster:
user: {{ options.registry_cluster_user }}
pass: {{ options.registry_cluster_pass }}

defaults:
difficulty: {{ options.defaults_difficulty }}
resources: { cpu: {{ options.defaults_resources_cpu }}, memory: {{ options.defaults_resources_memory }} }

points: {% for pts in options.points %}
- difficulty: {{ pts.difficulty }}
min: {{ pts.min }}
max: {{ pts.max }}
{% endfor %}
# TODO: templatize the deploy section
deploy:
# control challenge deployment status explicitly per environment/profile
testing:
misc/garf: true
pwn/notsh: true
web/bar: true

profiles: {% for prof in options.profiles %}
{{ prof.profile_name}}:
frontend_url: {{ prof.frontend_url }}
frontend_token: {{ prof.frontend_token }}
challenges_domain: {{ prof.challenges_domain }}
# TODO: kubeconfig
kubecontext: {{ prof.kubecontext }}
s3:
bucket_name: {{ prof.s3_bucket_name }}
endpoint: {{ prof.s3_endpoint }}
region: {{ prof.s3_region }}
access_key: {{ prof.s3_accesskey }}
secret_key: {{ prof.s3_secretaccesskey }}
dns:
# Place external-dns configuration options here;
# this yaml will be passed directly to external-dns without modification
# Reference: https://github.com/bitnami/charts/tree/main/bitnami/external-dns
{% endfor %}
10 changes: 10 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,14 @@ pub enum Commands {
#[arg(short, long, value_name = "PROFILE")]
profile: String,
},

/// Create an initial rcds.yaml to the current working directory.
Init {
/// Cannot be used with -b. If enabled, will prompt for each field of the config file. If disabled, behavior depends on --blank.
#[arg(short = 'i', long)]
interactive: bool,
/// Cannot be used with -i. If enabled, will create the file without any fields set. If disabled, will create an example config file (fields set with fake data).
#[arg(short = 'b', long, conflicts_with = "interactive")]
blank: bool,
},
}
29 changes: 29 additions & 0 deletions src/commands/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use anyhow::{Context, Result};
use std::fs::File;
use std::io::Write;
use std::process::exit;
use tracing::error;

use crate::init;
use crate::{access_handlers::frontend, commands::deploy};

pub fn run(interactive: &bool, blank: &bool) -> Result<()> {
let options = if *interactive {
init::interactive_init()?
} else if *blank {
init::blank_init()
} else {
init::example_init()
};

let configuration = init::templatize_init(options).context("could not render template")?;

let mut f = File::create("rcds.yaml")?;
f.write_all(configuration.as_bytes())?;

// Note about external-dns
println!("Note: external-dns configuration settings will need to be provided in rcds.yaml after file creation, under the `profiles.name.dns` key.");
println!("Reference: https://github.com/bitnami/charts/tree/main/bitnami/external-dns");

Ok(())
}
1 change: 1 addition & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod build;
pub mod check_access;
pub mod cluster_setup;
pub mod deploy;
pub mod init;
pub mod validate;

// These modules should not do much and act mostly as a thunk to handle
Expand Down
24 changes: 24 additions & 0 deletions src/init/example_values.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Example strings for rcds.yaml

pub static FLAG_REGEX: &str = "ctf{.*}";
pub static REGISTRY_DOMAIN: &str = "ghcr.io/youraccount";
pub static REGISTRY_BUILD_USER: &str = "admin";
pub static REGISTRY_BUILD_PASS: &str = "notrealcreds";
pub static REGISTRY_CLUSTER_USER: &str = "cluster_user";
pub static REGISTRY_CLUSTER_PASS: &str = "alsofake";
pub static DEFAULTS_DIFFICULTY: &str = "1";
pub static DEFAULTS_RESOURCES_CPU: &str = "1";
pub static DEFAULTS_RESOURCES_MEMORY: &str = "500M";
pub static POINTS_DIFFICULTY: &str = "easy";
pub static POINTS_MIN: &str = "200";
pub static POINTS_MAX: &str = "500";
pub static PROFILES_PROFILE_NAME: &str = "default";
pub static PROFILES_FRONTEND_URL: &str = "https://ctf.coolguy.invalid";
pub static PROFILES_FRONTEND_TOKEN: &str = "secretsecretsecret";
pub static PROFILES_CHALLENGES_DOMAIN: &str = "chals.coolguy.invalid";
pub static PROFILES_KUBECONTEXT: &str = "ctf-cluster";
pub static PROFILES_S3_BUCKET_NAME: &str = "ctf-bucket";
pub static PROFILES_S3_ENDPOINT: &str = "s3.coolguy.invalid";
pub static PROFILES_S3_REGION: &str = "us-west-2";
pub static PROFILES_S3_ACCESSKEY: &str = "accesskey";
pub static PROFILES_S3_SECRETACCESSKEY: &str = "secretkey";
Loading