Skip to content

Commit

Permalink
Introduce Sensitive which can be used for hiding Debug impls
Browse files Browse the repository at this point in the history
Use it everywhere where we used to manually implement `Debug` on types
to hide information.

Alternative to #2463.

Fixes #2459.
  • Loading branch information
hrxi committed May 10, 2024
1 parent 3071188 commit 7c6a928
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 84 deletions.
72 changes: 13 additions & 59 deletions lib/src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use nimiq_network_interface::Multiaddr;
use nimiq_network_libp2p::{Keypair as IdentityKeypair, Libp2pKeyPair};
use nimiq_primitives::{networks::NetworkId, policy::Policy};
use nimiq_serde::Deserialize;
use nimiq_utils::file_store::FileStore;
#[cfg(feature = "validator")]
use nimiq_utils::key_rng::SecureGenerate;
use nimiq_utils::{file_store::FileStore, Sensitive};
use nimiq_zkp_circuits::DEFAULT_KEYS_PATH;
use strum_macros::Display;

Expand Down Expand Up @@ -161,7 +161,7 @@ impl From<TlsSettings> for TlsConfig {
}
}

#[derive(Clone, Eq, PartialEq, Hash)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct FileStorageConfig {
/// The parent directory where the database will be stored. The database directory name
/// is determined by the network ID and consensus type using the `database_name` static
Expand All @@ -172,31 +172,31 @@ pub struct FileStorageConfig {
pub peer_key_path: PathBuf,

/// The key used for the peer key, if the file is not present.
pub peer_key: Option<String>,
pub peer_key: Option<Sensitive<String>>,

/// Path to voting key.
#[cfg(feature = "validator")]
pub voting_key_path: Option<PathBuf>,

/// The voting key used for the validator, if the file is not present.
#[cfg(feature = "validator")]
pub voting_key: Option<String>,
pub voting_key: Option<Sensitive<String>>,

/// Path to signing key.
#[cfg(feature = "validator")]
pub signing_key_path: Option<PathBuf>,

/// The signing key used for the validator, if the file is not present.
#[cfg(feature = "validator")]
pub signing_key: Option<String>,
pub signing_key: Option<Sensitive<String>>,

/// Path to fee key.
#[cfg(feature = "validator")]
pub fee_key_path: Option<PathBuf>,

/// The fee key used for the validator, if the file is not present.
#[cfg(feature = "validator")]
pub fee_key: Option<String>,
pub fee_key: Option<Sensitive<String>>,
}

impl FileStorageConfig {
Expand Down Expand Up @@ -241,28 +241,6 @@ impl Default for FileStorageConfig {
}
}

impl Debug for FileStorageConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug_struct = f.debug_struct("FileStorageConfig");
debug_struct
.field("database_parent", &self.database_parent)
.field("peer_key_path", &self.peer_key_path)
.field("peer_key", &self.peer_key.as_ref().map(|_| "***"));

#[cfg(feature = "validator")]
{
debug_struct
.field("voting_key_path", &self.voting_key_path)
.field("voting_key", &self.voting_key.as_ref().map(|_| "***"))
.field("signing_key_path", &self.signing_key_path)
.field("signing_key", &self.signing_key.as_ref().map(|_| "***"))
.field("fee_key_path", &self.fee_key_path)
.field("fee_key", &self.fee_key.as_ref().map(|_| "***"));
}
debug_struct.finish()
}
}

/// Configuration options for the database
#[cfg(feature = "database-storage")]
#[derive(Debug, Clone, Builder, Eq, PartialEq)]
Expand Down Expand Up @@ -525,24 +503,24 @@ pub struct Credentials {
/// Username
pub username: String,
/// Password
pub password: String,
pub password: Sensitive<String>,
}

impl Credentials {
pub fn new<U: AsRef<str>, P: AsRef<str>>(username: U, password: P) -> Self {
Self {
username: username.as_ref().to_owned(),
password: password.as_ref().to_owned(),
password: Sensitive(password.as_ref().to_owned()),
}
}

pub fn check<U: AsRef<str>, P: AsRef<str>>(&self, username: U, password: P) -> bool {
self.username == username.as_ref() && self.password == password.as_ref()
self.username == username.as_ref() && *self.password == password.as_ref()
}
}

#[cfg(feature = "rpc-server")]
#[derive(Clone, Builder)]
#[derive(Builder, Clone, Debug)]
#[builder(setter(into))]
pub struct RpcServerConfig {
/// Bind the RPC server to the specified IP address.
Expand Down Expand Up @@ -578,22 +556,8 @@ pub struct RpcServerConfig {
pub credentials: Option<Credentials>,
}

#[cfg(feature = "rpc-server")]
impl Debug for RpcServerConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RpcServerConfig")
.field("bind_to", &self.bind_to)
.field("port", &self.port)
.field("corsdomain", &self.corsdomain)
.field("allow_ips", &self.allow_ips)
.field("allowed_methods", &self.allowed_methods)
.field("credentials", &self.credentials.as_ref().map(|_| "***"))
.finish()
}
}

#[cfg(feature = "metrics-server")]
#[derive(Clone, Builder)]
#[derive(Builder, Clone, Debug)]
#[builder(setter(into))]
pub struct MetricsServerConfig {
/// Bind the server to the specified ip and port.
Expand All @@ -607,16 +571,6 @@ pub struct MetricsServerConfig {
pub credentials: Option<Credentials>,
}

#[cfg(feature = "metrics-server")]
impl Debug for MetricsServerConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MetricsServerConfig")
.field("addr", &self.addr)
.field("credentials", &self.credentials.as_ref().map(|_| "***"))
.finish()
}
}

/// Client configuration
///
/// # ToDo
Expand Down Expand Up @@ -895,7 +849,7 @@ impl ClientConfigBuilder {
};

