Splitting config

This commit is contained in:
Nadja Reitzenstein 2022-03-20 21:22:15 +01:00
parent 28d90f1078
commit b02afe5575
10 changed files with 137 additions and 74 deletions

View File

@ -56,6 +56,7 @@ ptr_meta = "0.1"
rkyv_typename = "0.7"
rkyv_dyn = "0.7"
inventory = "0.1"
linkme = "0.2.10"
chrono = { version = "0.4", features = ["serde"] }
# Password hashing for internal users
@ -77,7 +78,6 @@ capnp-rpc = "0.14.1"
rsasl = { git = "https://github.com/dequbed/rsasl.git", branch = "main", default_features = false, features = ["unstable_custom_mechanism", "provider", "registry_static", "plain"] }
desfire = "0.2.0-alpha1"
hex = { version = "0.4.3", features = ["serde"] }
linkme = "0.2.10"
futures-signals = "0.3.22"
async-oneshot = "0.5"

59
bffhd/capnp/config.rs Normal file
View File

@ -0,0 +1,59 @@
use std::fmt::Formatter;
use std::net::ToSocketAddrs;
use std::path::PathBuf;
use serde::{Serialize, Deserialize};
use crate::config::deser_option;
#[derive(Debug, Clone, Serialize, Deserialize)]
/// API Socket Configuration block.
///
/// One configuration block can result in several sockets if the given `address` resolves to more
/// than one SocketAddr. BFFH will attempt to bind to all of them.
pub struct Listen {
pub address: String,
#[serde(default, skip_serializing_if = "Option::is_none", deserialize_with = "deser_option")]
pub port: Option<u16>,
}
impl Listen {
pub fn to_tuple(&self) -> (&str, u16) {
(self.address.as_str(), self.port.unwrap_or(DEFAULT_PORT))
}
}
impl std::fmt::Display for Listen {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", &self.address, self.port.unwrap_or(DEFAULT_PORT))
}
}
impl ToSocketAddrs for Listen {
type Iter = <(String, u16) as ToSocketAddrs>::Iter;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
if let Some(port) = self.port {
(self.address.as_str(), port).to_socket_addrs()
} else {
(self.address.as_str(), DEFAULT_PORT).to_socket_addrs()
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TlsListen {
pub certfile: PathBuf,
pub keyfile: PathBuf,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ciphers: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tls_min_version: Option<String>,
#[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")]
pub protocols: Vec<String>,
}
// The default port in the non-assignable i.e. free-use area
pub const DEFAULT_PORT: u16 = 59661;

View File

@ -1,6 +1,3 @@
use crate::config::Listen;
use async_net::TcpListener;
@ -18,13 +15,12 @@ use std::io;
use std::net::SocketAddr;
use crate::authentication::AuthenticationHandle;
use crate::session::SessionManager;
mod config;
pub use config::{Listen, TlsListen};
mod authenticationsystem;
mod connection;
mod machine;

8
bffhd/config/dhall.rs Normal file
View File

@ -0,0 +1,8 @@
use std::path::Path;
use crate::Config;
pub fn read_config_file(path: impl AsRef<Path>) -> Result<Config, serde_dhall::Error> {
serde_dhall::from_file(path)
.parse()
.map_err(Into::into)
}

View File

@ -6,17 +6,23 @@ use serde::{Serialize, Deserialize};
use std::fmt::Formatter;
use std::net::{ToSocketAddrs};
use serde_dhall::{SimpleType};
mod dhall;
pub use dhall::read_config_file as read;
use crate::authorization::permissions::{PrivilegesBuf};
use crate::authorization::roles::Role;
use crate::capnp::{Listen, TlsListen};
use crate::logging::LogConfig;
type Result<T> = std::result::Result<T, serde_dhall::Error>;
pub fn load(path: impl AsRef<Path>, args: &clap::ArgMatches) -> anyhow::Result<Config> {
unimplemented!()
}
pub fn read(path: &Path) -> Result<Config> {
serde_dhall::from_file(path)
.parse()
.map_err(Into::into)
pub struct ConfigBlock {
static_type: SimpleType,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -78,7 +84,7 @@ pub struct Config {
pub verbosity: isize,
#[serde(default, skip)]
pub log_format: String,
pub logging: LogConfig,
}
impl Config {
@ -105,49 +111,6 @@ pub(crate) fn deser_option<'de, D, T>(d: D) -> std::result::Result<Option<T>, D:
Ok(T::deserialize(d).ok())
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Listen {
address: String,
#[serde(default, skip_serializing_if = "Option::is_none", deserialize_with = "deser_option")]
port: Option<u16>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TlsListen {
pub certfile: PathBuf,
pub keyfile: PathBuf,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ciphers: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tls_min_version: Option<String>,
#[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")]
pub protocols: Vec<String>,
}
impl Listen {
pub fn to_tuple(&self) -> (&str, u16) {
(self.address.as_str(), self.port.unwrap_or(DEFAULT_PORT))
}
}
impl std::fmt::Display for Listen {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", &self.address, self.port.unwrap_or(DEFAULT_PORT))
}
}
impl ToSocketAddrs for Listen {
type Iter = <(String, u16) as ToSocketAddrs>::Iter;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
if let Some(port) = self.port {
(self.address.as_str(), port).to_socket_addrs()
} else {
(self.address.as_str(), DEFAULT_PORT).to_socket_addrs()
}
}
}
impl Default for Config {
fn default() -> Self {
@ -194,10 +157,7 @@ impl Default for Config {
tlskeylog: None,
verbosity: 0,
log_format: "Full".to_string(),
logging: LogConfig::default(),
}
}
}
// The default port in the non-assignable i.e. free-use area
pub const DEFAULT_PORT: u16 = 59661;

View File

@ -40,7 +40,6 @@ mod session;
use std::sync::{Arc};
use anyhow::Context;
@ -79,7 +78,7 @@ pub static RESOURCES: OnceCell<ResourcesHandle> = OnceCell::new();
impl Diflouroborane {
pub fn new(config: Config) -> anyhow::Result<Self> {
logging::init(&config);
logging::init(&config.logging);
tracing::info!(version=RELEASE_STRING, "Starting");
let span = tracing::info_span!("setup");

View File

@ -1,16 +1,46 @@
use tracing_subscriber::{EnvFilter};
use crate::Config;
pub fn init(config: &Config) {
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogConfig {
#[serde(default, skip_serializing_if = "Option::is_none")]
/// Log filter string in the tracing format `target[span{field=value}]=level`.
/// lvalue is optional and multiple filters can be combined with comma.
/// e.g. `warn,diflouroborane::actors=debug` will only print `WARN` and `ERROR` unless the
/// message is logged in a span below `diflouroborane::actors` (i.e. by an actor task) in
/// which case `DEBUG` and `INFO` will also be printed.
pub filter: Option<String>,
pub format: String,
}
impl Default for LogConfig {
fn default() -> Self {
Self {
filter: None,
format: "full".to_string(),
}
}
}
pub fn init(config: &LogConfig) {
let filter = if let Some(ref filter) = config.filter {
EnvFilter::new(filter.as_str())
} else {
EnvFilter::from_env("BFFH_LOG")
};
let builder = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env());
let format = config.log_format.to_lowercase();
.with_env_filter(filter);
let format = config.format.to_lowercase();
match format.as_str() {
"compact" => builder.compact().init(),
"pretty" => builder.pretty().init(),
"full" => builder.init(),
_ => builder.init(),
}
tracing::info!(format = format.as_str(), "Logging initialized")
}

View File

@ -9,7 +9,10 @@ use rkyv_dyn::{DynDeserializer, DynError, DynSerializer};
use crate::utils::oid::ObjectIdentifier;
// Not using linkme because dynamically loaded modules
use inventory;
use rkyv::ser::{ScratchSpace, Serializer};
use serde::de::Error as SerdeError;
use serde::ser::SerializeMap;

View File

@ -8,6 +8,7 @@ use futures_rustls::TlsAcceptor;
use rustls::{Certificate, PrivateKey, ServerConfig, SupportedCipherSuite};
use rustls::version::{TLS12, TLS13};
use tracing::{Level};
use crate::capnp::TlsListen;
use crate::config;
use crate::keylog::KeyLogFile;
@ -61,7 +62,7 @@ impl TlsConfig {
}
}
pub fn make_tls_acceptor(&self, config: &config::TlsListen) -> anyhow::Result<TlsAcceptor> {
pub fn make_tls_acceptor(&self, config: &TlsListen) -> anyhow::Result<TlsAcceptor> {
let span = tracing::debug_span!("tls");
let _guard = span.enter();

View File

@ -1,4 +1,4 @@
use clap::{Arg, Command};
use clap::{Arg, Command, Parser};
use diflouroborane::{config, Diflouroborane};
@ -91,16 +91,23 @@ fn main() -> anyhow::Result<()> {
// invalidate the generated TOML
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(&encoded.as_bytes()).unwrap();
handle.write_all(encoded.as_bytes()).unwrap();
// Early return to exit.
return Ok(());
} else if matches.is_present("check config") {
match config::read(&PathBuf::from_str(configpath).unwrap()) {
Ok(c) => {
println!("{:#?}", c);
println!("config is valid");
std::process::exit(0);
let formatted = format!("{:#?}", c);
// Direct writing to fd 1 is faster but also prevents any print-formatting that could
// invalidate the generated TOML
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(formatted.as_bytes()).unwrap();
// Early return to exit.
return Ok(());
}
Err(e) => {
eprintln!("{}", e);
@ -140,7 +147,7 @@ fn main() -> anyhow::Result<()> {
if config.verbosity == 0 && matches.is_present("quiet") {
config.verbosity = -1;
}
config.log_format = matches.value_of("log format").unwrap_or("Full").to_string();
config.logging.format = matches.value_of("log format").unwrap_or("full").to_string();
let mut bffh = Diflouroborane::new(config)?;
bffh.run()?;