mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2025-06-11 02:43:20 +02:00
Switch out anyhow for miette
This commit is contained in:
@ -12,6 +12,7 @@ use std::future::Future;
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
use miette::IntoDiagnostic;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::Duration;
|
||||
|
||||
@ -110,11 +111,11 @@ static ROOT_CERTS: Lazy<RootCertStore> = Lazy::new(|| {
|
||||
store
|
||||
});
|
||||
|
||||
pub fn load(executor: Executor, config: &Config, resources: ResourcesHandle) -> anyhow::Result<()> {
|
||||
pub fn load(executor: Executor, config: &Config, resources: ResourcesHandle) -> miette::Result<()> {
|
||||
let span = tracing::info_span!("loading actors");
|
||||
let _guard = span;
|
||||
|
||||
let mqtt_url = Url::parse(config.mqtt_url.as_str())?;
|
||||
let mqtt_url = Url::parse(config.mqtt_url.as_str()).into_diagnostic()?;
|
||||
let (transport, default_port) = match mqtt_url.scheme() {
|
||||
"mqtts" | "ssl" => (
|
||||
rumqttc::Transport::tls_with_config(
|
||||
@ -131,12 +132,12 @@ pub fn load(executor: Executor, config: &Config, resources: ResourcesHandle) ->
|
||||
|
||||
scheme => {
|
||||
tracing::error!(%scheme, "MQTT url uses invalid scheme");
|
||||
anyhow::bail!("invalid config");
|
||||
miette::bail!("invalid config");
|
||||
}
|
||||
};
|
||||
let host = mqtt_url.host_str().ok_or_else(|| {
|
||||
tracing::error!("MQTT url must contain a hostname");
|
||||
anyhow::anyhow!("invalid config")
|
||||
miette::miette!("invalid config")
|
||||
})?;
|
||||
let port = mqtt_url.port().unwrap_or(default_port);
|
||||
|
||||
@ -167,7 +168,7 @@ pub fn load(executor: Executor, config: &Config, resources: ResourcesHandle) ->
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::error!(?error, "MQTT connection failed");
|
||||
anyhow::bail!("mqtt connection failed")
|
||||
miette::bail!("mqtt connection failed")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::users::Users;
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use rsasl::error::SessionError;
|
||||
use rsasl::mechname::Mechname;
|
||||
use rsasl::property::{AuthId, Password};
|
||||
@ -127,8 +128,13 @@ impl AuthenticationHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self, mechanism: &Mechname) -> anyhow::Result<Session> {
|
||||
Ok(self.inner.rsasl.server_start(mechanism)?)
|
||||
pub fn start(&self, mechanism: &Mechname) -> miette::Result<Session> {
|
||||
Ok(self
|
||||
.inner
|
||||
.rsasl
|
||||
.server_start(mechanism)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to start a SASL authentication with the given mechanism")?)
|
||||
}
|
||||
|
||||
pub fn list_available_mechs(&self) -> impl IntoIterator<Item = &Mechname> {
|
||||
|
@ -95,7 +95,7 @@ impl Roles {
|
||||
|
||||
pub fn is_permitted(&self, user: &UserData, perm: impl AsRef<Permission>) -> bool {
|
||||
let perm = perm.as_ref();
|
||||
tracing::debug!(perm=perm.as_str(), "Checking permission");
|
||||
tracing::debug!(perm = perm.as_str(), "Checking permission");
|
||||
let mut seen = HashSet::new();
|
||||
for role_id in user.roles.iter() {
|
||||
if self.permitted_tally(&mut seen, role_id, perm.as_ref()) {
|
||||
|
@ -60,7 +60,7 @@ impl APIServer {
|
||||
acceptor: TlsAcceptor,
|
||||
sessionmanager: SessionManager,
|
||||
authentication: AuthenticationHandle,
|
||||
) -> anyhow::Result<Self> {
|
||||
) -> miette::Result<Self> {
|
||||
let span = tracing::info_span!("binding API listen sockets");
|
||||
let _guard = span.enter();
|
||||
|
||||
|
@ -1,7 +1,81 @@
|
||||
use thiserror::Error;
|
||||
|
||||
mod raw;
|
||||
|
||||
use miette::{Diagnostic, LabeledSpan, Severity, SourceCode};
|
||||
pub use raw::RawDB;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
mod typed;
|
||||
pub use typed::{Adapter, AlignedAdapter, ArchivedValue, DB};
|
||||
|
||||
pub type Error = lmdb::Error;
|
||||
pub type ErrorO = lmdb::Error;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Error)]
|
||||
#[error(transparent)]
|
||||
pub struct Error(#[from] lmdb::Error);
|
||||
|
||||
impl Diagnostic for Error {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
Some(Box::new(match self.0 {
|
||||
lmdb::Error::KeyExist => "bffh::db::raw::key_exists".to_string(),
|
||||
lmdb::Error::NotFound => "bffh::db::raw::not_found".to_string(),
|
||||
lmdb::Error::PageNotFound => "bffh::db::raw::page_not_found".to_string(),
|
||||
lmdb::Error::Corrupted => "bffh::db::raw::corrupted".to_string(),
|
||||
lmdb::Error::Panic => "bffh::db::raw::panic".to_string(),
|
||||
lmdb::Error::VersionMismatch => "bffh::db::raw::version_mismatch".to_string(),
|
||||
lmdb::Error::Invalid => "bffh::db::raw::invalid".to_string(),
|
||||
lmdb::Error::MapFull => "bffh::db::raw::map_full".to_string(),
|
||||
lmdb::Error::DbsFull => "bffh::db::raw::dbs_full".to_string(),
|
||||
lmdb::Error::ReadersFull => "bffh::db::raw::readers_full".to_string(),
|
||||
lmdb::Error::TlsFull => "bffh::db::raw::tls_full".to_string(),
|
||||
lmdb::Error::TxnFull => "bffh::db::raw::txn_full".to_string(),
|
||||
lmdb::Error::CursorFull => "bffh::db::raw::cursor_full".to_string(),
|
||||
lmdb::Error::PageFull => "bffh::db::raw::page_full".to_string(),
|
||||
lmdb::Error::MapResized => "bffh::db::raw::map_resized".to_string(),
|
||||
lmdb::Error::Incompatible => "bffh::db::raw::incompatible".to_string(),
|
||||
lmdb::Error::BadRslot => "bffh::db::raw::bad_rslot".to_string(),
|
||||
lmdb::Error::BadTxn => "bffh::db::raw::bad_txn".to_string(),
|
||||
lmdb::Error::BadValSize => "bffh::db::raw::bad_val_size".to_string(),
|
||||
lmdb::Error::BadDbi => "bffh::db::raw::bad_dbi".to_string(),
|
||||
lmdb::Error::Other(n) => format!("bffh::db::raw::e{}", n),
|
||||
}))
|
||||
}
|
||||
|
||||
fn severity(&self) -> Option<Severity> {
|
||||
Some(Severity::Error)
|
||||
}
|
||||
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
match self.0 {
|
||||
lmdb::Error::KeyExist => Some(Box::new("The provided key already exists in the database")),
|
||||
lmdb::Error::NotFound => Some(Box::new("The requested key was not found in the database")),
|
||||
lmdb::Error::PageNotFound => Some(Box::new("The requested page was not found. This usually indicates corruption.")),
|
||||
lmdb::Error::Corrupted => None,
|
||||
lmdb::Error::Panic => None,
|
||||
lmdb::Error::VersionMismatch => None,
|
||||
lmdb::Error::Invalid => None,
|
||||
lmdb::Error::MapFull => None,
|
||||
lmdb::Error::DbsFull => None,
|
||||
lmdb::Error::ReadersFull => None,
|
||||
lmdb::Error::TlsFull => None,
|
||||
lmdb::Error::TxnFull => None,
|
||||
lmdb::Error::CursorFull => None,
|
||||
lmdb::Error::PageFull => None,
|
||||
lmdb::Error::MapResized => None,
|
||||
lmdb::Error::Incompatible => None,
|
||||
lmdb::Error::BadRslot => Some(Box::new("This usually indicates that the operation can't complete because an incompatible transaction is still open.")),
|
||||
lmdb::Error::BadTxn => None,
|
||||
lmdb::Error::BadValSize => None,
|
||||
lmdb::Error::BadDbi => None,
|
||||
lmdb::Error::Other(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::Result;
|
||||
use lmdb::{DatabaseFlags, Environment, RwTransaction, Transaction, WriteFlags};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -142,11 +142,11 @@ impl<A: Adapter> DB<A> {
|
||||
}
|
||||
|
||||
pub fn del(&self, txn: &mut RwTransaction, key: &impl AsRef<[u8]>) -> Result<(), db::Error> {
|
||||
self.db.del::<_, &[u8]>(txn, key, None)
|
||||
Ok(self.db.del::<_, &[u8]>(txn, key, None)?)
|
||||
}
|
||||
|
||||
pub fn clear(&self, txn: &mut RwTransaction) -> Result<(), db::Error> {
|
||||
self.db.clear(txn)
|
||||
Ok(self.db.clear(txn)?)
|
||||
}
|
||||
|
||||
pub fn get_all<'txn, T: Transaction>(
|
||||
|
160
bffhd/error.rs
160
bffhd/error.rs
@ -1,74 +1,116 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::db;
|
||||
use rsasl::error::SessionError;
|
||||
use std::any::TypeId;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::fmt::Display;
|
||||
use std::io;
|
||||
|
||||
type DBError = db::Error;
|
||||
use crate::resources::state::db::StateDBError;
|
||||
use backtrace::{Backtrace, BacktraceFmt, PrintFmt};
|
||||
use miette::{Diagnostic, LabeledSpan, Severity, SourceCode};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TracedError<E: Diagnostic> {
|
||||
pub inner: E,
|
||||
pub backtrace: Backtrace,
|
||||
}
|
||||
|
||||
impl<E: Diagnostic> fmt::Display for TracedError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "Error: {}", self.inner)?;
|
||||
|
||||
let cwd = std::env::current_dir();
|
||||
let mut print_path =
|
||||
move |fmt: &mut fmt::Formatter<'_>, path: backtrace::BytesOrWideString<'_>| {
|
||||
let path = path.into_path_buf();
|
||||
if let Ok(cwd) = &cwd {
|
||||
if let Ok(suffix) = path.strip_prefix(cwd) {
|
||||
return fmt::Display::fmt(&suffix.display(), fmt);
|
||||
}
|
||||
}
|
||||
fmt::Display::fmt(&path.display(), fmt)
|
||||
};
|
||||
let mut bf = BacktraceFmt::new(f, PrintFmt::Short, &mut print_path);
|
||||
bf.add_context()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: 'static + Diagnostic> StdError for TracedError<E> {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
self.inner.source()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: 'static + Diagnostic> Diagnostic for TracedError<E> {
|
||||
#[inline(always)]
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.inner.code()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn severity(&self) -> Option<Severity> {
|
||||
self.inner.severity()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.inner.help()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||
self.inner.url()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn source_code(&self) -> Option<&dyn SourceCode> {
|
||||
self.inner.source_code()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
|
||||
self.inner.labels()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
|
||||
self.inner.related()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn diagnostic_source(&self) -> Option<&dyn Diagnostic> {
|
||||
self.inner.diagnostic_source()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
/// Shared error type
|
||||
pub enum Error {
|
||||
pub enum BffhError {
|
||||
#[error("SASL error: {0:?}")]
|
||||
SASL(SessionError),
|
||||
IO(io::Error),
|
||||
Boxed(Box<dyn std::error::Error>),
|
||||
Capnp(capnp::Error),
|
||||
DB(DBError),
|
||||
#[error("IO error: {0}")]
|
||||
IO(#[from] io::Error),
|
||||
#[error("IO error: {0}")]
|
||||
Boxed(#[from] Box<dyn std::error::Error>),
|
||||
#[error("IO error: {0}")]
|
||||
Capnp(#[from] capnp::Error),
|
||||
#[error("IO error: {0}")]
|
||||
DB(#[from] db::Error),
|
||||
#[error("You do not have the permission required to do that.")]
|
||||
Denied,
|
||||
#[error("State DB operation failed")]
|
||||
StateDB(#[from] StateDBError),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::SASL(e) => {
|
||||
write!(f, "SASL Error: {}", e)
|
||||
}
|
||||
Error::IO(e) => {
|
||||
write!(f, "IO Error: {}", e)
|
||||
}
|
||||
Error::Boxed(e) => {
|
||||
write!(f, "{}", e)
|
||||
}
|
||||
Error::Capnp(e) => {
|
||||
write!(f, "Cap'n Proto Error: {}", e)
|
||||
}
|
||||
Error::DB(e) => {
|
||||
write!(f, "DB Error: {:?}", e)
|
||||
}
|
||||
Error::Denied => {
|
||||
write!(f, "You do not have the permission required to do that.")
|
||||
}
|
||||
}
|
||||
impl From<SessionError> for BffhError {
|
||||
fn from(e: SessionError) -> Self {
|
||||
Self::SASL(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SessionError> for Error {
|
||||
fn from(e: SessionError) -> Error {
|
||||
Error::SASL(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Error {
|
||||
Error::IO(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<dyn std::error::Error>> for Error {
|
||||
fn from(e: Box<dyn std::error::Error>) -> Error {
|
||||
Error::Boxed(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<capnp::Error> for Error {
|
||||
fn from(e: capnp::Error) -> Error {
|
||||
Error::Capnp(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DBError> for Error {
|
||||
fn from(e: DBError) -> Error {
|
||||
Error::DB(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
pub type Result<T> = std::result::Result<T, BffhError>;
|
||||
|
26
bffhd/lib.rs
26
bffhd/lib.rs
@ -42,9 +42,8 @@ mod tls;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
use futures_util::StreamExt;
|
||||
use miette::{Context, IntoDiagnostic, Report};
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::audit::AuditLog;
|
||||
@ -75,7 +74,7 @@ pub struct Diflouroborane {
|
||||
pub static RESOURCES: OnceCell<ResourcesHandle> = OnceCell::new();
|
||||
|
||||
impl Diflouroborane {
|
||||
pub fn new(config: Config) -> anyhow::Result<Self> {
|
||||
pub fn new(config: Config) -> miette::Result<Self> {
|
||||
logging::init(&config.logging);
|
||||
tracing::info!(version = env::VERSION, "Starting BFFH");
|
||||
|
||||
@ -84,15 +83,16 @@ impl Diflouroborane {
|
||||
|
||||
let executor = Executor::new();
|
||||
|
||||
let env = StateDB::open_env(&config.db_path)
|
||||
.context("Failed to create state DB env. Does the parent directory for `db_path` exist?")?;
|
||||
let statedb =
|
||||
StateDB::create_with_env(env.clone()).context("Failed to open state DB file")?;
|
||||
let env = StateDB::open_env(&config.db_path)?;
|
||||
|
||||
let users = Users::new(env.clone()).context("Failed to open users DB file")?;
|
||||
let statedb = StateDB::create_with_env(env.clone())?;
|
||||
|
||||
let users = Users::new(env.clone())?;
|
||||
let roles = Roles::new(config.roles.clone());
|
||||
|
||||
let _audit_log = AuditLog::new(&config).context("Failed to initialize audit log")?;
|
||||
let _audit_log = AuditLog::new(&config)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to initialize audit log")?;
|
||||
|
||||
let resources = ResourcesHandle::new(config.machines.iter().map(|(id, desc)| {
|
||||
Resource::new(Arc::new(resources::Inner::new(
|
||||
@ -113,13 +113,15 @@ impl Diflouroborane {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> anyhow::Result<()> {
|
||||
pub fn run(&mut self) -> miette::Result<()> {
|
||||
let mut signals = signal_hook_async_std::Signals::new(&[SIGINT, SIGQUIT, SIGTERM])
|
||||
.context("Failed to construct signal handler")?;
|
||||
.into_diagnostic()
|
||||
.wrap_err("Failed to construct signal handler")?;
|
||||
|
||||
actors::load(self.executor.clone(), &self.config, self.resources.clone())?;
|
||||
|
||||
let tlsconfig = TlsConfig::new(self.config.tlskeylog.as_ref(), !self.config.is_quiet())?;
|
||||
let tlsconfig = TlsConfig::new(self.config.tlskeylog.as_ref(), !self.config.is_quiet())
|
||||
.into_diagnostic()?;
|
||||
let acceptor = tlsconfig.make_tls_acceptor(&self.config.tlsconfig)?;
|
||||
|
||||
let sessionmanager = SessionManager::new(self.users.clone(), self.roles.clone());
|
||||
|
@ -1,6 +1,12 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::db;
|
||||
use crate::db::{AlignedAdapter, ArchivedValue, RawDB, DB};
|
||||
use lmdb::{DatabaseFlags, Environment, EnvironmentFlags, Transaction, WriteFlags};
|
||||
use miette::{Diagnostic, LabeledSpan, Severity, SourceCode};
|
||||
use std::any::TypeId;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
use crate::resources::state::State;
|
||||
@ -11,8 +17,24 @@ pub struct StateDB {
|
||||
db: DB<AlignedAdapter<State>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
pub enum StateDBError {
|
||||
#[error("opening the state db environment failed")]
|
||||
#[diagnostic(
|
||||
code(bffh::db::state::open_env),
|
||||
help("does the parent directory for state_db exist?")
|
||||
)]
|
||||
OpenEnv(#[source] db::Error),
|
||||
#[error("opening the state db failed")]
|
||||
#[diagnostic(code(bffh::db::state::open))]
|
||||
Open(#[source] db::Error),
|
||||
#[error("creating the state db failed")]
|
||||
#[diagnostic(code(bffh::db::state::create))]
|
||||
Create(#[source] db::Error),
|
||||
}
|
||||
|
||||
impl StateDB {
|
||||
pub fn open_env<P: AsRef<Path>>(path: P) -> lmdb::Result<Arc<Environment>> {
|
||||
pub fn open_env<P: AsRef<Path>>(path: P) -> Result<Arc<Environment>, StateDBError> {
|
||||
Environment::new()
|
||||
.set_flags(
|
||||
EnvironmentFlags::WRITE_MAP
|
||||
@ -23,6 +45,7 @@ impl StateDB {
|
||||
.set_max_dbs(8)
|
||||
.open(path.as_ref())
|
||||
.map(Arc::new)
|
||||
.map_err(|e| StateDBError::OpenEnv(e.into()))
|
||||
}
|
||||
|
||||
fn new(env: Arc<Environment>, db: RawDB) -> Self {
|
||||
@ -30,30 +53,32 @@ impl StateDB {
|
||||
Self { env, db }
|
||||
}
|
||||
|
||||
pub fn open_with_env(env: Arc<Environment>) -> lmdb::Result<Self> {
|
||||
let db = unsafe { RawDB::open(&env, Some("state"))? };
|
||||
pub fn open_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
||||
let db = unsafe { RawDB::open(&env, Some("state")) };
|
||||
let db = db.map_err(|e| StateDBError::Open(e.into()))?;
|
||||
Ok(Self::new(env, db))
|
||||
}
|
||||
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> lmdb::Result<Self> {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, StateDBError> {
|
||||
let env = Self::open_env(path)?;
|
||||
Self::open_with_env(env)
|
||||
}
|
||||
|
||||
pub fn create_with_env(env: Arc<Environment>) -> lmdb::Result<Self> {
|
||||
pub fn create_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
||||
let flags = DatabaseFlags::empty();
|
||||
let db = unsafe { RawDB::create(&env, Some("state"), flags)? };
|
||||
let db = unsafe { RawDB::create(&env, Some("state"), flags) };
|
||||
let db = db.map_err(|e| StateDBError::Create(e.into()))?;
|
||||
|
||||
Ok(Self::new(env, db))
|
||||
}
|
||||
|
||||
pub fn create<P: AsRef<Path>>(path: P) -> lmdb::Result<Self> {
|
||||
pub fn create<P: AsRef<Path>>(path: P) -> Result<Self, StateDBError> {
|
||||
let env = Self::open_env(path)?;
|
||||
Self::create_with_env(env)
|
||||
}
|
||||
|
||||
pub fn begin_ro_txn(&self) -> Result<impl Transaction + '_, db::Error> {
|
||||
self.env.begin_ro_txn()
|
||||
self.env.begin_ro_txn().map_err(db::Error::from)
|
||||
}
|
||||
|
||||
pub fn get(&self, key: impl AsRef<[u8]>) -> Result<Option<ArchivedValue<State>>, db::Error> {
|
||||
@ -72,7 +97,7 @@ impl StateDB {
|
||||
let mut txn = self.env.begin_rw_txn()?;
|
||||
let flags = WriteFlags::empty();
|
||||
self.db.put(&mut txn, key, val, flags)?;
|
||||
txn.commit()
|
||||
Ok(txn.commit()?)
|
||||
}
|
||||
}
|
||||
|
||||
|
22
bffhd/tls.rs
22
bffhd/tls.rs
@ -6,6 +6,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::capnp::TlsListen;
|
||||
use futures_rustls::TlsAcceptor;
|
||||
use miette::IntoDiagnostic;
|
||||
use rustls::version::{TLS12, TLS13};
|
||||
use rustls::{Certificate, PrivateKey, ServerConfig, SupportedCipherSuite};
|
||||
use tracing::Level;
|
||||
@ -74,26 +75,27 @@ impl TlsConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_tls_acceptor(&self, config: &TlsListen) -> anyhow::Result<TlsAcceptor> {
|
||||
pub fn make_tls_acceptor(&self, config: &TlsListen) -> miette::Result<TlsAcceptor> {
|
||||
let span = tracing::debug_span!("tls");
|
||||
let _guard = span.enter();
|
||||
|
||||
tracing::debug!(path = %config.certfile.as_path().display(), "reading certificates");
|
||||
let mut certfp = BufReader::new(File::open(config.certfile.as_path())?);
|
||||
let certs = rustls_pemfile::certs(&mut certfp)?
|
||||
let mut certfp = BufReader::new(File::open(config.certfile.as_path()).into_diagnostic()?);
|
||||
let certs = rustls_pemfile::certs(&mut certfp)
|
||||
.into_diagnostic()?
|
||||
.into_iter()
|
||||
.map(Certificate)
|
||||
.collect();
|
||||
|
||||
tracing::debug!(path = %config.keyfile.as_path().display(), "reading private key");
|
||||
let mut keyfp = BufReader::new(File::open(config.keyfile.as_path())?);
|
||||
let key = match rustls_pemfile::read_one(&mut keyfp)? {
|
||||
let mut keyfp = BufReader::new(File::open(config.keyfile.as_path()).into_diagnostic()?);
|
||||
let key = match rustls_pemfile::read_one(&mut keyfp).into_diagnostic()? {
|
||||
Some(rustls_pemfile::Item::PKCS8Key(key) | rustls_pemfile::Item::RSAKey(key)) => {
|
||||
PrivateKey(key)
|
||||
}
|
||||
_ => {
|
||||
tracing::error!("private key file invalid");
|
||||
anyhow::bail!("private key file must contain a PEM-encoded private key")
|
||||
miette::bail!("private key file must contain a PEM-encoded private key")
|
||||
}
|
||||
};
|
||||
|
||||
@ -105,15 +107,17 @@ impl TlsConfig {
|
||||
match min.as_str() {
|
||||
"tls12" => tls_builder.with_protocol_versions(&[&TLS12]),
|
||||
"tls13" => tls_builder.with_protocol_versions(&[&TLS13]),
|
||||
x => anyhow::bail!("TLS version {} is invalid", x),
|
||||
x => miette::bail!("TLS version {} is invalid", x),
|
||||
}
|
||||
} else {
|
||||
tls_builder.with_safe_default_protocol_versions()
|
||||
}?;
|
||||
}
|
||||
.into_diagnostic()?;
|
||||
|
||||
let mut tls_config = tls_builder
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, key)?;
|
||||
.with_single_cert(certs, key)
|
||||
.into_diagnostic()?;
|
||||
|
||||
if let Some(keylog) = &self.keylog {
|
||||
tls_config.key_log = keylog.clone();
|
||||
|
@ -2,7 +2,7 @@ use lmdb::{DatabaseFlags, Environment, RwTransaction, Transaction, WriteFlags};
|
||||
use rkyv::Infallible;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Context;
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::db;
|
||||
@ -28,9 +28,11 @@ pub struct User {
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn check_password(&self, pwd: &[u8]) -> anyhow::Result<bool> {
|
||||
pub fn check_password(&self, pwd: &[u8]) -> miette::Result<bool> {
|
||||
if let Some(ref encoded) = self.userdata.passwd {
|
||||
argon2::verify_encoded(encoded, pwd).context("Stored password is an invalid string")
|
||||
argon2::verify_encoded(encoded, pwd)
|
||||
.into_diagnostic()
|
||||
.wrap_err("Stored password is an invalid string")
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
@ -109,7 +111,7 @@ impl UserDB {
|
||||
// TODO: Make an userdb-specific Transaction newtype to make this safe
|
||||
pub unsafe fn get_rw_txn(&self) -> Result<RwTransaction, db::Error> {
|
||||
// The returned transaction is only valid for *this* environment.
|
||||
self.env.begin_rw_txn()
|
||||
Ok(self.env.begin_rw_txn()?)
|
||||
}
|
||||
|
||||
pub unsafe fn new(env: Arc<Environment>, db: RawDB) -> Self {
|
||||
|
@ -1,10 +1,10 @@
|
||||
use anyhow::Context;
|
||||
use lmdb::{Environment, Transaction};
|
||||
use once_cell::sync::OnceCell;
|
||||
use rkyv::{Archive, Deserialize, Infallible, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter, Write};
|
||||
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -65,7 +65,7 @@ pub struct Users {
|
||||
}
|
||||
|
||||
impl Users {
|
||||
pub fn new(env: Arc<Environment>) -> anyhow::Result<Self> {
|
||||
pub fn new(env: Arc<Environment>) -> miette::Result<Self> {
|
||||
let span = tracing::debug_span!("users", ?env, "Creating Users handle");
|
||||
let _guard = span.enter();
|
||||
|
||||
@ -74,7 +74,7 @@ impl Users {
|
||||
tracing::debug!("Global resource not yet initialized, initializing…");
|
||||
unsafe { UserDB::create(env) }
|
||||
})
|
||||
.context("Failed to open userdb")?;
|
||||
.wrap_err("Failed to open userdb")?;
|
||||
|
||||
Ok(Self { userdb })
|
||||
}
|
||||
@ -90,19 +90,19 @@ impl Users {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn put_user(&self, uid: &str, user: &db::User) -> Result<(), lmdb::Error> {
|
||||
pub fn put_user(&self, uid: &str, user: &db::User) -> Result<(), crate::db::Error> {
|
||||
tracing::trace!(uid, ?user, "Updating user");
|
||||
self.userdb.put(uid, user)
|
||||
}
|
||||
|
||||
pub fn del_user(&self, uid: &str) -> Result<(), lmdb::Error> {
|
||||
pub fn del_user(&self, uid: &str) -> Result<(), crate::db::Error> {
|
||||
tracing::trace!(uid, "Deleting user");
|
||||
self.userdb.delete(uid)
|
||||
}
|
||||
|
||||
pub fn load_file<P: AsRef<Path>>(&self, path: P) -> anyhow::Result<()> {
|
||||
let f = std::fs::read(path)?;
|
||||
let map: HashMap<String, UserData> = toml::from_slice(&f)?;
|
||||
pub fn load_file<P: AsRef<Path>>(&self, path: P) -> miette::Result<()> {
|
||||
let f = std::fs::read(path).into_diagnostic()?;
|
||||
let map: HashMap<String, UserData> = toml::from_slice(&f).into_diagnostic()?;
|
||||
|
||||
let mut txn = unsafe { self.userdb.get_rw_txn()? };
|
||||
|
||||
@ -132,7 +132,7 @@ impl Users {
|
||||
}
|
||||
}
|
||||
|
||||
txn.commit()?;
|
||||
txn.commit().map_err(crate::db::Error::from)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user