mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-12-22 11:43:49 +01:00
Compare commits
8 Commits
b82bfa42f3
...
8b15acf983
Author | SHA1 | Date | |
---|---|---|---|
|
8b15acf983 | ||
|
40ba114e61 | ||
|
c2c34ede67 | ||
|
2b0fe0e868 | ||
|
fbfb76c34e | ||
|
971dee36fd | ||
|
41983e6039 | ||
|
ca25cd83d0 |
@ -31,6 +31,7 @@ Diflouroborane uses Cargo, so compilation boils down to:
|
|||||||
```shell
|
```shell
|
||||||
$ cargo build --release
|
$ cargo build --release
|
||||||
```
|
```
|
||||||
|
https://www.geeksforgeeks.org/how-to-install-rust-on-raspberry-pi/ can show you how to install rust on your Linux computer.
|
||||||
|
|
||||||
The compiled binary can then be found in `./target/release/bffhd`
|
The compiled binary can then be found in `./target/release/bffhd`
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ struct AuthInfo {
|
|||||||
iv: Vec<u8>,
|
iv: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(tag = "Cmd")]
|
#[serde(tag = "Cmd")]
|
||||||
enum CardCommand {
|
enum CardCommand {
|
||||||
|
@ -26,7 +26,7 @@ impl Callback {
|
|||||||
impl SessionCallback for Callback {
|
impl SessionCallback for Callback {
|
||||||
fn callback(
|
fn callback(
|
||||||
&self,
|
&self,
|
||||||
session_data: &SessionData,
|
_session_data: &SessionData,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
request: &mut Request,
|
request: &mut Request,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
|
@ -113,7 +113,7 @@ impl AuthenticationSystem for Authentication {
|
|||||||
f.write_char(')')
|
f.write_char(')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut response;
|
let 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) =
|
||||||
|
@ -211,7 +211,6 @@ impl ManageServer for Machine {
|
|||||||
mut result: manage::GetMachineInfoExtendedResults,
|
mut result: manage::GetMachineInfoExtendedResults,
|
||||||
) -> Promise<(), ::capnp::Error> {
|
) -> Promise<(), ::capnp::Error> {
|
||||||
let mut builder = result.get();
|
let mut builder = result.get();
|
||||||
let user = User::new_self(self.session.clone());
|
|
||||||
User::build_optional(
|
User::build_optional(
|
||||||
&self.session,
|
&self.session,
|
||||||
self.resource.get_current_user(),
|
self.resource.get_current_user(),
|
||||||
|
@ -36,7 +36,7 @@ impl PermissionSystem for Permissions {
|
|||||||
|
|
||||||
tracing::trace!("method call");
|
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 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);
|
||||||
for (i, role) in roles.into_iter().enumerate() {
|
for (i, role) in roles.into_iter().enumerate() {
|
||||||
let mut role_builder = b.reborrow().get(i as u32);
|
let mut role_builder = b.reborrow().get(i as u32);
|
||||||
|
@ -109,7 +109,7 @@ impl manage::Server for User {
|
|||||||
if let Some(mut user) = self.session.users.get_user(uid) {
|
if let Some(mut user) = self.session.users.get_user(uid) {
|
||||||
if let Ok(true) = user.check_password(old_pw.as_bytes()) {
|
if let Ok(true) = user.check_password(old_pw.as_bytes()) {
|
||||||
user.set_pw(new_pw.as_bytes());
|
user.set_pw(new_pw.as_bytes());
|
||||||
self.session.users.put_user(uid, &user);
|
pry!(self.session.users.put_user(uid, &user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
@ -143,9 +143,9 @@ impl admin::Server for User {
|
|||||||
// Only update if needed
|
// Only update if needed
|
||||||
if !target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
if !target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
||||||
target.userdata.roles.push(rolename.to_string());
|
target.userdata.roles.push(rolename.to_string());
|
||||||
self.session
|
pry!(self.session
|
||||||
.users
|
.users
|
||||||
.put_user(self.user.get_username(), &target);
|
.put_user(self.user.get_username(), &target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,9 +168,9 @@ impl admin::Server for User {
|
|||||||
// Only update if needed
|
// Only update if needed
|
||||||
if target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
if target.userdata.roles.iter().any(|r| r.as_str() == rolename) {
|
||||||
target.userdata.roles.retain(|r| r.as_str() != rolename);
|
target.userdata.roles.retain(|r| r.as_str() != rolename);
|
||||||
self.session
|
pry!(self.session
|
||||||
.users
|
.users
|
||||||
.put_user(self.user.get_username(), &target);
|
.put_user(self.user.get_username(), &target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ impl admin::Server for User {
|
|||||||
let uid = self.user.get_username();
|
let uid = self.user.get_username();
|
||||||
if let Some(mut user) = self.session.users.get_user(uid) {
|
if let Some(mut user) = self.session.users.get_user(uid) {
|
||||||
user.set_pw(new_pw.as_bytes());
|
user.set_pw(new_pw.as_bytes());
|
||||||
self.session.users.put_user(uid, &user);
|
pry!(self.session.users.put_user(uid, &user));
|
||||||
}
|
}
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
@ -221,7 +221,7 @@ impl card_d_e_s_fire_e_v2::Server for User {
|
|||||||
Vec::new()
|
Vec::new()
|
||||||
});
|
});
|
||||||
if !tk.is_empty() {
|
if !tk.is_empty() {
|
||||||
let mut b = results.get();
|
let b = results.get();
|
||||||
let mut lb = b.init_token_list(1);
|
let mut lb = b.init_token_list(1);
|
||||||
lb.set(0, &tk[..]);
|
lb.set(0, &tk[..]);
|
||||||
}
|
}
|
||||||
@ -299,7 +299,8 @@ impl card_d_e_s_fire_e_v2::Server for User {
|
|||||||
.insert("cardtoken".to_string(), token.to_string());
|
.insert("cardtoken".to_string(), token.to_string());
|
||||||
user.userdata.kv.insert("cardkey".to_string(), card_key);
|
user.userdata.kv.insert("cardkey".to_string(), card_key);
|
||||||
|
|
||||||
self.session.users.put_user(self.user.get_username(), &user);
|
pry!(self.session.users.put_user(self.user.get_username(), &user));
|
||||||
|
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +339,7 @@ impl card_d_e_s_fire_e_v2::Server for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session.users.put_user(self.user.get_username(), &user);
|
pry!(self.session.users.put_user(self.user.get_username(), &user));
|
||||||
|
|
||||||
Promise::ok(())
|
Promise::ok(())
|
||||||
}
|
}
|
||||||
|
@ -84,13 +84,13 @@ impl manage::Server for Users {
|
|||||||
"method call"
|
"method call"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut builder = result.get();
|
let builder = result.get();
|
||||||
|
|
||||||
if !username.is_empty() && !password.is_empty() {
|
if !username.is_empty() && !password.is_empty() {
|
||||||
if self.session.users.get_user(username).is_none() {
|
if self.session.users.get_user(username).is_none() {
|
||||||
let user = db::User::new_with_plain_pw(username, password);
|
let user = db::User::new_with_plain_pw(username, password);
|
||||||
self.session.users.put_user(username, &user);
|
pry!(self.session.users.put_user(username, &user));
|
||||||
let mut builder = builder.init_successful();
|
let builder = builder.init_successful();
|
||||||
User::fill(&self.session, user, builder);
|
User::fill(&self.session, user, builder);
|
||||||
} else {
|
} else {
|
||||||
let mut builder = builder.init_failed();
|
let mut builder = builder.init_failed();
|
||||||
|
@ -38,13 +38,15 @@ pub fn read(file: impl AsRef<Path>) -> Result<Config, ConfigError> {
|
|||||||
if !path.is_file() {
|
if !path.is_file() {
|
||||||
return Err(ConfigError::NotAFile(path.to_string_lossy().to_string()));
|
return Err(ConfigError::NotAFile(path.to_string_lossy().to_string()));
|
||||||
}
|
}
|
||||||
let mut config = dhall::read_config_file(file)?;
|
let config = dhall::read_config_file(file)?;
|
||||||
for (envvar, value) in std::env::vars() {
|
// TODO: configuration by environment variables?
|
||||||
match envvar.as_str() {
|
// but rather in in a separate function
|
||||||
// Do things like this?
|
// for (envvar, value) in std::env::vars() {
|
||||||
// "BFFH_LOG" => config.logging.filter = Some(value),
|
// match envvar.as_str() {
|
||||||
_ => {}
|
// // Do things like this?
|
||||||
}
|
// // "BFFH_LOG" => config.logging.filter = Some(value),
|
||||||
}
|
// _ => {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
// for converting a database error into a failed promise
|
||||||
|
use capnp;
|
||||||
|
|
||||||
mod raw;
|
mod raw;
|
||||||
|
|
||||||
use miette::{Diagnostic, Severity};
|
use miette::{Diagnostic, Severity};
|
||||||
@ -79,3 +82,9 @@ impl Diagnostic for Error {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Error> for capnp::Error {
|
||||||
|
fn from(dberr: Error) -> capnp::Error {
|
||||||
|
capnp::Error::failed(format!("database error: {}", dberr.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,7 +10,6 @@ use futures_util::future::BoxFuture;
|
|||||||
use futures_util::ready;
|
use futures_util::ready;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::mem;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@ -62,10 +61,7 @@ impl Future for Dummy {
|
|||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
DummyState::Empty => {
|
DummyState::Empty => {
|
||||||
tracing::trace!("Dummy initiator is empty, initializing…");
|
tracing::trace!("Dummy initiator is empty, initializing…");
|
||||||
mem::replace(
|
self.state = DummyState::Sleeping(Self::timer(), Some(Status::Free));
|
||||||
&mut self.state,
|
|
||||||
DummyState::Sleeping(Self::timer(), Some(Status::Free)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
DummyState::Sleeping(timer, next) => {
|
DummyState::Sleeping(timer, next) => {
|
||||||
tracing::trace!("Sleep timer exists, polling it.");
|
tracing::trace!("Sleep timer exists, polling it.");
|
||||||
@ -76,7 +72,7 @@ impl Future for Dummy {
|
|||||||
|
|
||||||
let status = next.take().unwrap();
|
let status = next.take().unwrap();
|
||||||
let f = self.flip(status);
|
let f = self.flip(status);
|
||||||
mem::replace(&mut self.state, DummyState::Updating(f));
|
self.state = DummyState::Updating(f);
|
||||||
}
|
}
|
||||||
DummyState::Updating(f) => {
|
DummyState::Updating(f) => {
|
||||||
tracing::trace!("Update future exists, polling it .");
|
tracing::trace!("Update future exists, polling it .");
|
||||||
@ -85,10 +81,7 @@ impl Future for Dummy {
|
|||||||
|
|
||||||
tracing::trace!("Update future completed, sleeping!");
|
tracing::trace!("Update future completed, sleeping!");
|
||||||
|
|
||||||
mem::replace(
|
self.state = DummyState::Sleeping(Self::timer(), Some(next));
|
||||||
&mut self.state,
|
|
||||||
DummyState::Sleeping(Self::timer(), Some(next)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ pub fn load(
|
|||||||
config: &Config,
|
config: &Config,
|
||||||
resources: ResourcesHandle,
|
resources: ResourcesHandle,
|
||||||
sessions: SessionManager,
|
sessions: SessionManager,
|
||||||
authentication: AuthenticationHandle,
|
_authentication: AuthenticationHandle,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
let span = tracing::info_span!("loading initiators");
|
let span = tracing::info_span!("loading initiators");
|
||||||
let _guard = span.enter();
|
let _guard = span.enter();
|
||||||
|
@ -116,7 +116,7 @@ impl ProcessState {
|
|||||||
impl Future for Process {
|
impl Future for Process {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
if let Process {
|
if let Process {
|
||||||
state: Some(state),
|
state: Some(state),
|
||||||
buffer,
|
buffer,
|
||||||
|
@ -87,6 +87,7 @@ impl error::Description for SignalHandlerErr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error, Diagnostic)]
|
#[derive(Debug, Error, Diagnostic)]
|
||||||
|
// TODO 0.5: #[non_exhaustive]
|
||||||
pub enum BFFHError {
|
pub enum BFFHError {
|
||||||
#[error("DB operation failed")]
|
#[error("DB operation failed")]
|
||||||
DBError(
|
DBError(
|
||||||
@ -210,7 +211,9 @@ impl Diflouroborane {
|
|||||||
self.resources.clone(),
|
self.resources.clone(),
|
||||||
sessionmanager.clone(),
|
sessionmanager.clone(),
|
||||||
authentication.clone(),
|
authentication.clone(),
|
||||||
);
|
).expect("initializing initiators failed");
|
||||||
|
// TODO 0.5: error handling. Add variant to BFFHError
|
||||||
|
|
||||||
actors::load(self.executor.clone(), &self.config, self.resources.clone())?;
|
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())?;
|
||||||
@ -229,13 +232,13 @@ impl Diflouroborane {
|
|||||||
self.executor.spawn(apiserver.handle_until(rx));
|
self.executor.spawn(apiserver.handle_until(rx));
|
||||||
|
|
||||||
let f = async {
|
let f = async {
|
||||||
let mut sig = None;
|
let mut sig;
|
||||||
while {
|
while {
|
||||||
sig = signals.next().await;
|
sig = signals.next().await;
|
||||||
sig.is_none()
|
sig.is_none()
|
||||||
} {}
|
} {}
|
||||||
tracing::info!(signal = %sig.unwrap(), "Received signal");
|
tracing::info!(signal = %sig.unwrap(), "Received signal");
|
||||||
tx.send(());
|
_ = tx.send(()); // ignore result, as an Err means that the executor we want to stop has already stopped
|
||||||
};
|
};
|
||||||
|
|
||||||
self.executor.run(f);
|
self.executor.run(f);
|
||||||
|
@ -85,10 +85,13 @@ impl Inner {
|
|||||||
self.db.put(&self.id.as_bytes(), &state).unwrap();
|
self.db.put(&self.id.as_bytes(), &state).unwrap();
|
||||||
tracing::trace!("Updated DB, sending update signal");
|
tracing::trace!("Updated DB, sending update signal");
|
||||||
|
|
||||||
AUDIT
|
let res = AUDIT
|
||||||
.get()
|
.get()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.log(self.id.as_str(), &format!("{}", state));
|
.log(self.id.as_str(), &format!("{}", state));
|
||||||
|
if let Err(e) = res {
|
||||||
|
tracing::error!("Writing to the audit log failed for {} {}: {e}", self.id.as_str(), state);
|
||||||
|
}
|
||||||
|
|
||||||
self.signal.set(state);
|
self.signal.set(state);
|
||||||
tracing::trace!("Sent update signal");
|
tracing::trace!("Sent update signal");
|
||||||
@ -161,7 +164,7 @@ impl Resource {
|
|||||||
|
|
||||||
fn set_state(&self, state: MachineState) {
|
fn set_state(&self, state: MachineState) {
|
||||||
let mut serializer = AllocSerializer::<1024>::default();
|
let mut serializer = AllocSerializer::<1024>::default();
|
||||||
serializer.serialize_value(&state);
|
serializer.serialize_value(&state).expect("serializing a MachineState shoud be infallible");
|
||||||
let archived = ArchivedValue::new(serializer.into_serializer().into_inner());
|
let archived = ArchivedValue::new(serializer.into_serializer().into_inner());
|
||||||
self.inner.set_state(archived)
|
self.inner.set_state(archived)
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ impl StateDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
pub fn open_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
||||||
let db = unsafe { RawDB::open(&env, Some("state")) };
|
let db = RawDB::open(&env, Some("state"))
|
||||||
let db = db.map_err(|e| StateDBError::Open(e.into()))?;
|
.map_err(|e| StateDBError::Open(e.into()))?;
|
||||||
Ok(Self::new(env, db))
|
Ok(Self::new(env, db))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ impl StateDB {
|
|||||||
|
|
||||||
pub fn create_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
pub fn create_with_env(env: Arc<Environment>) -> Result<Self, StateDBError> {
|
||||||
let flags = DatabaseFlags::empty();
|
let flags = DatabaseFlags::empty();
|
||||||
let db = unsafe { RawDB::create(&env, Some("state"), flags) };
|
let db = RawDB::create(&env, Some("state"), flags)
|
||||||
let db = db.map_err(|e| StateDBError::Create(e.into()))?;
|
.map_err(|e| StateDBError::Create(e.into()))?;
|
||||||
|
|
||||||
Ok(Self::new(env, db))
|
Ok(Self::new(env, db))
|
||||||
}
|
}
|
||||||
|
@ -182,8 +182,8 @@ impl UserDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_txn(&self, txn: &mut RwTransaction) -> Result<(), db::Error> {
|
pub fn clear_txn(&self, txn: &mut RwTransaction) -> Result<(), db::Error> {
|
||||||
self.db.clear(txn);
|
// TODO: why was the result ignored here?
|
||||||
Ok(())
|
self.db.clear(txn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all(&self) -> Result<HashMap<String, UserData>, db::Error> {
|
pub fn get_all(&self) -> Result<HashMap<String, UserData>, db::Error> {
|
||||||
|
Loading…
Reference in New Issue
Block a user