deploy 2.0.0-dev-46

This commit is contained in:
mbecker20
2025-10-08 03:59:22 -07:00
parent 8afbbf23dc
commit 9e85b9d4c8
17 changed files with 167 additions and 161 deletions
Generated
+19 -19
View File
@@ -939,7 +939,7 @@ dependencies = [
[[package]]
name = "cache"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"tokio",
@@ -1131,7 +1131,7 @@ dependencies = [
[[package]]
name = "command"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"komodo_client",
"run_command",
@@ -1157,7 +1157,7 @@ checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
[[package]]
name = "config"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"colored",
"indexmap 2.11.4",
@@ -1442,7 +1442,7 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
[[package]]
name = "database"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"async-compression",
@@ -1750,7 +1750,7 @@ dependencies = [
[[package]]
name = "environment"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"formatting",
@@ -1760,7 +1760,7 @@ dependencies = [
[[package]]
name = "environment_file"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"thiserror 2.0.17",
]
@@ -1856,7 +1856,7 @@ dependencies = [
[[package]]
name = "formatting"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"serror",
]
@@ -2028,7 +2028,7 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]]
name = "git"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"cache",
@@ -2628,7 +2628,7 @@ dependencies = [
[[package]]
name = "interpolate"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"komodo_client",
@@ -2759,7 +2759,7 @@ dependencies = [
[[package]]
name = "komodo_cli"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"chrono",
@@ -2785,7 +2785,7 @@ dependencies = [
[[package]]
name = "komodo_client"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"async_timing_util",
@@ -2821,7 +2821,7 @@ dependencies = [
[[package]]
name = "komodo_core"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"arc-swap",
@@ -2895,7 +2895,7 @@ dependencies = [
[[package]]
name = "komodo_periphery"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"arc-swap",
@@ -3018,7 +3018,7 @@ dependencies = [
[[package]]
name = "logger"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"komodo_client",
@@ -3290,7 +3290,7 @@ dependencies = [
[[package]]
name = "noise"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"base64 0.22.1",
@@ -3797,7 +3797,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "periphery_client"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"komodo_client",
"resolver_api",
@@ -4344,7 +4344,7 @@ dependencies = [
[[package]]
name = "response"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"axum",
@@ -4666,7 +4666,7 @@ dependencies = [
[[package]]
name = "secret_file"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"tokio",
]
@@ -5679,7 +5679,7 @@ dependencies = [
[[package]]
name = "transport"
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
dependencies = [
"anyhow",
"axum",
+1 -1
View File
@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
version = "2.0.0-dev-45"
version = "2.0.0-dev-46"
edition = "2024"
authors = ["mbecker20 <becker.maxh@gmail.com>"]
license = "GPL-3.0-or-later"
+9 -8
View File
@@ -21,7 +21,7 @@ use komodo_client::{
stack::StackState,
},
};
use noise::key::generate_write_keys;
use noise::key::EncodedKeyPair;
use periphery_client::api;
use reqwest::StatusCode;
use resolver_api::Resolve;
@@ -32,7 +32,7 @@ use crate::{
api::execute::{
ExecuteArgs, pull_deployment_inner, pull_stack_inner,
},
config::{core_config, core_private_key, core_public_key},
config::{core_config, core_keys},
helpers::{periphery_client, update::update_update},
resource::rotate_server_keys,
state::{
@@ -506,14 +506,15 @@ impl Resolve<ExecuteArgs> for RotateCoreKeys {
);
}
let keys = generate_write_keys(private_key_path)?;
let keys =
EncodedKeyPair::generate_write_async(private_key_path).await?;
info!("New Public Key: {}", keys.public);
let public_key = keys.public.to_string();
info!("New Public Key: {public_key}");
core_private_key().store(Arc::new(keys.private.into_inner()));
core_public_key().store(Arc::new(keys.public.clone()));
core_keys().store(Arc::new(keys));
let mut log = format!("New Public Key: {}\n", keys.public);
let mut log = format!("New Public Key: {public_key}\n");
for (server, state) in servers {
match state {
@@ -539,7 +540,7 @@ impl Resolve<ExecuteArgs> for RotateCoreKeys {
let periphery = periphery_client(&server).await?;
let res = periphery
.request(api::keys::RotateCorePublicKey {
public_key: keys.public.to_string(),
public_key: public_key.clone(),
})
.await;
match res {
+2 -2
View File
@@ -28,7 +28,7 @@ use uuid::Uuid;
use crate::{
auth::auth_request,
config::{core_config, core_public_key},
config::{core_config, core_keys},
helpers::periphery_client,
resource,
};
@@ -308,7 +308,7 @@ impl Resolve<ReadArgs> for GetCoreInfo {
.map(|i| i.namespace.to_string())
.collect(),
timezone: config.timezone.clone(),
public_key: core_public_key().load().to_string(),
public_key: core_keys().load().public.to_string(),
};
Ok(info)
}
+10 -23
View File
@@ -20,35 +20,22 @@ use komodo_client::entities::{
},
logger::LogConfig,
};
use noise::key::{SpkiPublicKey, load_maybe_generate_private_key};
use noise::key::{EncodedKeyPair, SpkiPublicKey};
/// Should call in startup to ensure Core errors without valid private key.
pub fn core_private_key() -> &'static ArcSwap<String> {
static CORE_PRIVATE_KEY: OnceLock<ArcSwap<String>> =
pub fn core_keys() -> &'static ArcSwap<EncodedKeyPair> {
static CORE_KEYS: OnceLock<ArcSwap<EncodedKeyPair>> =
OnceLock::new();
CORE_PRIVATE_KEY.get_or_init(|| {
CORE_KEYS.get_or_init(|| {
let config = core_config();
let private_key =
let keys =
if let Some(path) = config.private_key.strip_prefix("file:") {
load_maybe_generate_private_key(path).unwrap()
EncodedKeyPair::load_maybe_generate(path)
} else {
config.private_key.clone()
};
ArcSwap::new(Arc::new(private_key))
})
}
/// Should call in startup to ensure Core errors without valid private key.
pub fn core_public_key() -> &'static ArcSwap<SpkiPublicKey> {
static CORE_PUBLIC_KEY: OnceLock<ArcSwap<SpkiPublicKey>> =
OnceLock::new();
CORE_PUBLIC_KEY.get_or_init(|| {
let public_key = SpkiPublicKey::from_private_key(
core_private_key().load().as_str(),
)
.context("Got invalid private key")
.unwrap();
ArcSwap::new(Arc::new(public_key))
EncodedKeyPair::from_private_key(&config.private_key)
}
.unwrap();
ArcSwap::new(Arc::new(keys))
})
}
+2 -2
View File
@@ -31,7 +31,7 @@ use transport::{
};
use crate::{
config::{core_private_key, periphery_public_keys},
config::{core_keys, periphery_public_keys},
periphery::ConnectionChannels,
state::db_client,
};
@@ -309,7 +309,7 @@ impl PeripheryConnection {
L::login(LoginFlowArgs {
socket,
identifiers,
private_key: core_private_key().load().as_str(),
private_key: core_keys().load().private.as_str(),
public_key_validator: self.args.borrow(),
})
.await?;
+2 -2
View File
@@ -31,7 +31,7 @@ use transport::{
use crate::{
api::write::WriteArgs,
config::core_private_key,
config::core_keys,
helpers::query::id_or_name_filter,
resource::KomodoResource,
state::{db_client, periphery_connections},
@@ -162,7 +162,7 @@ async fn onboard_server_handler(
let onboarding_key = match ServerLoginFlow::login(LoginFlowArgs {
socket: &mut socket,
identifiers: identifiers.build(query.as_bytes()),
private_key: core_private_key().load().as_str(),
private_key: core_keys().load().private.as_str(),
public_key_validator: CreationKeyValidator,
})
.await
+2 -2
View File
@@ -13,7 +13,7 @@ use tower_http::{
services::{ServeDir, ServeFile},
};
use crate::config::{core_config, core_public_key};
use crate::config::{core_config, core_keys};
mod alert;
mod api;
@@ -54,7 +54,7 @@ async fn app() -> anyhow::Result<()> {
}
// Init + log public key. Will crash if invalid private key here.
info!("Public Key: {}", core_public_key().load());
info!("Public Key: {}", core_keys().load().public);
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
+22 -20
View File
@@ -1,18 +1,14 @@
use std::sync::Arc;
use komodo_client::entities::NoData;
use noise::key::{
EncodedKeyPair, SpkiPublicKey, generate_write_keys,
};
use noise::key::{EncodedKeyPair, SpkiPublicKey};
use periphery_client::api::keys::{
RotateCorePublicKey, RotatePrivateKey, RotatePrivateKeyResponse,
};
use resolver_api::Resolve;
use crate::{
config::{
periphery_config, periphery_private_key, periphery_public_key,
},
config::{periphery_config, periphery_keys},
connection::core_public_keys,
};
@@ -36,22 +32,24 @@ impl Resolve<super::Args> for RotatePrivateKey {
.into_inner(),
});
}
Some(path) => generate_write_keys(path)?,
Some(path) => {
EncodedKeyPair::generate_write_async(path).await?
}
},
None => generate_write_keys(
config.root_directory.join("keys/periphery.key"),
)?,
None => {
EncodedKeyPair::generate_write_async(
config.root_directory.join("keys/periphery.key"),
)
.await?
}
};
info!("New Public Key: {}", keys.public);
let public_key = keys.public.to_string();
info!("New Public Key: {public_key}");
periphery_private_key()
.store(Arc::new(keys.private.into_inner()));
periphery_public_key().store(Arc::new(keys.public.clone()));
periphery_keys().store(Arc::new(keys));
Ok(RotatePrivateKeyResponse {
public_key: keys.public.into_inner(),
})
Ok(RotatePrivateKeyResponse { public_key })
}
}
@@ -75,9 +73,13 @@ impl Resolve<super::Args> for RotateCorePublicKey {
return Ok(NoData {});
};
SpkiPublicKey::from(self.public_key)
.write_pem_async(path)
.await?;
let public_key = SpkiPublicKey::from(self.public_key);
// Check equality at path before trying to rewrite.
match SpkiPublicKey::from_file(path) {
Ok(existing) if existing == public_key => {}
_ => public_key.write_pem_async(path).await?,
}
core_public_keys().refresh();
+2 -2
View File
@@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
use crate::{
api::compose::list_compose_projects,
config::{periphery_config, periphery_public_key},
config::{periphery_config, periphery_keys},
docker::docker_client,
stats::stats_client,
};
@@ -229,7 +229,7 @@ impl Resolve<Args> for PollStatus {
Ok(PollStatusResponse {
periphery_info: PeripheryInformation {
version: env!("CARGO_PKG_VERSION").to_string(),
public_key: periphery_public_key().load().to_string(),
public_key: periphery_keys().load().public.to_string(),
terminals_disabled: config.disable_terminals,
container_exec_disabled: config.disable_container_exec,
stats_polling_rate: config.stats_polling_rate,
+16 -27
View File
@@ -3,7 +3,6 @@ use std::{
sync::{Arc, OnceLock},
};
use anyhow::Context;
use arc_swap::ArcSwap;
use clap::Parser;
use colored::Colorize;
@@ -15,39 +14,29 @@ use komodo_client::entities::{
config::periphery::{CliArgs, Env, PeripheryConfig},
logger::{LogConfig, LogLevel},
};
use noise::key::{SpkiPublicKey, load_maybe_generate_private_key};
use noise::key::EncodedKeyPair;
/// Should call in startup to ensure Periphery errors without valid private key.
pub fn periphery_private_key() -> &'static ArcSwap<String> {
static PERIPHERY_PRIVATE_KEY: OnceLock<ArcSwap<String>> =
pub fn periphery_keys() -> &'static ArcSwap<EncodedKeyPair> {
static PERIPHERY_KEYS: OnceLock<ArcSwap<EncodedKeyPair>> =
OnceLock::new();
PERIPHERY_PRIVATE_KEY.get_or_init(|| {
PERIPHERY_KEYS.get_or_init(|| {
let config = periphery_config();
let private_key = config.private_key.clone().unwrap_or(format!(
"file:{}/keys/periphery.key",
config.root_directory.display()
));
let private_key =
config.private_key.clone().unwrap_or_else(|| {
format!(
"file:{}/keys/periphery.key",
config.root_directory.display()
)
});
let keys =
if let Some(path) = private_key.strip_prefix("file:") {
load_maybe_generate_private_key(path).unwrap()
EncodedKeyPair::load_maybe_generate(path)
} else {
private_key
};
ArcSwap::new(Arc::new(private_key))
})
}
/// Should call in startup to ensure Periphery errors without valid private key.
pub fn periphery_public_key() -> &'static ArcSwap<SpkiPublicKey> {
static PERIPHERY_PUBLIC_KEY: OnceLock<ArcSwap<SpkiPublicKey>> =
OnceLock::new();
PERIPHERY_PUBLIC_KEY.get_or_init(|| {
let public_key = SpkiPublicKey::from_private_key(
periphery_private_key().load().as_str(),
)
.context("Got invalid private key")
.unwrap();
ArcSwap::new(Arc::new(public_key))
EncodedKeyPair::from_private_key(&private_key)
}
.unwrap();
ArcSwap::new(Arc::new(keys))
})
}
+2 -2
View File
@@ -14,7 +14,7 @@ use transport::{
use crate::{
api::Args,
config::{periphery_config, periphery_public_key},
config::{periphery_config, periphery_keys},
connection::{core_channels, core_public_keys},
};
@@ -176,7 +176,7 @@ async fn handle_onboarding(
// Post onboarding login 1: Send public key
socket
.send(periphery_public_key().load().as_bytes())
.send(periphery_keys().load().public.as_bytes())
.await
.context("Failed to send public key bytes")?;
+9 -15
View File
@@ -1,10 +1,9 @@
use std::{
fs::read_to_string,
sync::{Arc, OnceLock},
time::Duration,
};
use anyhow::{Context as _, anyhow};
use anyhow::anyhow;
use arc_swap::ArcSwap;
use bytes::Bytes;
use cache::CloneCache;
@@ -24,7 +23,7 @@ use uuid::Uuid;
use crate::{
api::{Args, PeripheryRequest},
config::{periphery_config, periphery_private_key},
config::{periphery_config, periphery_keys},
};
pub mod client;
@@ -68,18 +67,13 @@ impl CorePublicKeys {
let core_public_keys = core_public_keys
.iter()
.flat_map(|public_key| {
let res = || {
if let Some(path) = public_key.strip_prefix("file:") {
let contents =
read_to_string(path).with_context(|| {
format!("Failed to read public key at {path:?}")
})?;
SpkiPublicKey::from_maybe_pem(&contents)
} else {
SpkiPublicKey::from_maybe_pem(&public_key)
}
let res = if let Some(path) = public_key.strip_prefix("file:")
{
SpkiPublicKey::from_file(path)
} else {
SpkiPublicKey::from_maybe_pem(&public_key)
};
match (res(), config.server_enabled) {
match (res, config.server_enabled) {
(Ok(public_key), _) => Some(public_key),
(Err(e), false) => {
// If only outbound connections, only warn.
@@ -123,7 +117,7 @@ async fn handle_login<W: Websocket, L: LoginFlow>(
L::login(LoginFlowArgs {
socket,
identifiers,
private_key: periphery_private_key().load().as_str(),
private_key: periphery_keys().load().private.as_str(),
public_key_validator: core_public_keys(),
})
.await
+2 -2
View File
@@ -1,7 +1,7 @@
use futures::{StreamExt, stream::FuturesUnordered};
use komodo_client::entities::config::periphery::Command;
use crate::config::{periphery_args, periphery_public_key};
use crate::config::{periphery_args, periphery_keys};
#[macro_use]
extern crate tracing;
@@ -27,7 +27,7 @@ async fn app() -> anyhow::Result<()> {
}
// Init + log public key. Will crash if invalid private key here.
info!("Public Key: {}", periphery_public_key().load());
info!("Public Key: {}", periphery_keys().load().public);
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
+47 -32
View File
@@ -29,51 +29,66 @@ pub struct EncodedKeyPair {
}
impl EncodedKeyPair {
pub fn generate() -> anyhow::Result<EncodedKeyPair> {
pub fn generate() -> anyhow::Result<Self> {
let builder = snow::Builder::new(crate::NOISE_XX_PARAMS.parse()?);
let keypair = builder
.generate_keypair()
.context("Failed to generate keypair")?;
let private = Pkcs8PrivateKey::from_raw_bytes(&keypair.private)?;
let public = SpkiPublicKey::from_raw_bytes(&keypair.public)?;
Ok(EncodedKeyPair { private, public })
Ok(Self { private, public })
}
pub fn generate_write_sync(
path: impl AsRef<Path>,
) -> anyhow::Result<Self> {
let path = path.as_ref();
// Generate and write pems to path
let keys = Self::generate()?;
keys.private.write_pem_sync(path)?;
keys.public.write_pem_sync(path.with_extension("pub"))?;
Ok(keys)
}
pub async fn generate_write_async(
path: impl AsRef<Path>,
) -> anyhow::Result<Self> {
let path = path.as_ref();
// Generate and write pems to path
let keys = Self::generate()?;
keys.private.write_pem_async(path).await?;
keys
.public
.write_pem_async(path.with_extension("pub"))
.await?;
Ok(keys)
}
pub fn load_maybe_generate(
private_key_path: impl AsRef<Path>,
) -> anyhow::Result<Self> {
let path = private_key_path.as_ref();
let exists = path.try_exists().with_context(|| {
format!("Invalid private key path: {path:?}")
})?;
if !exists {
return Self::generate_write_sync(path);
}
let private = Pkcs8PrivateKey::from_file(private_key_path)?;
let public = private.compute_public_key()?;
Ok(Self { private, public })
}
pub fn from_private_key(
maybe_pkcs8_private_key: &str,
) -> anyhow::Result<EncodedKeyPair> {
) -> anyhow::Result<Self> {
let private =
Pkcs8PrivateKey::from_maybe_raw_bytes(maybe_pkcs8_private_key)?;
let public = private.compute_public_key()?;
Ok(Self { private, public })
}
}
pub fn load_maybe_generate_private_key(
path: impl AsRef<Path>,
) -> anyhow::Result<String> {
let path = path.as_ref();
if path
.try_exists()
.with_context(|| format!("Invalid private key path: {path:?}"))?
{
// Already exists, load it
std::fs::read_to_string(path).with_context(|| {
format!("Failed to read private key at {path:?}")
})
} else {
let keys = generate_write_keys(path)?;
Ok(keys.private.into_inner())
}
}
pub fn generate_write_keys(
path: impl AsRef<Path>,
) -> anyhow::Result<EncodedKeyPair> {
let path = path.as_ref();
// Generate and write pems to path
let keys = EncodedKeyPair::generate()?;
keys.private.write_pem_sync(path)?;
keys.public.write_pem_sync(path.with_extension("pub"))?;
Ok(keys)
}
+9
View File
@@ -68,6 +68,15 @@ impl Pkcs8PrivateKey {
})
}
pub fn from_file(path: impl AsRef<Path>) -> anyhow::Result<Self> {
let path = path.as_ref();
let contents =
std::fs::read_to_string(path).with_context(|| {
format!("Failed to read private key at {path:?}")
})?;
Self::from_maybe_raw_bytes(&contents)
}
/// - For raw bytes: converts to pkcs8 and returns
/// - For pkcs8 base64: clones and returns
/// - For pkcs8 base64 pem: unwraps and returns
+11 -2
View File
@@ -50,7 +50,7 @@ impl SpkiPublicKey {
let path = path.as_ref();
tracing::info!("Writing public key to {path:?}");
secret_file::write_sync(path, self.as_pem()).with_context(|| {
format!("Failed to write private key pem to {path:?}")
format!("Failed to write public key pem to {path:?}")
})
}
@@ -63,10 +63,19 @@ impl SpkiPublicKey {
secret_file::write_async(path, self.as_pem())
.await
.with_context(|| {
format!("Failed to write private key pem to {path:?}")
format!("Failed to write public key pem to {path:?}")
})
}
pub fn from_file(path: impl AsRef<Path>) -> anyhow::Result<Self> {
let path = path.as_ref();
let contents =
std::fs::read_to_string(path).with_context(|| {
format!("Failed to read public key at {path:?}")
})?;
Self::from_maybe_pem(&contents)
}
/// Accepts pem rfc7468 (openssl) or base64 der (second line of rfc7468 pem).
pub fn from_maybe_pem(
public_key_maybe_pem: &str,