Merge branch 'feature/spanned-api-handling' into development

* feature/spanned-api-handling:
  Output plentiful trace info for API calls
  log all api calls with `TRACE` level
  Add a connection-specific span to each API handler
This commit is contained in:
Nadja Reitzenstein 2022-06-24 14:35:41 +02:00
commit e1377d0f79
9 changed files with 358 additions and 45 deletions

View File

@ -1,9 +1,13 @@
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp::Error; use capnp::Error;
use capnp_rpc::pry; use capnp_rpc::pry;
use rsasl::mechname::Mechname;
use rsasl::property::AuthId; use rsasl::property::AuthId;
use rsasl::session::{Session, Step}; use rsasl::session::{Session, Step};
use std::fmt;
use std::fmt::{Formatter, Write};
use std::io::Cursor; use std::io::Cursor;
use tracing::Span;
use crate::capnp::session::APISession; use crate::capnp::session::APISession;
use crate::session::SessionManager; use crate::session::SessionManager;
@ -12,19 +16,46 @@ use api::authenticationsystem_capnp::authentication::{
}; };
use api::authenticationsystem_capnp::{response, response::Error as ErrorCode}; use api::authenticationsystem_capnp::{response, response::Error as ErrorCode};
const TARGET: &str = "bffh::api::authenticationsystem";
pub struct Authentication { pub struct Authentication {
span: Span,
state: State, state: State,
} }
impl Authentication { impl Authentication {
pub fn new(session: Session, sessionmanager: SessionManager) -> Self { pub fn new(
parent: &Span,
mechanism: &Mechname, /* TODO: this is stored in session as well, get it out of there. */
session: Session,
sessionmanager: SessionManager,
) -> Self {
let span = tracing::info_span!(
target: TARGET,
parent: parent,
"Authentication",
mechanism = mechanism.as_str()
);
tracing::trace!(
target: TARGET,
parent: &span,
"constructing valid authentication system"
);
Self { Self {
span,
state: State::Running(session, sessionmanager), state: State::Running(session, sessionmanager),
} }
} }
pub fn invalid_mechanism() -> Self { pub fn invalid_mechanism() -> Self {
let span = tracing::info_span!(target: TARGET, "Authentication",);
tracing::trace!(
target: TARGET,
parent: &span,
"constructing invalid mechanism authentication system"
);
Self { Self {
span,
state: State::InvalidMechanism, state: State::InvalidMechanism,
} }
} }
@ -44,6 +75,19 @@ impl Authentication {
} }
} }
impl fmt::Display for Authentication {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Authentication(")?;
match &self.state {
State::InvalidMechanism => f.write_str("invalid mechanism")?,
State::Finished => f.write_str("finished")?,
State::Aborted => f.write_str("aborted")?,
State::Running(_, _) => f.write_str("running")?,
}
f.write_char(')')
}
}
enum State { enum State {
InvalidMechanism, InvalidMechanism,
Finished, Finished,
@ -53,13 +97,30 @@ enum State {
impl AuthenticationSystem for Authentication { impl AuthenticationSystem for Authentication {
fn step(&mut self, params: StepParams, mut results: StepResults) -> Promise<(), Error> { fn step(&mut self, params: StepParams, mut results: StepResults) -> Promise<(), Error> {
let span = tracing::trace_span!("step"); let _guard = self.span.enter();
let _guard = span.enter(); let _span = tracing::trace_span!(target: TARGET, "step",).entered();
tracing::trace!(params.data = "<authentication data>", "method call");
#[repr(transparent)]
struct Response {
union_field: &'static str,
}
impl fmt::Display for Response {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str("Response(")?;
f.write_str(self.union_field)?;
f.write_char(')')
}
}
let mut response;
let mut builder = results.get(); let mut builder = results.get();
if let State::Running(mut session, manager) = if let State::Running(mut session, manager) =
std::mem::replace(&mut self.state, State::Aborted) std::mem::replace(&mut self.state, State::Aborted)
{ {
let data: &[u8] = pry!(pry!(params.get()).get_data()); let data: &[u8] = pry!(pry!(params.get()).get_data());
let mut out = Cursor::new(Vec::new()); let mut out = Cursor::new(Vec::new());
match session.step(Some(data), &mut out) { match session.step(Some(data), &mut out) {
Ok(Step::Done(data)) => { Ok(Step::Done(data)) => {
@ -71,11 +132,15 @@ impl AuthenticationSystem for Authentication {
"Authentication didn't provide an authid as required".to_string(), "Authentication didn't provide an authid as required".to_string(),
) )
})); }));
let session = pry!(manager.open(uid.as_ref()).ok_or_else(|| { let session = pry!(manager.open(&self.span, uid.as_ref()).ok_or_else(|| {
tracing::warn!(uid = uid.as_str(), "Failed to lookup the given user"); tracing::warn!(uid = uid.as_str(), "Failed to lookup the given user");
capnp::Error::failed("Failed to lookup the given user".to_string()) capnp::Error::failed("Failed to lookup the given user".to_string())
})); }));
response = Response {
union_field: "successful",
};
let mut builder = builder.init_successful(); let mut builder = builder.init_successful();
if data.is_some() { if data.is_some() {
builder.set_additional_data(out.into_inner().as_slice()); builder.set_additional_data(out.into_inner().as_slice());
@ -86,21 +151,49 @@ impl AuthenticationSystem for Authentication {
Ok(Step::NeedsMore(_)) => { Ok(Step::NeedsMore(_)) => {
self.state = State::Running(session, manager); self.state = State::Running(session, manager);
builder.set_challenge(out.into_inner().as_slice()); builder.set_challenge(out.into_inner().as_slice());
response = Response {
union_field: "challenge",
};
} }
Err(_) => { Err(_) => {
self.state = State::Aborted; self.state = State::Aborted;
self.build_error(builder); self.build_error(builder);
response = Response {
union_field: "error",
};
} }
} }
} else { } else {
self.build_error(builder); self.build_error(builder);
response = Response {
union_field: "error",
};
} }
tracing::trace!(
results = %response,
"method return"
);
Promise::ok(()) Promise::ok(())
} }
fn abort(&mut self, _: AbortParams, _: AbortResults) -> Promise<(), Error> { fn abort(&mut self, _: AbortParams, _: AbortResults) -> Promise<(), Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(
target: TARGET,
parent: &self.span,
"abort",
)
.entered();
tracing::trace!("method call");
self.state = State::Aborted; self.state = State::Aborted;
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
} }

View File

@ -1,5 +1,7 @@
use api::connection_capnp::bootstrap; use api::connection_capnp::bootstrap;
pub use api::connection_capnp::bootstrap::Client; pub use api::connection_capnp::bootstrap::Client;
use std::fmt;
use std::fmt::{Formatter, Write};
use std::net::SocketAddr; use std::net::SocketAddr;
use crate::authentication::AuthenticationHandle; use crate::authentication::AuthenticationHandle;
@ -8,12 +10,14 @@ use crate::session::SessionManager;
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp_rpc::pry; use capnp_rpc::pry;
use rsasl::mechname::Mechname; use rsasl::mechname::Mechname;
use tracing::Span;
/// Cap'n Proto API Handler /// Cap'n Proto API Handler
pub struct BootCap { pub struct BootCap {
peer_addr: SocketAddr, peer_addr: SocketAddr,
authentication: AuthenticationHandle, authentication: AuthenticationHandle,
sessionmanager: SessionManager, sessionmanager: SessionManager,
span: Span,
} }
impl BootCap { impl BootCap {
@ -21,12 +25,13 @@ impl BootCap {
peer_addr: SocketAddr, peer_addr: SocketAddr,
authentication: AuthenticationHandle, authentication: AuthenticationHandle,
sessionmanager: SessionManager, sessionmanager: SessionManager,
span: Span,
) -> Self { ) -> Self {
tracing::trace!(%peer_addr, "bootstrapping RPC");
Self { Self {
peer_addr, peer_addr,
authentication, authentication,
sessionmanager, sessionmanager,
span,
} }
} }
} }
@ -37,8 +42,14 @@ impl bootstrap::Server for BootCap {
_: bootstrap::GetAPIVersionParams, _: bootstrap::GetAPIVersionParams,
_: bootstrap::GetAPIVersionResults, _: bootstrap::GetAPIVersionResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let span = tracing::trace_span!("get_api_version", peer_addr=%self.peer_addr); let _guard = self.span.enter();
let _guard = span.enter(); let _span = tracing::trace_span!(
target: "bffh::api",
"Bootstrap",
method = "getAPIVersion",
)
.entered();
tracing::trace!("method call");
Promise::ok(()) Promise::ok(())
} }
@ -47,11 +58,24 @@ impl bootstrap::Server for BootCap {
_: bootstrap::GetServerReleaseParams, _: bootstrap::GetServerReleaseParams,
mut result: bootstrap::GetServerReleaseResults, mut result: bootstrap::GetServerReleaseResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let span = tracing::trace_span!("get_server_release", peer_addr=%self.peer_addr); let _guard = self.span.enter();
let _guard = span.enter(); let _span = tracing::trace_span!(
target: "bffh::api",
"Bootstrap",
method = "getServerRelease",
)
.entered();
tracing::trace!("method call");
let mut builder = result.get(); let mut builder = result.get();
builder.set_name("bffhd"); builder.set_name("bffhd");
builder.set_release(crate::env::VERSION); builder.set_release(crate::env::VERSION);
tracing::trace!(
results.name = "bffhd",
results.release = crate::env::VERSION,
"method return"
);
Promise::ok(()) Promise::ok(())
} }
@ -60,10 +84,13 @@ impl bootstrap::Server for BootCap {
_params: bootstrap::MechanismsParams, _params: bootstrap::MechanismsParams,
mut result: bootstrap::MechanismsResults, mut result: bootstrap::MechanismsResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let span = tracing::trace_span!("mechanisms", peer_addr=%self.peer_addr); let _guard = self.span.enter();
let _guard = span.enter(); let _span = tracing::trace_span!(
target: "bffh::api",
tracing::trace!("mechanisms"); "mechanisms",
)
.entered();
tracing::trace!(target: "bffh::api", "method call");
let builder = result.get(); let builder = result.get();
let mechs: Vec<_> = self let mechs: Vec<_> = self
@ -77,6 +104,28 @@ impl bootstrap::Server for BootCap {
mechbuilder.set(i as u32, m); mechbuilder.set(i as u32, m);
} }
struct DisMechs<'a>(Vec<&'a str>);
impl fmt::Display for DisMechs<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_char('[')?;
let mut first = true;
for mechanism in self.0.iter() {
if first {
first = false;
f.write_str(mechanism)?;
} else {
f.write_str(" ,")?;
f.write_str(mechanism)?;
}
}
f.write_char(']')?;
Ok(())
}
}
tracing::trace!(
results.mechs = %DisMechs(mechs),
"method return"
);
Promise::ok(()) Promise::ok(())
} }
@ -85,18 +134,22 @@ impl bootstrap::Server for BootCap {
params: bootstrap::CreateSessionParams, params: bootstrap::CreateSessionParams,
mut result: bootstrap::CreateSessionResults, mut result: bootstrap::CreateSessionResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let span = tracing::trace_span!("create_session", peer_addr=%self.peer_addr); let _guard = self.span.enter();
let _guard = span.enter(); let _span = tracing::trace_span!(
target: "bffh::api",
"createSession",
)
.entered();
let params = pry!(params.get()); let params = pry!(params.get());
let mechanism: &str = pry!(params.get_mechanism()); let mechanism: &str = pry!(params.get_mechanism());
tracing::trace!(mechanism); tracing::trace!(params.mechanism = mechanism, "method call");
let mechname = Mechname::new(mechanism.as_bytes()); let mechname = Mechname::new(mechanism.as_bytes());
let auth = if let Ok(mechname) = mechname { let auth = if let Ok(mechname) = mechname {
if let Ok(session) = self.authentication.start(mechname) { if let Ok(session) = self.authentication.start(mechname) {
Authentication::new(session, self.sessionmanager.clone()) Authentication::new(&self.span, mechname, session, self.sessionmanager.clone())
} else { } else {
Authentication::invalid_mechanism() Authentication::invalid_mechanism()
} }
@ -104,6 +157,11 @@ impl bootstrap::Server for BootCap {
Authentication::invalid_mechanism() Authentication::invalid_mechanism()
}; };
tracing::trace!(
results.authentication = %auth,
"method return"
);
let mut builder = result.get(); let mut builder = result.get();
builder.set_authentication(capnp_rpc::new_client(auth)); builder.set_authentication(capnp_rpc::new_client(auth));

View File

@ -6,17 +6,27 @@ use crate::RESOURCES;
use api::machinesystem_capnp::machine_system::info; use api::machinesystem_capnp::machine_system::info;
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp_rpc::pry; use capnp_rpc::pry;
use tracing::Span;
const TARGET: &str = "bffh::api::machinesystem";
#[derive(Clone)] #[derive(Clone)]
pub struct Machines { pub struct Machines {
span: Span,
session: SessionHandle, session: SessionHandle,
resources: ResourcesHandle, resources: ResourcesHandle,
} }
impl Machines { impl Machines {
pub fn new(session: SessionHandle) -> Self { pub fn new(session: SessionHandle) -> Self {
let span = tracing::info_span!(
target: TARGET,
parent: &session.span,
"MachineSystem",
);
// FIXME no unwrap bad // FIXME no unwrap bad
Self { Self {
span,
session, session,
resources: RESOURCES.get().unwrap().clone(), resources: RESOURCES.get().unwrap().clone(),
} }
@ -29,6 +39,16 @@ impl info::Server for Machines {
_: info::GetMachineListParams, _: info::GetMachineListParams,
mut result: info::GetMachineListResults, mut result: info::GetMachineListResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(
target: TARGET,
parent: &self.span,
"getMachineList",
)
.entered();
tracing::trace!("method call");
let machine_list: Vec<(usize, &Resource)> = self let machine_list: Vec<(usize, &Resource)> = self
.resources .resources
.list_all() .list_all()
@ -43,6 +63,9 @@ impl info::Server for Machines {
Machine::build(self.session.clone(), resource, mbuilder); Machine::build(self.session.clone(), resource, mbuilder);
} }
// TODO: indicate result?
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
@ -51,12 +74,25 @@ impl info::Server for Machines {
params: info::GetMachineParams, params: info::GetMachineParams,
mut result: info::GetMachineResults, mut result: info::GetMachineResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(
target: TARGET,
parent: &self.span,
"getMachine",
)
.entered();
let params = pry!(params.get()); let params = pry!(params.get());
let id = pry!(params.get_id()); let id = pry!(params.get_id());
tracing::trace!(params.id = id, "method call");
if let Some(resource) = self.resources.get_by_id(id) { if let Some(resource) = self.resources.get_by_id(id) {
tracing::trace!(results = "Just", results.inner = id, "method return");
let builder = result.get(); let builder = result.get();
Machine::optional_build(self.session.clone(), resource.clone(), builder); Machine::optional_build(self.session.clone(), resource.clone(), builder);
} else {
tracing::trace!(results = "Nothing", "method return");
} }
Promise::ok(()) Promise::ok(())
@ -67,12 +103,29 @@ impl info::Server for Machines {
params: info::GetMachineURNParams, params: info::GetMachineURNParams,
mut result: info::GetMachineURNResults, mut result: info::GetMachineURNResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(
target: TARGET,
parent: &self.span,
"getMachineURN",
)
.entered();
let params = pry!(params.get()); let params = pry!(params.get());
let urn = pry!(params.get_urn()); let urn = pry!(params.get_urn());
tracing::trace!(params.urn = urn, "method call");
if let Some(resource) = self.resources.get_by_urn(urn) { if let Some(resource) = self.resources.get_by_urn(urn) {
tracing::trace!(
results = "Just",
results.inner = resource.get_id(),
"method return"
);
let builder = result.get(); let builder = result.get();
Machine::optional_build(self.session.clone(), resource.clone(), builder); Machine::optional_build(self.session.clone(), resource.clone(), builder);
} else {
tracing::trace!(results = "Nothing", "method return");
} }
Promise::ok(()) Promise::ok(())

View File

@ -12,7 +12,7 @@ use futures_util::{stream, AsyncRead, AsyncWrite, FutureExt, StreamExt};
use std::future::Future; use std::future::Future;
use std::io; use std::io;
use std::net::SocketAddr; use std::net::{IpAddr, SocketAddr};
use crate::authentication::AuthenticationHandle; use crate::authentication::AuthenticationHandle;
use crate::session::SessionManager; use crate::session::SessionManager;
@ -145,12 +145,36 @@ impl APIServer {
peer_addr: SocketAddr, peer_addr: SocketAddr,
stream: impl Future<Output = io::Result<TlsStream<IO>>>, stream: impl Future<Output = io::Result<TlsStream<IO>>>,
) { ) {
tracing::debug!("handling new API connection"); let span = tracing::trace_span!("api.handle");
let _guard = span.enter();
struct Peer {
ip: IpAddr,
port: u16,
}
let peer = Peer {
ip: peer_addr.ip(),
port: peer_addr.port(),
};
tracing::debug!(
%peer.ip,
peer.port,
"spawning api handler"
);
let connection_span = tracing::info_span!(
target: "bffh::api",
"connection",
%peer.ip,
peer.port,
);
let f = async move { let f = async move {
tracing::trace!(parent: &connection_span, "starting tls exchange");
let stream = match stream.await { let stream = match stream.await {
Ok(stream) => stream, Ok(stream) => stream,
Err(e) => { Err(error) => {
tracing::error!("TLS handshake failed: {}", e); tracing::error!(parent: &connection_span, %error, "TLS handshake failed");
return; return;
} }
}; };
@ -161,10 +185,15 @@ impl APIServer {
peer_addr, peer_addr,
self.authentication.clone(), self.authentication.clone(),
self.sessionmanager.clone(), self.sessionmanager.clone(),
connection_span.clone(),
)); ));
if let Err(e) = RpcSystem::new(Box::new(vat), Some(bootstrap.client)).await { if let Err(error) = RpcSystem::new(Box::new(vat), Some(bootstrap.client)).await {
tracing::error!("Error during RPC handling: {}", e); tracing::error!(
parent: &connection_span,
%error,
"error occured during rpc handling",
);
} }
}; };
let cgroup = SupervisionRegistry::with(SupervisionRegistry::new_group); let cgroup = SupervisionRegistry::with(SupervisionRegistry::new_group);

View File

@ -5,16 +5,22 @@ use api::permissionsystem_capnp::permission_system::info::{
}; };
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp::Error; use capnp::Error;
use tracing::Span;
use crate::session::SessionHandle; use crate::session::SessionHandle;
const TARGET: &str = "bffh::api::permissionsystem";
pub struct Permissions { pub struct Permissions {
span: Span,
roles: Roles, roles: Roles,
} }
impl Permissions { impl Permissions {
pub fn new(session: SessionHandle) -> Self { pub fn new(session: SessionHandle) -> Self {
let span = tracing::info_span!(target: TARGET, "PermissionSystem",);
Self { Self {
span,
roles: session.roles, roles: session.roles,
} }
} }
@ -26,6 +32,10 @@ impl PermissionSystem for Permissions {
_: GetRoleListParams, _: GetRoleListParams,
mut results: GetRoleListResults, mut results: GetRoleListResults,
) -> Promise<(), Error> { ) -> Promise<(), Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "getRoleList",).entered();
tracing::trace!("method call");
let roles = self.roles.list().collect::<Vec<&String>>(); let roles = self.roles.list().collect::<Vec<&String>>();
let mut builder = results.get(); let mut builder = results.get();
let mut b = builder.init_role_list(roles.len() as u32); let mut b = builder.init_role_list(roles.len() as u32);
@ -33,6 +43,7 @@ impl PermissionSystem for Permissions {
let mut role_builder = b.reborrow().get(i as u32); let mut role_builder = b.reborrow().get(i as u32);
role_builder.set_name(role); role_builder.set_name(role);
} }
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
} }

View File

@ -1,20 +1,25 @@
use api::usersystem_capnp::user_system::{info, manage, search}; use api::usersystem_capnp::user_system::{info, manage, search};
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp_rpc::pry; use capnp_rpc::pry;
use tracing::Span;
use crate::capnp::user::User; use crate::capnp::user::User;
use crate::session::SessionHandle; use crate::session::SessionHandle;
use crate::users::{db, UserRef}; use crate::users::{db, UserRef};
const TARGET: &str = "bffh::api::usersystem";
#[derive(Clone)] #[derive(Clone)]
pub struct Users { pub struct Users {
span: Span,
session: SessionHandle, session: SessionHandle,
} }
impl Users { impl Users {
pub fn new(session: SessionHandle) -> Self { pub fn new(session: SessionHandle) -> Self {
Self { session } let span = tracing::info_span!(target: TARGET, "UserSystem",);
Self { span, session }
} }
} }
@ -24,8 +29,14 @@ impl info::Server for Users {
_: info::GetUserSelfParams, _: info::GetUserSelfParams,
mut result: info::GetUserSelfResults, mut result: info::GetUserSelfResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "getUserSelf").entered();
tracing::trace!("method call");
let builder = result.get(); let builder = result.get();
User::build(self.session.clone(), builder); User::build(self.session.clone(), builder);
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
} }
@ -36,6 +47,10 @@ impl manage::Server for Users {
_: manage::GetUserListParams, _: manage::GetUserListParams,
mut result: manage::GetUserListResults, mut result: manage::GetUserListResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "getUserList",).entered();
tracing::trace!("method call");
let userdb = self.session.users.into_inner(); let userdb = self.session.users.into_inner();
let users = pry!(userdb let users = pry!(userdb
.get_all() .get_all()
@ -44,18 +59,30 @@ impl manage::Server for Users {
for (i, (_, user)) in users.into_iter().enumerate() { for (i, (_, user)) in users.into_iter().enumerate() {
User::fill(&self.session, user, builder.reborrow().get(i as u32)); User::fill(&self.session, user, builder.reborrow().get(i as u32));
} }
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
fn add_user_fallible( fn add_user_fallible(
&mut self, &mut self,
params: manage::AddUserFallibleParams, params: manage::AddUserFallibleParams,
mut result: manage::AddUserFallibleResults, mut result: manage::AddUserFallibleResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "addUserFallible").entered();
let params = pry!(params.get()); let params = pry!(params.get());
let username = pry!(params.get_username()); let username = pry!(params.get_username());
let password = pry!(params.get_password()); let password = pry!(params.get_password());
// FIXME: saslprep passwords & usernames before storing them // FIXME: saslprep passwords & usernames before storing them
tracing::trace!(
params.username = username,
params.password = "<redacted>",
"method call"
);
let mut builder = result.get(); let mut builder = result.get();
if !username.is_empty() && !password.is_empty() { if !username.is_empty() && !password.is_empty() {
@ -81,21 +108,29 @@ impl manage::Server for Users {
} }
} }
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
fn remove_user( fn remove_user(
&mut self, &mut self,
params: manage::RemoveUserParams, params: manage::RemoveUserParams,
_: manage::RemoveUserResults, _: manage::RemoveUserResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "removeUser",).entered();
let who: &str = pry!(pry!(pry!(params.get()).get_user()).get_username()); let who: &str = pry!(pry!(pry!(params.get()).get_user()).get_username());
tracing::trace!(params.user = who, "method call");
if let Err(e) = self.session.users.del_user(who) { if let Err(e) = self.session.users.del_user(who) {
tracing::warn!("Failed to delete user: {:?}", e); tracing::warn!("Failed to delete user: {:?}", e);
} else { } else {
tracing::info!("Deleted user {}", who); tracing::info!("Deleted user {}", who);
} }
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
} }
@ -106,9 +141,17 @@ impl search::Server for Users {
params: search::GetUserByNameParams, params: search::GetUserByNameParams,
mut result: search::GetUserByNameResults, mut result: search::GetUserByNameResults,
) -> Promise<(), ::capnp::Error> { ) -> Promise<(), ::capnp::Error> {
let _guard = self.span.enter();
let _span = tracing::trace_span!(target: TARGET, "getUserByName",).entered();
let username: &str = pry!(pry!(params.get()).get_username()); let username: &str = pry!(pry!(params.get()).get_username());
tracing::trace!(params.username = username, "method call");
let userref = UserRef::new(username.to_string()); let userref = UserRef::new(username.to_string());
User::build_optional(&self.session, Some(userref), result.get()); User::build_optional(&self.session, Some(userref), result.get());
tracing::trace!("method return");
Promise::ok(()) Promise::ok(())
} }
} }

