diff --git a/tools/orca/setup_orca.sh b/tools/orca/setup_orca.sh new file mode 100755 index 000000000..c5393eb12 --- /dev/null +++ b/tools/orca/setup_orca.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +set -e + +if [ ! -f "$0" ]; then + echo "This script must be run from the tools/orca directory." + exit 1 +fi + +MYDIR="$(pwd)" + +echo "Running this will run the setup_dev_environment script" +echo "which resets the local dev environment to a default state." +echo "" +echo "Also, you'll need to start the server in another tab." +echo "" +echo "Hit ctrl-c to quit now if that's not what you intend!" + +# read -rp "Press Enter to continue" + +cd ../../server/daemon/ || exit 1 + +KANI_TEMP="$(mktemp -d)" +echo "Running the script..." +../../scripts/setup_dev_environment.sh | tee "${KANI_TEMP}/kanifile" + +echo "#########################" +echo "Back to orca now..." +echo "#########################" + +if [ -z "${KANIDM_CONFIG}" ]; then + KANIDM_CONFIG="../../examples/insecure_server.toml" +fi + +ADMIN_PW=$(grep -E "^admin password" "${KANI_TEMP}/kanifile" | awk '{print $NF}') +IDM_ADMIN_PW=$(grep -E "^idm_admin password" "${KANI_TEMP}/kanifile" | awk '{print $NF}') +rm "${KANI_TEMP}/kanifile" + +if [ -n "${DEBUG}" ]; then + echo "Admin pw: ${ADMIN_PW}" + echo "IDM Admin pw: ${IDM_ADMIN_PW}" +fi + +cd "$MYDIR" || exit 1 + +LDAP_DN="DN=$(grep domain "${KANIDM_CONFIG}" | awk '{print $NF}' | tr -d '"' | sed -E 's/\./,DN=/g')" + +cargo run --bin orca -- configure \ + --profile /tmp/kanidm/orca.toml \ + --admin-password "${ADMIN_PW}" \ + --kanidm-uri "$(grep origin "${KANIDM_CONFIG}" | awk '{print $NF}' | tr -d '"')" \ + --ldap-uri "ldaps://$(grep domain "${KANIDM_CONFIG}" | awk '{print $NF}' | tr -d '"'):636" \ + --ldap-base-dn "${LDAP_DN}" diff --git a/tools/orca/src/main.rs b/tools/orca/src/main.rs index 1be06ce7b..ef23083e5 100644 --- a/tools/orca/src/main.rs +++ b/tools/orca/src/main.rs @@ -25,6 +25,7 @@ use uuid::Uuid; use crate::ds::DirectoryServer; use crate::ipa::IpaServer; use crate::kani::{KaniHttpServer, KaniLdapServer}; +use crate::profile::Profile; use crate::setup::config; mod data; @@ -49,6 +50,7 @@ impl OrcaOpt { OrcaOpt::Setup(opt) => opt.copt.debug, OrcaOpt::Run(opt) => opt.copt.debug, OrcaOpt::Version(opt) => opt.debug, + OrcaOpt::Configure(opt) => opt.copt.debug, } } } @@ -250,6 +252,76 @@ async fn main() { // load the related data (if any) or generate it // run the test! } + OrcaOpt::Configure(opt) => update_config_file(opt), }; debug!("Exit"); } + +fn update_config_file(opt: ConfigOpt) { + let mut profile = match opt.profile.exists() { + true => { + let file_contents = std::fs::read_to_string(&opt.profile).unwrap(); + toml::from_str(&file_contents).unwrap() + } + + false => Profile::default(), + }; + println!("Current profile:\n{}", toml::to_string(&profile).unwrap()); + + if let Some(name) = opt.name { + println!("Updating config name."); + profile.name = name; + }; + + if let Some(new_password) = opt.admin_password { + println!("Updating admin password."); + profile.kani_http_config.as_mut().unwrap().admin_pw = new_password.clone(); + profile.kani_ldap_config.as_mut().unwrap().admin_pw = new_password; + }; + + if let Some(kani_uri) = opt.kanidm_uri { + println!("Updating kanidm uri."); + profile.kani_http_config.as_mut().unwrap().uri = kani_uri.clone(); + profile.kani_ldap_config.as_mut().unwrap().uri = kani_uri; + }; + + if let Some(ldap_uri) = opt.ldap_uri { + println!("Updating ldap uri."); + profile.kani_ldap_config.as_mut().unwrap().ldap_uri = ldap_uri; + }; + + if let Some(base_dn) = opt.ldap_base_dn { + println!("Updating base DN."); + profile.kani_ldap_config.as_mut().unwrap().base_dn = base_dn; + }; + + if let Some(data_file) = opt.data_file { + println!("Updating data_file path."); + profile.data = data_file; + }; + + if let Some(results) = opt.results { + println!("Updating results path."); + profile.results = results.to_str().unwrap().to_string(); + }; + + let file_contents = match toml::to_string(&profile) { + Err(err) => { + error!("Failed to serialize the config file: {:?}", err); + return; + } + Ok(val) => val, + }; + + match std::fs::write(&opt.profile, &file_contents) { + Err(err) => { + eprintln!("Failed to write the config file: {:?}", err); + return; + } + Ok(_) => { + println!("Wrote out the new config file"); + } + }; + + println!("New config:\n{}", file_contents); +} diff --git a/tools/orca/src/opt.rs b/tools/orca/src/opt.rs index 173a278b7..f65cf0eec 100644 --- a/tools/orca/src/opt.rs +++ b/tools/orca/src/opt.rs @@ -53,6 +53,41 @@ struct RunOpt { pub profile_path: PathBuf, } +#[derive(Debug, Parser)] +/// Configuration options +struct ConfigOpt { + #[clap(flatten)] + pub copt: CommonOpt, + #[clap(value_parser, short, long)] + /// Update the admin password + pub admin_password: Option, + #[clap(value_parser, short, long)] + /// Update the Kanidm URI + pub kanidm_uri: Option, + #[clap(value_parser, short, long)] + /// Update the LDAP URI + pub ldap_uri: Option, + #[clap(value_parser, short = 'D', long)] + /// Update the LDAP base DN + pub ldap_base_dn: Option, + + #[clap(value_parser, short = 'D', long)] + /// Set the configuration name + pub name: Option, + + #[clap(value_parser, short, long)] + /// The data file path to update (or create) + pub data_file: Option, + + #[clap(value_parser, short, long)] + /// The place we'll drop the results + pub results: Option, + + #[clap(value_parser, short, long)] + /// The configuration file path to update (or create) + pub profile: PathBuf, +} + #[derive(Debug, Subcommand, Clone)] /// The target to run against pub(crate) enum TargetOpt { @@ -150,5 +185,8 @@ enum OrcaOpt { Run(RunOpt), #[clap(name = "version")] /// Print version info and exit - Version(CommonOpt) + Version(CommonOpt), + #[clap(name = "configure")] + /// Update a config file + Configure(ConfigOpt), } diff --git a/tools/orca/src/profile.rs b/tools/orca/src/profile.rs index abf26f0fd..521d5f7c2 100644 --- a/tools/orca/src/profile.rs +++ b/tools/orca/src/profile.rs @@ -1,26 +1,26 @@ -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct DsConfig { pub uri: String, pub dm_pw: String, pub base_dn: String, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct IpaConfig { pub uri: String, pub realm: String, pub admin_pw: String, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct KaniHttpConfig { pub uri: String, pub admin_pw: String, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct KaniLdapConfig { pub uri: String, pub ldap_uri: String, @@ -28,7 +28,7 @@ pub struct KaniLdapConfig { pub base_dn: String, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct SearchBasicConfig { // Could consider fn for this #[serde(default = "Priority::lowest")] pub warmup_seconds: u32, @@ -44,7 +44,7 @@ impl Default for SearchBasicConfig { } } -#[derive(Debug, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct Profile { pub name: String, pub data: String, @@ -56,3 +56,30 @@ pub struct Profile { #[serde(default)] pub search_basic_config: SearchBasicConfig, } + +impl Default for Profile { + fn default() -> Self { + let kani_http_config = KaniHttpConfig { + uri: "https://localhost:8443".to_string(), + admin_pw: "".to_string(), + }; + + let kani_ldap_config = KaniLdapConfig { + uri: "https://localhost:8443".to_string(), + ldap_uri: "ldaps://localhost:636".to_string(), + admin_pw: "".to_string(), + base_dn: "dn=localhost".to_string(), + }; + + Self { + name: "orca default profile".to_string(), + data: "/tmp/kanidm/orcatest".to_string(), + results: "/tmp/kanidm/orca-results/".to_string(), + ds_config: None, + ipa_config: None, + kani_http_config: Some(kani_http_config), + kani_ldap_config: Some(kani_ldap_config), + search_basic_config: SearchBasicConfig::default(), + } + } +} diff --git a/tools/orca/src/setup.rs b/tools/orca/src/setup.rs index 7585818eb..a0de48fd4 100644 --- a/tools/orca/src/setup.rs +++ b/tools/orca/src/setup.rs @@ -84,7 +84,7 @@ pub(crate) fn config( debug!("Target server info -> {}", server.info()); // load the related data (if any) or generate it if that is what we have. - let data_file = File::open(data_path).map_err(|e| { + let data_file = File::open(&data_path).map_err(|e| { error!("Unable to open data file [{:?}] 🥺", e); })?; @@ -92,7 +92,8 @@ pub(crate) fn config( let data: TestData = serde_json::from_reader(data_reader).map_err(|e| { error!( - "Unable to process data file. You may need to preprocess it again: {:?}", + "Unable to process data file {}. You may need to preprocess it again: {:?}", + data_path.display(), e ); })?;