diff --git a/bin/periphery/src/config.rs b/bin/periphery/src/config.rs index 99c8c37fb..b73b67c15 100644 --- a/bin/periphery/src/config.rs +++ b/bin/periphery/src/config.rs @@ -73,9 +73,9 @@ pub fn periphery_config() -> &'static PeripheryConfig { env.periphery_private_key, ) .unwrap_or(config.private_key), - core_public_key: env - .periphery_core_public_key - .or(config.core_public_key), + core_public_keys: env + .periphery_core_public_keys + .or(config.core_public_keys), passkeys: maybe_read_list_from_file( env.periphery_passkeys_file, env.periphery_passkeys, diff --git a/bin/periphery/src/connection/mod.rs b/bin/periphery/src/connection/mod.rs index 9fde31fe3..fbda7572b 100644 --- a/bin/periphery/src/connection/mod.rs +++ b/bin/periphery/src/connection/mod.rs @@ -73,13 +73,13 @@ pub struct CorePublicKeyValidator; impl PublicKeyValidator for CorePublicKeyValidator { fn validate(&self, public_key: String) -> anyhow::Result<()> { - if let Some(expected_public_key) = - periphery_config().core_public_key.as_ref() - && &public_key != expected_public_key + if let Some(public_keys) = + periphery_config().core_public_keys.as_ref() + && public_keys.iter().all(|expected| &public_key != expected) { Err( anyhow!("Got invalid public key: {public_key}") - .context("Ensure public key matches 'core_public_key' in periphery config (PERIPHERY_CORE_PUBLIC_KEY)") + .context("Ensure public key matches one of the 'core_public_keys' in periphery config (PERIPHERY_CORE_PUBLIC_KEYS)") .context("Periphery failed to validate Core public key"), ) } else { diff --git a/bin/periphery/src/connection/server.rs b/bin/periphery/src/connection/server.rs index ee3274881..ce585296a 100644 --- a/bin/periphery/src/connection/server.rs +++ b/bin/periphery/src/connection/server.rs @@ -149,7 +149,7 @@ async fn handle_login( ) -> anyhow::Result<()> { let config = periphery_config(); - match (&config.core_public_key, &config.passkeys) { + match (&config.core_public_keys, &config.passkeys) { (Some(_), _) | (_, None) => { // Send login type [0] (Noise auth) socket diff --git a/client/core/rs/src/entities/config/periphery.rs b/client/core/rs/src/entities/config/periphery.rs index e3a6c8384..8c41e7592 100644 --- a/client/core/rs/src/entities/config/periphery.rs +++ b/client/core/rs/src/entities/config/periphery.rs @@ -18,7 +18,7 @@ use serde::Deserialize; use std::{collections::HashMap, path::PathBuf}; use crate::{ - deserializers::ForgivingVec, + deserializers::{ForgivingVec, option_string_list_deserializer}, entities::{ Timelength, logger::{LogConfig, LogLevel, StdioLogMode}, @@ -125,8 +125,9 @@ pub struct Env { pub periphery_private_key: Option, /// Override `private_key` from file pub periphery_private_key_file: Option, - /// Override `core_public_key` - pub periphery_core_public_key: Option, + /// Override `core_public_keys` + #[serde(alias = "periphery_core_public_key")] + pub periphery_core_public_keys: Option>, /// Override `passkeys` pub periphery_passkeys: Option>, /// Override `passkeys` from file @@ -200,8 +201,12 @@ pub struct PeripheryConfig { pub private_key: String, /// Optionally pin a specific Core public key /// for additional trust. - #[serde(skip_serializing_if = "Option::is_none")] - pub core_public_key: Option, + #[serde( + alias = "core_public_key", + deserialize_with = "option_string_list_deserializer", + skip_serializing_if = "Option::is_none" + )] + pub core_public_keys: Option>, /// Deprecated. Legacy v1 compatibility. /// Users should upgrade to private / public key authentication. #[serde(skip_serializing_if = "Option::is_none")] @@ -382,7 +387,7 @@ impl Default for PeripheryConfig { fn default() -> Self { Self { private_key: default_private_key(), - core_public_key: None, + core_public_keys: None, passkeys: None, core_address: None, connect_as: None, @@ -417,7 +422,7 @@ impl PeripheryConfig { pub fn sanitized(&self) -> PeripheryConfig { PeripheryConfig { private_key: empty_or_redacted(&self.private_key), - core_public_key: self.core_public_key.clone(), + core_public_keys: self.core_public_keys.clone(), passkeys: self.passkeys.as_ref().map(|passkeys| { passkeys.iter().map(|p| empty_or_redacted(p)).collect() }),