periphery support same key gen functions

This commit is contained in:
mbecker20
2025-09-29 23:32:47 -07:00
parent 941787db64
commit 21689ce0ad
14 changed files with 133 additions and 71 deletions

26
Cargo.lock generated
View File

@@ -100,9 +100,9 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.11"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
@@ -2757,6 +2757,17 @@ dependencies = [
"simple_asn1",
]
[[package]]
name = "keygen"
version = "2.0.0-dev-17"
dependencies = [
"anyhow",
"colored",
"komodo_client",
"noise",
"serde_json",
]
[[package]]
name = "komodo_cli"
version = "2.0.0-dev-17"
@@ -2772,9 +2783,9 @@ dependencies = [
"environment_file",
"envy",
"futures-util",
"keygen",
"komodo_client",
"logger",
"noise",
"serde",
"serde_json",
"serde_qs",
@@ -2918,6 +2929,7 @@ dependencies = [
"futures",
"git",
"interpolate",
"keygen",
"komodo_client",
"logger",
"noise",
@@ -4045,9 +4057,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -6603,9 +6615,9 @@ dependencies = [
[[package]]
name = "zeroize"
version = "1.8.1"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"

View File

@@ -31,6 +31,7 @@ database = { path = "lib/database" }
response = { path = "lib/response" }
command = { path = "lib/command" }
config = { path = "lib/config" }
keygen = { path = "lib/keygen" }
logger = { path = "lib/logger" }
cache = { path = "lib/cache" }
noise = { path = "lib/noise" }

View File

@@ -18,8 +18,8 @@ environment_file.workspace = true
komodo_client.workspace = true
database.workspace = true
config.workspace = true
keygen.workspace = true
logger.workspace = true
noise.workspace = true
# external
futures-util.workspace = true
comfy-table.workspace = true

View File

@@ -17,7 +17,6 @@ use crate::config::cli_config;
pub mod container;
pub mod database;
pub mod execute;
pub mod key;
pub mod list;
pub mod update;

View File

@@ -42,7 +42,7 @@ async fn app() -> anyhow::Result<()> {
Ok(())
}
args::Command::Key { command } => {
command::key::handle(command).await
keygen::handle_key_command(command).await
}
args::Command::Database { command } => {
command::database::handle(command).await

View File

@@ -25,6 +25,7 @@ transport.workspace = true
response.workspace = true
command.workspace = true
config.workspace = true
keygen.workspace = true
logger.workspace = true
cache.workspace = true
noise.workspace = true

View File

@@ -20,16 +20,26 @@ pub fn periphery_public_key() -> &'static String {
})
}
pub fn periphery_args() -> &'static CliArgs {
static PERIPHERY_ARGS: OnceLock<CliArgs> = OnceLock::new();
PERIPHERY_ARGS.get_or_init(CliArgs::parse)
}
pub fn periphery_config() -> &'static PeripheryConfig {
static PERIPHERY_CONFIG: OnceLock<PeripheryConfig> =
OnceLock::new();
PERIPHERY_CONFIG.get_or_init(|| {
let env: Env = envy::from_env()
.expect("failed to parse periphery environment");
let args = CliArgs::parse();
let config_paths =
args.config_path.unwrap_or(env.periphery_config_paths);
let args = periphery_args();
let config_paths = args
.config_path
.as_ref()
.unwrap_or(&env.periphery_config_paths);
println!("{config_paths:?}");
let config = if config_paths.is_empty() {
println!(
"{}: No config paths found, using default config",
@@ -44,7 +54,8 @@ pub fn periphery_config() -> &'static PeripheryConfig {
.collect::<Vec<_>>(),
match_wildcards: &args
.config_keyword
.unwrap_or(env.periphery_config_keywords)
.as_ref()
.unwrap_or(&env.periphery_config_keywords)
.iter()
.map(String::as_str)
.collect::<Vec<_>>(),

View File

@@ -1,6 +1,7 @@
use futures::{StreamExt, stream::FuturesUnordered};
use komodo_client::entities::config::periphery::Command;
use crate::config::periphery_public_key;
use crate::config::{periphery_args, periphery_public_key};
#[macro_use]
extern crate tracing;
@@ -14,7 +15,6 @@ mod stats;
mod terminal;
async fn app() -> anyhow::Result<()> {
dotenvy::dotenv().ok();
let config = config::periphery_config();
logger::init(&config.logging)?;
@@ -77,6 +77,13 @@ async fn app() -> anyhow::Result<()> {
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Handle `periphery key gen` and `periphery key compute <private-key>`
if let Some(Command::Key { command }) = &periphery_args().command {
return keygen::handle_key_command(command).await;
}
dotenvy::dotenv().ok();
let mut term_signal = tokio::signal::unix::signal(
tokio::signal::unix::SignalKind::terminate(),
)?;

View File

@@ -1,48 +0,0 @@
use serde::Serialize;
#[derive(Debug, Clone, clap::Subcommand)]
pub enum KeyCommand {
/// Generate a new public / private key pair
/// for use with Core - Periphery authentication.
/// (aliases: `gen`, `g`)
#[clap(alias = "gen", alias = "g")]
Generate {
/// Specify the format of the output.
#[arg(long, short = 'f', default_value_t = KeyOutputFormat::Standard)]
format: KeyOutputFormat,
},
/// Compute the public key for a given private key.
/// (aliases: `comp`, `c`)
#[clap(alias = "comp", alias = "c")]
Compute {
/// Pass the private key
private_key: String,
/// Specify the format of the output.
#[arg(long, short = 'f', default_value_t = KeyOutputFormat::Standard)]
format: KeyOutputFormat,
},
}
#[derive(
Debug, Clone, Copy, Default, strum::Display, clap::ValueEnum,
)]
#[strum(serialize_all = "lowercase")]
pub enum KeyOutputFormat {
/// Readable output format. Default. (alias: `t`)
#[default]
#[clap(alias = "s")]
Standard,
/// Json (single line) output format. (alias: `j`)
#[clap(alias = "j")]
Json,
/// Json "pretty" (multi line) output format. (alias: `jp`)
#[clap(alias = "jp")]
JsonPretty,
}
#[derive(Serialize)]
pub struct KeyPair<'a> {
pub private_key: &'a str,
pub public_key: &'a str,
}

View File

@@ -6,7 +6,6 @@ use crate::api::execute::Execution;
pub mod container;
pub mod database;
pub mod key;
pub mod list;
pub mod update;
@@ -52,11 +51,11 @@ pub enum Command {
unsanitized: bool,
},
/// Public-Private key utilities. (alias: `k`)
/// Private-Public key utilities. (alias: `k`)
#[clap(alias = "k")]
Key {
#[command(subcommand)]
command: key::KeyCommand,
command: crate::entities::config::KeyCommand,
},
/// Database utilities. (alias: `db`)

View File

@@ -182,6 +182,54 @@ pub struct ProviderAccount {
pub token: String,
}
/// Private-Public key utilities. (alias: `k`)
#[derive(Debug, Clone, clap::Subcommand)]
pub enum KeyCommand {
/// Generate a new public / private key pair
/// for use with Core - Periphery authentication.
/// (aliases: `gen`, `g`)
#[clap(alias = "gen", alias = "g")]
Generate {
/// Specify the format of the output.
#[arg(long, short = 'f', default_value_t = KeyOutputFormat::Standard)]
format: KeyOutputFormat,
},
/// Compute the public key for a given private key.
/// (aliases: `comp`, `c`)
#[clap(alias = "comp", alias = "c")]
Compute {
/// Pass the private key
private_key: String,
/// Specify the format of the output.
#[arg(long, short = 'f', default_value_t = KeyOutputFormat::Standard)]
format: KeyOutputFormat,
},
}
#[derive(
Debug, Clone, Copy, Default, strum::Display, clap::ValueEnum,
)]
#[strum(serialize_all = "lowercase")]
pub enum KeyOutputFormat {
/// Readable output format. Default. (alias: `t`)
#[default]
#[clap(alias = "s")]
Standard,
/// Json (single line) output format. (alias: `j`)
#[clap(alias = "j")]
Json,
/// Json "pretty" (multi line) output format. (alias: `jp`)
#[clap(alias = "jp")]
JsonPretty,
}
#[derive(Serialize)]
pub struct KeyPair<'a> {
pub private_key: &'a str,
pub public_key: &'a str,
}
pub fn empty_or_redacted(src: &str) -> String {
if src.is_empty() {
String::new()

View File

@@ -50,6 +50,10 @@ use super::{
#[derive(Parser)]
#[command(name = "periphery", author, about, version)]
pub struct CliArgs {
/// Additional utilities.
#[command(subcommand)]
pub command: Option<Command>,
/// Sets the path of a config file or directory to use.
/// Can use multiple times
#[arg(long, short = 'c')]
@@ -80,6 +84,16 @@ pub struct CliArgs {
pub log_level: Option<tracing::Level>,
}
#[derive(Debug, Clone, clap::Subcommand)]
pub enum Command {
/// Private-Public key utilities. (alias: `k`)
#[clap(alias = "k")]
Key {
#[command(subcommand)]
command: crate::entities::config::KeyCommand,
},
}
/// # Periphery Environment Variables
///
/// The variables should be passed in the traditional `UPPER_SNAKE_CASE` format,

16
lib/keygen/Cargo.toml Normal file
View File

@@ -0,0 +1,16 @@
[package]
name = "keygen"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
[dependencies]
komodo_client.workspace = true
noise.workspace = true
#
serde_json.workspace = true
colored.workspace = true
anyhow.workspace = true

View File

@@ -1,10 +1,12 @@
use anyhow::Context;
use colored::Colorize;
use komodo_client::entities::config::cli::args::key::{
use komodo_client::entities::config::{
KeyCommand, KeyOutputFormat, KeyPair,
};
pub async fn handle(command: &KeyCommand) -> anyhow::Result<()> {
pub async fn handle_key_command(
command: &KeyCommand,
) -> anyhow::Result<()> {
match command {
KeyCommand::Generate { format } => {
let keys = noise::Base64KeyPair::generate()
@@ -14,11 +16,11 @@ pub async fn handle(command: &KeyCommand) -> anyhow::Result<()> {
// Prefixed with 'base64:' so Core / Periphery know to parse
// private key as base64.
println!(
"Private Key: {}{}",
"\nPrivate Key: {}{}",
"base64:".red().bold(),
keys.private_key.red().bold()
);
println!("\nPublic Key: {}", keys.public_key.bold());
println!("Public Key: {}", keys.public_key.bold());
}
KeyOutputFormat::Json => print_json(
&format!("base64:{}", keys.private_key),