let credentials = match (&rpc_config.username, &rpc_config.password) {
(Some(u), Some(p)) => Some(Credentials::new(u.clone(), p.clone())),
(Some(u), Some(p)) => Some(Credentials::new(u, p)),
(None, None) => None,
_ => {
return Err(Error::config_error(
Expand Down Expand Up @@ -938,7 +892,7 @@ impl ClientConfigBuilder {

let credentials =
match (&metrics_config.username, &metrics_config.password) {
(Some(u), Some(p)) => Some(Credentials::new(u.clone(), p.clone())),
(Some(u), Some(p)) => Some(Credentials::new(u, p)),
(None, None) => None,
_ => return Err(Error::config_error(
"Metrics: Either both username and password have to be set or none.",
Expand Down
30 changes: 8 additions & 22 deletions lib/src/config/config_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use nimiq_mempool::{
use nimiq_network_interface::Multiaddr;
use nimiq_primitives::{coin::Coin, networks::NetworkId};
use nimiq_serde::Deserialize;
use nimiq_utils::Sensitive;
use thiserror::Error;
use url::Url;

Expand Down Expand Up @@ -124,7 +125,7 @@ impl FromStr for ConfigFile {
#[serde(deny_unknown_fields)]
pub struct NetworkSettings {
pub peer_key_file: Option<String>,
pub peer_key: Option<String>,
pub peer_key: Option<Sensitive<String>>,

#[serde(default)]
pub listen_addresses: Vec<String>,
Expand Down Expand Up @@ -241,7 +242,7 @@ pub struct RpcServerSettings {
#[serde(default)]
pub methods: Vec<String>,
pub username: Option<String>,
pub password: Option<String>,
pub password: Option<Sensitive<String>>,
}

#[derive(Clone, Debug, Deserialize, Default)]
Expand All @@ -252,7 +253,7 @@ pub struct MetricsServerSettings {
pub bind: Option<String>,
pub port: Option<u16>,
pub username: Option<String>,
pub password: Option<String>,
pub password: Option<Sensitive<String>>,
}

#[derive(Clone, Debug, Deserialize)]
Expand Down Expand Up @@ -403,35 +404,20 @@ impl From<MempoolFilterSettings> for MempoolRules {
}
}

#[derive(Clone, Deserialize, Default)]
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct ValidatorSettings {
pub validator_address: String,
pub signing_key_file: Option<String>,
pub signing_key: Option<String>,
pub signing_key: Option<Sensitive<String>>,
pub voting_key_file: Option<String>,
pub voting_key: Option<String>,
pub voting_key: Option<Sensitive<String>>,
pub fee_key_file: Option<String>,
pub fee_key: Option<String>,
pub fee_key: Option<Sensitive<String>>,
#[serde(default)]
pub automatic_reactivate: bool,
}

impl Debug for ValidatorSettings {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ValidatorSettings")
.field("validator_address", &self.validator_address)
.field("signing_key_file", &self.signing_key_file)
.field("signing_key", &self.signing_key.as_ref().map(|_| "***"))
.field("voting_key_file", &self.voting_key_file)
.field("voting_key", &self.voting_key.as_ref().map(|_| "***"))
.field("fee_key_file", &self.fee_key_file)
.field("fee_key", &self.fee_key.as_ref().map(|_| "***"))
.field("automatic_reactivate", &self.automatic_reactivate)
.finish()
}
}

#[derive(Clone, Debug, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct ZKPSettings {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/extras/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn initialize_rpc_server(
// Configure RPC server
let basic_auth = config.credentials.map(|credentials| Credentials {
username: credentials.username,
password: credentials.password,
password: credentials.password.0,
});

let allowed_methods = config.allowed_methods.unwrap_or_default();
Expand Down
7 changes: 6 additions & 1 deletion spammer/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
collections::VecDeque,
ops::Deref,
path::PathBuf,
str::FromStr,
sync::{Arc, RwLock},
Expand Down Expand Up @@ -181,7 +182,11 @@ async fn main_inner() -> Result<(), Error> {
let private_key = match config.network_id {
NetworkId::UnitAlbatross => UNIT_KEY,
// First try to get it from the "fee_key" field in the config file, if that's not set, then use the hardcoded default.
NetworkId::DevAlbatross => validator_settings.fee_key.as_deref().unwrap_or(DEV_KEY),
NetworkId::DevAlbatross => validator_settings
.fee_key
.as_deref()
.map(Deref::deref)
.unwrap_or(DEV_KEY),
_ => panic!("Unsupported network"),
};

Expand Down
3 changes: 2 additions & 1 deletion utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod tagged_signing;
#[cfg(feature = "time")]
pub mod time;

mod sensitive;
mod waker;

pub use self::waker::WakerExt;
pub use self::{sensitive::Sensitive, waker::WakerExt};
52 changes: 52 additions & 0 deletions utils/src/sensitive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::{
fmt,
ops::{Deref, DerefMut},
};

use serde::{
de::{Deserialize, Deserializer},
ser::{Serialize, Serializer},
};

#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Sensitive<T>(pub T);

impl<T> fmt::Debug for Sensitive<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("***")
}
}

impl<T, U: ?Sized> AsRef<U> for Sensitive<T>
where
T: AsRef<U>,
{
fn as_ref(&self) -> &U {
self.0.as_ref()
}
}

impl<T> Deref for Sensitive<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}

impl<T> DerefMut for Sensitive<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Sensitive<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Sensitive<T>, D::Error> {
T::deserialize(deserializer).map(Sensitive)
}
}

impl<T: Serialize> Serialize for Sensitive<T> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.serialize(serializer)
}
}

0 comments on commit 7c6a928

Please sign in to comment.