diff --git a/Cargo.lock b/Cargo.lock index 1c7e1d69..4c39919f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -686,6 +686,7 @@ dependencies = [ "regex", "russh", "russh-keys", + "schemars 0.8.22", "serde", "tokio", ] @@ -875,6 +876,22 @@ dependencies = [ "shlex", ] +[[package]] +name = "cert_manager" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "cidr", + "env_logger", + "harmony", + "harmony_cli", + "harmony_macros", + "harmony_types", + "log", + "tokio", + "url", +] + [[package]] name = "cfg-if" version = "1.0.3" @@ -1205,6 +1222,22 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "crossterm" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi 0.3.9", +] + [[package]] name = "crossterm" version = "0.28.1" @@ -1767,6 +1800,7 @@ dependencies = [ "harmony_tui", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", @@ -1781,7 +1815,7 @@ dependencies = [ "harmony", "harmony_macros", "http 1.3.1", - "inquire", + "inquire 0.7.5", "k8s-openapi", "kube", "log", @@ -1857,6 +1891,7 @@ dependencies = [ "harmony_tui", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", @@ -1920,6 +1955,7 @@ dependencies = [ "harmony_secret_derive", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", @@ -1965,6 +2001,7 @@ dependencies = [ "harmony_secret", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", @@ -2033,6 +2070,7 @@ dependencies = [ "harmony_secret_derive", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", @@ -2548,7 +2586,7 @@ dependencies = [ "helm-wrapper-rs", "hex", "http 1.3.1", - "inquire", + "inquire 0.7.5", "k3d-rs", "k8s-openapi", "kube", @@ -2599,7 +2637,7 @@ dependencies = [ "harmony_tui", "indicatif", "indicatif-log-bridge", - "inquire", + "inquire 0.7.5", "lazy_static", "log", "tokio", @@ -2680,10 +2718,12 @@ dependencies = [ "harmony_secret_derive", "http 1.3.1", "infisical", - "inquire", + "inquire 0.7.5", + "interactive-parse", "lazy_static", "log", "pretty_assertions", + "schemars 0.8.22", "serde", "serde_json", "tempfile", @@ -3348,6 +3388,22 @@ dependencies = [ "generic-array", ] +[[package]] +name = "inquire" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33e7c1ddeb15c9abcbfef6029d8e29f69b52b6d6c891031b88ed91b5065803b" +dependencies = [ + "bitflags 1.3.2", + "crossterm 0.25.0", + "dyn-clone", + "lazy_static", + "newline-converter 0.2.2", + "thiserror 1.0.69", + "unicode-segmentation", + "unicode-width 0.1.14", +] + [[package]] name = "inquire" version = "0.7.5" @@ -3359,7 +3415,7 @@ dependencies = [ "dyn-clone", "fuzzy-matcher", "fxhash", - "newline-converter", + "newline-converter 0.3.0", "once_cell", "unicode-segmentation", "unicode-width 0.1.14", @@ -3378,6 +3434,22 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "interactive-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c6684d66c9fd6b51cafbf2a9105583d5046dd4c6363f31745686f503a285e8" +dependencies = [ + "crossterm 0.26.1", + "inquire 0.6.2", + "lazy_static", + "log", + "schemars 0.8.22", + "serde", + "serde_json", + "thiserror 1.0.69", +] + [[package]] name = "io-uring" version = "0.7.10" @@ -3482,25 +3554,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "json-prompt" -version = "0.1.0" -dependencies = [ - "brocade", - "cidr", - "env_logger", - "harmony", - "harmony_cli", - "harmony_macros", - "harmony_secret", - "harmony_secret_derive", - "harmony_types", - "log", - "serde", - "tokio", - "url", -] - [[package]] name = "jsonpath-rust" version = "0.7.5" @@ -3956,6 +4009,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "newline-converter" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f71d09d5c87634207f894c6b31b6a2b2c64ea3bdcf71bd5599fdbbe1600c00f" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "newline-converter" version = "0.3.0" @@ -6113,6 +6175,7 @@ dependencies = [ "harmony_secret_derive", "harmony_types", "log", + "schemars 0.8.22", "serde", "tokio", "url", diff --git a/brocade/Cargo.toml b/brocade/Cargo.toml index 89c4fb85..5fe0bd1e 100644 --- a/brocade/Cargo.toml +++ b/brocade/Cargo.toml @@ -16,3 +16,4 @@ env_logger.workspace = true regex = "1.11.3" harmony_secret = { path = "../harmony_secret" } serde.workspace = true +schemars = "0.8" diff --git a/brocade/examples/main.rs b/brocade/examples/main.rs index 47d4a631..05d74b6a 100644 --- a/brocade/examples/main.rs +++ b/brocade/examples/main.rs @@ -3,9 +3,10 @@ use std::net::{IpAddr, Ipv4Addr}; use brocade::{BrocadeOptions, ssh}; use harmony_secret::{Secret, SecretManager}; use harmony_types::switch::PortLocation; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Secret, Clone, Debug, Serialize, Deserialize)] +#[derive(Secret, Clone, Debug, JsonSchema, Serialize, Deserialize)] struct BrocadeSwitchAuth { username: String, password: String, diff --git a/examples/ha_cluster/Cargo.toml b/examples/ha_cluster/Cargo.toml index ed9e65a9..7d7523b8 100644 --- a/examples/ha_cluster/Cargo.toml +++ b/examples/ha_cluster/Cargo.toml @@ -19,3 +19,4 @@ url = { workspace = true } harmony_secret = { path = "../../harmony_secret" } brocade = { path = "../../brocade" } serde = { workspace = true } +schemars = "0.8" diff --git a/examples/ha_cluster/src/main.rs b/examples/ha_cluster/src/main.rs index 8da0278e..5340676d 100644 --- a/examples/ha_cluster/src/main.rs +++ b/examples/ha_cluster/src/main.rs @@ -21,6 +21,7 @@ use harmony::{ use harmony_macros::{ip, mac_address}; use harmony_secret::{Secret, SecretManager}; use harmony_types::net::Url; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[tokio::main] @@ -136,7 +137,7 @@ async fn main() { .unwrap(); } -#[derive(Secret, Serialize, Deserialize, Debug)] +#[derive(Secret, Serialize, JsonSchema, Deserialize, Debug)] pub struct BrocadeSwitchAuth { pub username: String, pub password: String, diff --git a/examples/nanodc/Cargo.toml b/examples/nanodc/Cargo.toml index 3072ddff..c2f19684 100644 --- a/examples/nanodc/Cargo.toml +++ b/examples/nanodc/Cargo.toml @@ -19,3 +19,4 @@ env_logger = { workspace = true } url = { workspace = true } serde = { workspace = true } brocade = { path = "../../brocade" } +schemars = "0.8" diff --git a/examples/nanodc/src/main.rs b/examples/nanodc/src/main.rs index bffd6595..ed8a9431 100644 --- a/examples/nanodc/src/main.rs +++ b/examples/nanodc/src/main.rs @@ -25,6 +25,7 @@ use harmony::{ use harmony_macros::{ip, mac_address}; use harmony_secret::{Secret, SecretManager}; use harmony_types::net::Url; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[tokio::main] @@ -192,7 +193,7 @@ async fn main() { .unwrap(); } -#[derive(Secret, Serialize, Deserialize, Debug)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug)] pub struct BrocadeSwitchAuth { pub username: String, pub password: String, diff --git a/examples/okd_installation/Cargo.toml b/examples/okd_installation/Cargo.toml index dfbe944b..83a3ef5a 100644 --- a/examples/okd_installation/Cargo.toml +++ b/examples/okd_installation/Cargo.toml @@ -20,3 +20,4 @@ env_logger = { workspace = true } url = { workspace = true } serde.workspace = true brocade = { path = "../../brocade" } +schemars = "0.8" diff --git a/examples/okd_installation/src/topology.rs b/examples/okd_installation/src/topology.rs index ce43f6b7..37478683 100644 --- a/examples/okd_installation/src/topology.rs +++ b/examples/okd_installation/src/topology.rs @@ -8,13 +8,14 @@ use harmony::{ }; use harmony_macros::{ip, ipv4}; use harmony_secret::{Secret, SecretManager}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::{ net::IpAddr, sync::{Arc, OnceLock}, }; -#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] struct OPNSenseFirewallConfig { username: String, password: String, @@ -103,7 +104,7 @@ pub fn get_inventory() -> Inventory { } } -#[derive(Secret, Serialize, Deserialize, Debug)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug)] pub struct BrocadeSwitchAuth { pub username: String, pub password: String, diff --git a/examples/okd_pxe/Cargo.toml b/examples/okd_pxe/Cargo.toml index 133b2f97..446133c1 100644 --- a/examples/okd_pxe/Cargo.toml +++ b/examples/okd_pxe/Cargo.toml @@ -20,3 +20,4 @@ env_logger = { workspace = true } url = { workspace = true } serde.workspace = true brocade = { path = "../../brocade" } +schemars = "0.8" diff --git a/examples/okd_pxe/src/topology.rs b/examples/okd_pxe/src/topology.rs index 73e5ba3f..0cc4e2a1 100644 --- a/examples/okd_pxe/src/topology.rs +++ b/examples/okd_pxe/src/topology.rs @@ -9,6 +9,7 @@ use harmony::{ }; use harmony_macros::{ip, ipv4}; use harmony_secret::{Secret, SecretManager}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::{ net::IpAddr, @@ -98,7 +99,7 @@ pub fn get_inventory() -> Inventory { } } -#[derive(Secret, Serialize, Deserialize, Debug)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug)] pub struct BrocadeSwitchAuth { pub username: String, pub password: String, diff --git a/examples/opnsense/Cargo.toml b/examples/opnsense/Cargo.toml index 197d6fd1..4b6ae189 100644 --- a/examples/opnsense/Cargo.toml +++ b/examples/opnsense/Cargo.toml @@ -19,3 +19,4 @@ url = { workspace = true } harmony_secret = { path = "../../harmony_secret" } brocade = { path = "../../brocade" } serde = { workspace = true } +schemars = "0.8" diff --git a/examples/opnsense/src/main.rs b/examples/opnsense/src/main.rs index cb17d0a9..fb9cee9e 100644 --- a/examples/opnsense/src/main.rs +++ b/examples/opnsense/src/main.rs @@ -7,6 +7,7 @@ use harmony::{ }; use harmony_macros::{ip, ipv4}; use harmony_secret::{Secret, SecretManager}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[tokio::main] @@ -70,7 +71,7 @@ async fn main() { .unwrap(); } -#[derive(Secret, Serialize, Deserialize, Debug)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug)] pub struct BrocadeSwitchAuth { pub username: String, pub password: String, diff --git a/examples/sttest/Cargo.toml b/examples/sttest/Cargo.toml index b8f90f8c..618039af 100644 --- a/examples/sttest/Cargo.toml +++ b/examples/sttest/Cargo.toml @@ -20,3 +20,4 @@ env_logger = { workspace = true } url = { workspace = true } serde = { workspace = true } brocade = { path = "../../brocade" } +schemars = "0.8" diff --git a/examples/sttest/src/topology.rs b/examples/sttest/src/topology.rs index ca797eb0..52c38526 100644 --- a/examples/sttest/src/topology.rs +++ b/examples/sttest/src/topology.rs @@ -7,13 +7,14 @@ use harmony::{ }; use harmony_macros::{ip, ipv4}; use harmony_secret::{Secret, SecretManager}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::{ net::IpAddr, sync::{Arc, OnceLock}, }; -#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] struct OPNSenseFirewallConfig { username: String, password: String, diff --git a/harmony/src/domain/config/secret.rs b/harmony/src/domain/config/secret.rs index 02538691..e4f03299 100644 --- a/harmony/src/domain/config/secret.rs +++ b/harmony/src/domain/config/secret.rs @@ -1,20 +1,21 @@ use harmony_secret_derive::Secret; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] pub struct OPNSenseFirewallCredentials { pub username: String, pub password: String, } // TODO we need a better way to handle multiple "instances" of the same secret structure. -#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] pub struct SshKeyPair { pub private: String, pub public: String, } -#[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] pub struct RedhatSecret { pub pull_secret: String, } diff --git a/harmony/src/modules/application/features/monitoring.rs b/harmony/src/modules/application/features/monitoring.rs index fd6ae2a3..6f5bb214 100644 --- a/harmony/src/modules/application/features/monitoring.rs +++ b/harmony/src/modules/application/features/monitoring.rs @@ -28,6 +28,7 @@ use harmony_secret_derive::Secret; use harmony_types::net::Url; use kube::api::ObjectMeta; use log::{debug, info}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -132,7 +133,7 @@ impl< } } -#[derive(Secret, Serialize, Deserialize, Clone, Debug)] +#[derive(Secret, Serialize, Deserialize, JsonSchema, Clone, Debug)] struct NtfyAuth { username: String, password: String, diff --git a/harmony/src/modules/brocade.rs b/harmony/src/modules/brocade.rs index a52dd6ea..22ee564e 100644 --- a/harmony/src/modules/brocade.rs +++ b/harmony/src/modules/brocade.rs @@ -4,6 +4,7 @@ use async_trait::async_trait; use brocade::BrocadeOptions; use harmony_secret::{Secret, SecretManager}; use harmony_types::id::Id; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ @@ -37,13 +38,13 @@ pub struct BrocadeEnableSnmpInterpret { score: BrocadeEnableSnmpScore, } -#[derive(Secret, Clone, Debug, Serialize, Deserialize)] +#[derive(Secret, Clone, Debug, JsonSchema, Serialize, Deserialize)] struct BrocadeSwitchAuth { username: String, password: String, } -#[derive(Secret, Clone, Debug, Serialize, Deserialize)] +#[derive(Secret, Clone, Debug, JsonSchema, Serialize, Deserialize)] struct BrocadeSnmpAuth { username: String, auth_password: String, diff --git a/harmony/src/modules/okd/okd_node.rs b/harmony/src/modules/okd/okd_node.rs index d04478be..655ee1ce 100644 --- a/harmony/src/modules/okd/okd_node.rs +++ b/harmony/src/modules/okd/okd_node.rs @@ -45,7 +45,7 @@ impl OKDRoleProperties for WorkerRole { } fn required_hosts(&self) -> i16 { - 2 + 1 } fn logical_hosts<'a>(&self, t: &'a HAClusterTopology) -> &'a Vec { diff --git a/harmony_secret/Cargo.toml b/harmony_secret/Cargo.toml index 36bfb31a..0c76cfa8 100644 --- a/harmony_secret/Cargo.toml +++ b/harmony_secret/Cargo.toml @@ -19,6 +19,8 @@ tokio.workspace = true async-trait.workspace = true http.workspace = true inquire.workspace = true +interactive-parse = "0.1.5" +schemars = "0.8" [dev-dependencies] pretty_assertions.workspace = true diff --git a/harmony_secret/src/lib.rs b/harmony_secret/src/lib.rs index a4f636fb..2ff566ca 100644 --- a/harmony_secret/src/lib.rs +++ b/harmony_secret/src/lib.rs @@ -9,7 +9,10 @@ use config::INFISICAL_ENVIRONMENT; use config::INFISICAL_PROJECT_ID; use config::INFISICAL_URL; use config::SECRET_STORE; +use interactive_parse::InteractiveParseObj; use log::debug; +use log::info; +use schemars::JsonSchema; use serde::{Serialize, de::DeserializeOwned}; use std::fmt; use store::InfisicalSecretStore; @@ -20,7 +23,8 @@ use tokio::sync::OnceCell; pub use harmony_secret_derive::Secret; // The Secret trait remains the same. -pub trait Secret: Serialize + DeserializeOwned + Sized { +// pub trait Secret: Serialize + DeserializeOwned + Sized { +pub trait Secret: Serialize + DeserializeOwned + JsonSchema + InteractiveParseObj + Sized { const KEY: &'static str; } @@ -120,23 +124,15 @@ impl SecretManager { let ns = &manager.namespace; let key = T::KEY; - let secret_json = inquire::Text::new(&format!( - "Secret not found for {} {}, paste the JSON here :", - ns, key - )) - .prompt() - .map_err(|e| { - SecretStoreError::Store(format!("Failed to prompt secret {ns} {key} : {e}").into()) - })?; - let secret: T = serde_json::from_str(&secret_json).map_err(|e| { - SecretStoreError::Deserialization { - key: T::KEY.to_string(), - source: e, - } - })?; + debug!("Prompting interactively for secret {ns} {key}"); + info!("Secret not found for {} {}, fill the fields :", ns, key); - Ok(secret) + T::parse_to_obj().map_err(|e| { + SecretStoreError::Store( + format!("Failed to interactively parse secret {ns} {key}: {e}").into(), + ) + }) })?; if prompted { @@ -168,12 +164,12 @@ mod test { use pretty_assertions::assert_eq; use serde::{Deserialize, Serialize}; - #[derive(Serialize, Deserialize, Debug, PartialEq)] + #[derive(Serialize, Deserialize, JsonSchema, Debug, PartialEq)] struct TestUserMeta { labels: Vec, } - #[derive(Secret, Serialize, Deserialize, Debug, PartialEq)] + #[derive(Secret, Serialize, Deserialize, JsonSchema, Debug, PartialEq)] struct TestSecret { user: String, password: String,