This commit is contained in:
Samuel Lorch 2024-07-30 12:01:11 +02:00
commit 352461f410
6 changed files with 127 additions and 3 deletions

View file

@ -32,6 +32,9 @@ pub enum ApiError {
#[error(transparent)]
IOError(#[from] std::io::Error),
#[error(transparent)]
DbusError(#[from] zbus::Error),
}
impl Into<ErrorObject<'static>> for ApiError {

12
src/api/system/mod.rs Normal file
View file

@ -0,0 +1,12 @@
use crate::state::RpcState;
use jsonrpsee::RpcModule;
mod power;
mod service;
mod user;
pub fn register_methods(module: &mut RpcModule<RpcState>) {
power::register_methods(module);
user::register_methods(module);
service::register_methods(module);
}

27
src/api/system/power.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::api::ApiError;
use crate::state::RpcState;
use jsonrpsee::types::Params;
use jsonrpsee::RpcModule;
use std::sync::Arc;
pub fn register_methods(module: &mut RpcModule<RpcState>) {
module
.register_async_method("system.power.shutdown", halt_system)
.unwrap();
module
.register_async_method("system.power.restart", reboot_system)
.unwrap();
}
pub async fn halt_system<'a>(_: Params<'a>, _state: Arc<RpcState>) -> Result<(), ApiError> {
let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(&_state.dbus_conn).await?;
systemd_manager.halt().await?;
Ok(())
}
pub async fn reboot_system<'a>(_: Params<'a>, _state: Arc<RpcState>) -> Result<(), ApiError> {
let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(&_state.dbus_conn).await?;
systemd_manager.reboot().await?;
Ok(())
}

83
src/api/system/service.rs Normal file
View file

@ -0,0 +1,83 @@
use crate::api::ApiError;
use crate::state::RpcState;
use jsonrpsee::{types::Params, RpcModule};
use std::sync::Arc;
const SERVICE_UNBOUND: &str = "unbound.service";
const SERVICE_SSH: &str = "sshd.service";
const SERVICE_KEAV4: &str = "kea-dhcp4.service";
const SERVICE_KEAV6: &str = "kea-dhcp6.service";
const SERVICE_CHRONY: &str = "chronyd.service";
const SERVICE_NETWORKD: &str = "systemd-networkd.service";
const SERVICE_NFTABLES: &str = "nftables.service";
pub fn register_methods(module: &mut RpcModule<RpcState>) {
module
.register_async_method("system.services.status", get_services_status)
.unwrap();
module
.register_async_method("system.services.restart", restart_service)
.unwrap();
module
.register_async_method("system.services.stop", stop_service)
.unwrap();
}
pub async fn get_services_status<'a>(
_: Params<'a>,
_state: Arc<RpcState>,
) -> Result<Vec<String>, ApiError> {
let res: Vec<String> = vec![
get_service_status(&_state.dbus_conn, SERVICE_UNBOUND).await?,
get_service_status(&_state.dbus_conn, SERVICE_SSH).await?,
get_service_status(&_state.dbus_conn, SERVICE_KEAV4).await?,
get_service_status(&_state.dbus_conn, SERVICE_KEAV6).await?,
get_service_status(&_state.dbus_conn, SERVICE_CHRONY).await?,
get_service_status(&_state.dbus_conn, SERVICE_NETWORKD).await?,
get_service_status(&_state.dbus_conn, SERVICE_NFTABLES).await?,
];
Ok(res)
}
async fn get_service_status(
dbus_conn: &zbus::Connection,
unit: &str,
) -> Result<String, zbus::Error> {
let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(dbus_conn).await?;
match systemd_manager.get_unit(unit.to_string()).await {
Ok(unit_object_path) => {
let systemd_unit =
zbus_systemd::systemd1::UnitProxy::new(dbus_conn, unit_object_path).await?;
match systemd_unit.active_state().await {
Ok(status) => Ok(status),
Err(_err) => Ok("unknown status".to_string()),
}
}
// TODO handle error better
Err(_err) => Ok("unknown unit".to_string()),
}
}
// TODO add services whitelist
async fn restart_service<'a>(params: Params<'a>, _state: Arc<RpcState>) -> Result<(), ApiError> {
let unit: String = params.parse().map_err(ApiError::ParameterDeserialize)?;
let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(&_state.dbus_conn).await?;
let unit_object_path = systemd_manager.get_unit(unit).await?;
let systemd_unit =
zbus_systemd::systemd1::UnitProxy::new(&_state.dbus_conn, unit_object_path).await?;
systemd_unit.restart("replace".to_string()).await?;
Ok(())
}
async fn stop_service<'a>(params: Params<'a>, _state: Arc<RpcState>) -> Result<(), ApiError> {
let unit: String = params.parse().map_err(ApiError::ParameterDeserialize)?;
let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(&_state.dbus_conn).await?;
let unit_object_path = systemd_manager.get_unit(unit).await?;
let systemd_unit =
zbus_systemd::systemd1::UnitProxy::new(&_state.dbus_conn, unit_object_path).await?;
systemd_unit.stop("replace".to_string()).await?;
Ok(())
}

View file

@ -6,13 +6,12 @@ use jsonrpsee::RpcModule;
use pwhash::sha512_crypt;
use serde::{Deserialize, Serialize};
use crate::api::ApiError;
use ApiError::ConfigError;
use ApiError::HashError;
use ApiError::NotFound;
use ApiError::ParameterDeserialize;
use super::ApiError;
const USER_CHANGE_PATH: &str = "system.user";
pub fn register_methods(module: &mut RpcModule<RpcState>) {

View file

@ -193,7 +193,7 @@ pub fn generate_default_config(path: &str) -> Result<(), ConfigError> {
let hash = sha512_crypt::hash("nfsense")?;
conf.config_version = 1;
conf.system.users.push(crate::definitions::system::User {
name: "admin".to_string(),
name: "root".to_string(),
comment: "Default Admin".to_string(),
hash: hash,
});