View File

@ -17,6 +17,7 @@ use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use tracing::Span;
use url::Url; use url::Url;
mod dummy; mod dummy;
@ -33,12 +34,17 @@ pub trait Initiator: Future<Output = ()> {
#[derive(Clone)] #[derive(Clone)]
pub struct InitiatorCallbacks { pub struct InitiatorCallbacks {
span: Span,
resource: Resource, resource: Resource,
sessions: SessionManager, sessions: SessionManager,
} }
impl InitiatorCallbacks { impl InitiatorCallbacks {
pub fn new(resource: Resource, sessions: SessionManager) -> Self { pub fn new(span: Span, resource: Resource, sessions: SessionManager) -> Self {
Self { resource, sessions } Self {
span,
resource,
sessions,
}
} }
pub async fn try_update(&mut self, session: SessionHandle, status: Status) { pub async fn try_update(&mut self, session: SessionHandle, status: Status) {
@ -46,17 +52,19 @@ impl InitiatorCallbacks {
} }
pub fn open_session(&self, uid: &str) -> Option<SessionHandle> { pub fn open_session(&self, uid: &str) -> Option<SessionHandle> {
self.sessions.open(uid) self.sessions.open(&self.span, uid)
} }
} }
pub struct InitiatorDriver { pub struct InitiatorDriver {
span: Span,
name: String, name: String,
initiator: Box<dyn Initiator + Unpin + Send>, initiator: Box<dyn Initiator + Unpin + Send>,
} }
impl InitiatorDriver { impl InitiatorDriver {
pub fn new<I>( pub fn new<I>(
span: Span,
name: String, name: String,
params: &HashMap<String, String>, params: &HashMap<String, String>,
resource: Resource, resource: Resource,
@ -65,9 +73,13 @@ impl InitiatorDriver {
where where
I: 'static + Initiator + Unpin + Send, I: 'static + Initiator + Unpin + Send,
{ {
let callbacks = InitiatorCallbacks::new(resource, sessions); let callbacks = InitiatorCallbacks::new(span.clone(), resource, sessions);
let initiator = Box::new(I::new(params, callbacks)?); let initiator = Box::new(I::new(params, callbacks)?);
Ok(Self { name, initiator }) Ok(Self {
span,
name,
initiator,
})
} }
} }
@ -133,15 +145,22 @@ fn load_single(
resource: Resource, resource: Resource,
sessions: &SessionManager, sessions: &SessionManager,
) -> Option<InitiatorDriver> { ) -> Option<InitiatorDriver> {
let span = tracing::info_span!(
"initiator",
name = %name,
module = %module_name,
);
tracing::info!(%name, %module_name, ?params, "Loading initiator"); tracing::info!(%name, %module_name, ?params, "Loading initiator");
let o = match module_name.as_ref() { let o = match module_name.as_ref() {
"Dummy" => Some(InitiatorDriver::new::<Dummy>( "Dummy" => Some(InitiatorDriver::new::<Dummy>(
span,
name.clone(), name.clone(),
params, params,
resource, resource,
sessions.clone(), sessions.clone(),
)), )),
"Process" => Some(InitiatorDriver::new::<Process>( "Process" => Some(InitiatorDriver::new::<Process>(
span,
name.clone(), name.clone(),
params, params,
resource, resource,

View File

@ -43,7 +43,7 @@ mod tls;
use std::sync::Arc; use std::sync::Arc;
use futures_util::StreamExt; use futures_util::{FutureExt, StreamExt};
use miette::{Context, IntoDiagnostic, Report}; use miette::{Context, IntoDiagnostic, Report};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@ -94,9 +94,7 @@ impl Diflouroborane {
} }
tracing::info!("Server is being spawned"); tracing::info!("Server is being spawned");
let handle = executor.spawn(server.serve()); let handle = executor.spawn(server.serve());
std::thread::spawn(move || { executor.spawn(handle.map(|result| match result {
let result = async_io::block_on(handle);
match result {
Some(Ok(())) => { Some(Ok(())) => {
tracing::info!("console server finished without error"); tracing::info!("console server finished without error");
} }
@ -106,8 +104,7 @@ impl Diflouroborane {
None => { None => {
tracing::info!("console server finished with panic"); tracing::info!("console server finished with panic");
} }
} }));
});
let env = StateDB::open_env(&config.db_path)?; let env = StateDB::open_env(&config.db_path)?;

View File

@ -3,6 +3,7 @@ use crate::authorization::roles::Roles;
use crate::resources::Resource; use crate::resources::Resource;
use crate::users::{db, UserRef}; use crate::users::{db, UserRef};
use crate::Users; use crate::Users;
use tracing::Span;
#[derive(Clone)] #[derive(Clone)]
pub struct SessionManager { pub struct SessionManager {
@ -16,11 +17,18 @@ impl SessionManager {
} }
// TODO: make infallible // TODO: make infallible
pub fn open(&self, uid: impl AsRef<str>) -> Option<SessionHandle> { pub fn open(&self, parent: &Span, uid: impl AsRef<str>) -> Option<SessionHandle> {
let uid = uid.as_ref(); let uid = uid.as_ref();
if let Some(user) = self.users.get_user(uid) { if let Some(user) = self.users.get_user(uid) {
tracing::trace!(uid, ?user, "opening new session for user"); let span = tracing::info_span!(
target: "bffh::api",
parent: parent,
"session",
uid = uid,
);
tracing::trace!(parent: &span, uid, ?user, "opening session");
Some(SessionHandle { Some(SessionHandle {
span,
users: self.users.clone(), users: self.users.clone(),
roles: self.roles.clone(), roles: self.roles.clone(),
user: UserRef::new(user.id), user: UserRef::new(user.id),
@ -33,6 +41,8 @@ impl SessionManager {
#[derive(Clone)] #[derive(Clone)]
pub struct SessionHandle { pub struct SessionHandle {
pub span: Span,
pub users: Users, pub users: Users,
pub roles: Roles, pub roles: Roles,