Skip to content

Commit

Permalink
Associate file name to config errors
Browse files Browse the repository at this point in the history
  • Loading branch information
progval authored and spb committed Aug 25, 2023
1 parent 0b98196 commit e569418
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 30 deletions.
14 changes: 10 additions & 4 deletions sable_network/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Context;
use serde::Deserialize;
use std::{fs::File, io::BufReader, path::PathBuf};

Expand All @@ -17,21 +18,26 @@ pub struct TlsData {

impl TlsConfig {
pub fn load_from_disk(&self) -> Result<TlsData, anyhow::Error> {
let cert_file = File::open(&self.cert_file)?;
let cert_file = File::open(&self.cert_file)
.with_context(|| format!("Could not open certificate {}", self.cert_file.display()))?;
let mut cert_reader = BufReader::new(cert_file);
let cert_chain = rustls_pemfile::certs(&mut cert_reader)?;
let cert_chain = rustls_pemfile::certs(&mut cert_reader)
.with_context(|| format!("Could not parse certificate {}", self.cert_file.display()))?;

let key_file = File::open(&self.key_file)?;
let key_file = File::open(&self.key_file)
.with_context(|| format!("Could not open private key {}", self.key_file.display()))?;
let mut key_reader = BufReader::new(key_file);

let server_key = rustls_pemfile::read_one(&mut key_reader)?;
let server_key = rustls_pemfile::read_one(&mut key_reader)
.with_context(|| format!("Could not parse private key {}", self.key_file.display()))?;

use rustls_pemfile::Item;

let server_key = match server_key {
Some(Item::RSAKey(key)) | Some(Item::PKCS8Key(key)) => Ok(key),
Some(Item::X509Certificate(_)) | None => Err(ConfigError::FormatError(
"No private key in file".to_string(),
self.key_file.clone(),
)),
}?;

Expand Down
68 changes: 44 additions & 24 deletions sable_network/src/sync/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,62 +36,82 @@ pub struct NodeConfig {
/// Errors that could happen when loading or processing a config
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
#[error("JSON parse error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("Invalid address specifier: {0}")]
AddrParseError(#[from] std::net::AddrParseError),
#[error("{0}")]
FormatError(String),
#[error("Missing field: {0}")]
MissingField(String),
#[error("I/O error on {1}: {0}")]
IoError(std::io::Error, PathBuf),
#[error("JSON parse error in {1}: {0}")]
JsonError(serde_json::Error, PathBuf),
#[error("Invalid address specifier in {1}: {0}")]
AddrParseError(std::net::AddrParseError, PathBuf),
#[error("{1}: {0}")]
FormatError(String, PathBuf),
#[error("Missing field {0} in {1}")]
MissingField(String, PathBuf),
}

impl SyncConfig {
/// Load the network configuration from a given file path
pub fn load_file<P: AsRef<Path>>(filename: P) -> Result<Self, ConfigError> {
let file = File::open(filename)?;
pub fn load_file<P: AsRef<Path> + Copy>(filename: P) -> Result<Self, ConfigError> {
let file = File::open(filename)
.map_err(|e| ConfigError::IoError(e, filename.as_ref().to_owned()))?;
let reader = BufReader::new(file);
Ok(serde_json::from_reader(reader)?)
Ok(serde_json::from_reader(reader)
.map_err(|e| ConfigError::JsonError(e, filename.as_ref().to_owned()))?)
}

/// Load and return the CA certificate for the network from the referenced
/// file path
pub fn load_ca_cert(&self) -> Result<Certificate, ConfigError> {
let ca_file = File::open(&self.ca_file)?;
let ca_file =
File::open(&self.ca_file).map_err(|e| ConfigError::IoError(e, self.ca_file.clone()))?;
let mut ca_reader = BufReader::new(ca_file);
let ca_data = rustls_pemfile::certs(&mut ca_reader)?
let ca_data = rustls_pemfile::certs(&mut ca_reader)
.map_err(|e| ConfigError::IoError(e, self.ca_file.clone()))?
.pop()
.ok_or_else(|| ConfigError::FormatError("No certificate in CA file".to_string()))?;
.ok_or_else(|| {
ConfigError::FormatError(
"No certificate in CA file".to_string(),
self.ca_file.clone(),
)
})?;

Ok(Certificate(ca_data))
}
}

impl NodeConfig {
/// Load the node configuration from a given file path
pub fn load_file<P: AsRef<Path>>(filename: P) -> Result<Self, ConfigError> {
let file = File::open(filename)?;
pub fn load_file<P: AsRef<Path> + Copy>(filename: P) -> Result<Self, ConfigError> {
let file = File::open(filename)
.map_err(|e| ConfigError::IoError(e, filename.as_ref().to_owned()))?;
let reader = BufReader::new(file);
Ok(serde_json::from_reader(reader)?)
Ok(serde_json::from_reader(reader)
.map_err(|e| ConfigError::JsonError(e, filename.as_ref().to_owned()))?)
}

/// Load and return the client certificate and private key for this node
/// from the referenced file path
pub fn load_cert_and_keys(&self) -> Result<(Vec<Certificate>, PrivateKey), ConfigError> {
let cert_file = File::open(&self.cert_file)?;
let cert_file = File::open(&self.cert_file)
.map_err(|e| ConfigError::IoError(e, self.cert_file.clone()))?;
let mut cert_reader = BufReader::new(cert_file);
let cert_chain = rustls_pemfile::certs(&mut cert_reader)?
let cert_chain = rustls_pemfile::certs(&mut cert_reader)
.map_err(|e| ConfigError::IoError(e, self.cert_file.clone()))?
.into_iter()
.map(Certificate)
.collect();

let key_file = File::open(&self.key_file)?;
let key_file = File::open(&self.key_file)
.map_err(|e| ConfigError::IoError(e, self.key_file.clone()))?;
let mut key_reader = BufReader::new(key_file);
let client_key = rustls_pemfile::rsa_private_keys(&mut key_reader)?
let client_key = rustls_pemfile::rsa_private_keys(&mut key_reader)
.map_err(|e| ConfigError::IoError(e, self.key_file.clone()))?
.pop()
.ok_or_else(|| ConfigError::FormatError("No private key in file".to_string()))?;
.ok_or_else(|| {
ConfigError::FormatError(
"No private key in file".to_string(),
self.key_file.clone(),
)
})?;

Ok((cert_chain, PrivateKey(client_key)))
}
Expand Down
7 changes: 5 additions & 2 deletions sable_server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,12 @@ impl ManagementConfig {
pub fn load_network_config(
filename: impl AsRef<Path>,
) -> Result<sable_network::network::config::NetworkConfig, sable_network::sync::ConfigError> {
let file = File::open(filename)?;
let file = File::open(filename.as_ref())
.map_err(|e| sable_network::sync::ConfigError::IoError(e, filename.as_ref().to_owned()))?;
let reader = BufReader::new(file);
Ok(serde_json::from_reader(reader)?)
Ok(serde_json::from_reader(reader).map_err(|e| {
sable_network::sync::ConfigError::JsonError(e, filename.as_ref().to_owned())
})?)
}

impl From<LogLevel> for LevelFilter {
Expand Down

0 comments on commit e569418

Please sign in to comment.