From 6cecae76dce0874dc1761e9fd98922843e0ec9a4 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Mon, 29 Jul 2024 23:43:50 +0200 Subject: [PATCH 1/5] change default username to root --- src/config_manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config_manager.rs b/src/config_manager.rs index b4f6a8d..a6d414a 100644 --- a/src/config_manager.rs +++ b/src/config_manager.rs @@ -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, }); From 7449bade916ee0cd3a3b69031eb1e9db25c42f82 Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Mon, 29 Jul 2024 23:46:54 +0200 Subject: [PATCH 2/5] split up system api module --- src/api/system/mod.rs | 12 ++++++++++++ src/api/{system.rs => system/user.rs} | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/api/system/mod.rs rename src/api/{system.rs => system/user.rs} (99%) diff --git a/src/api/system/mod.rs b/src/api/system/mod.rs new file mode 100644 index 0000000..cce9845 --- /dev/null +++ b/src/api/system/mod.rs @@ -0,0 +1,12 @@ +use crate::state::RpcState; +use jsonrpsee::RpcModule; + +mod power; +mod service; +mod user; + +pub fn register_methods(module: &mut RpcModule) { + power::register_methods(module); + user::register_methods(module); + service::register_methods(module); +} diff --git a/src/api/system.rs b/src/api/system/user.rs similarity index 99% rename from src/api/system.rs rename to src/api/system/user.rs index 4534d06..0ed8ccd 100644 --- a/src/api/system.rs +++ b/src/api/system/user.rs @@ -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) { From fb03a17d36cb8592c10fea72eab5014675c2fbaf Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Mon, 29 Jul 2024 23:47:52 +0200 Subject: [PATCH 3/5] Add dbus error to apierror --- src/api/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/api/mod.rs b/src/api/mod.rs index fc88e11..c354c4a 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -32,6 +32,9 @@ pub enum ApiError { #[error(transparent)] IOError(#[from] std::io::Error), + + #[error(transparent)] + DbusError(#[from] zbus::Error), } impl Into> for ApiError { From 1e66729e5959bc33729be69c22e5942810ac65fc Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Mon, 29 Jul 2024 23:49:50 +0200 Subject: [PATCH 4/5] add system power api --- src/api/system/power.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/api/system/power.rs diff --git a/src/api/system/power.rs b/src/api/system/power.rs new file mode 100644 index 0000000..ad14ab7 --- /dev/null +++ b/src/api/system/power.rs @@ -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) { + 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) -> 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) -> Result<(), ApiError> { + let systemd_manager = zbus_systemd::systemd1::ManagerProxy::new(&_state.dbus_conn).await?; + systemd_manager.reboot().await?; + Ok(()) +} From ea1dd223b7c9f691415af9833cc1fd3d3aa7375f Mon Sep 17 00:00:00 2001 From: Samuel Lorch Date: Mon, 29 Jul 2024 23:55:17 +0200 Subject: [PATCH 5/5] add system service api --- src/api/system/service.rs | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/api/system/service.rs diff --git a/src/api/system/service.rs b/src/api/system/service.rs new file mode 100644 index 0000000..1631f6c --- /dev/null +++ b/src/api/system/service.rs @@ -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) { + 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, +) -> Result, ApiError> { + let res: Vec = 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 { + 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) -> 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) -> 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(()) +}