Skip to content

Commit 46435e5

Browse files
authored
refactor(pedm): modify serve arguments (#1301)
- `serve` now takes a `Config` struct rather than a path - pipe name is now part of `Config` rather than a direct argument - `Config` struct is now exported as `devolutions_pedm::Config` - `serve` is now exported as `devolutions_pedm::serve`
1 parent 8dd4530 commit 46435e5

4 files changed

Lines changed: 47 additions & 34 deletions

File tree

crates/devolutions-pedm/src/api/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use axum::extract::{ConnectInfo, Request};
1212
use axum::middleware::{self, Next};
1313
use axum::response::Response;
1414
use axum::{Json, Router};
15-
use camino::Utf8PathBuf;
1615
use futures_util::future::BoxFuture;
1716
use hyper_util::rt::{TokioExecutor, TokioIo};
1817
use hyper_util::server;
@@ -40,6 +39,7 @@ use revoke::post_revoke;
4039
use state::{AppState, AppStateError};
4140
use status::get_status;
4241

42+
use crate::config::Config;
4343
use crate::db::DbError;
4444
use crate::error::{Error, ErrorResponse};
4545
use crate::utils::AccountExt;
@@ -94,7 +94,7 @@ async fn named_pipe_middleware(
9494
Ok(next.run(request).await)
9595
}
9696

97-
fn create_pipe(pipe_name: &'static str) -> anyhow::Result<NamedPipeServer> {
97+
fn create_pipe(pipe_name: &str) -> anyhow::Result<NamedPipeServer> {
9898
let pipe = ServerOptions::new().write_dac(true).create(pipe_name)?;
9999

100100
let dacl = Acl::new()?.set_entries(&[
@@ -165,8 +165,8 @@ async fn health_check() -> &'static str {
165165
"OK"
166166
}
167167

168-
pub async fn serve(pipe_name: &'static str, config_path: Option<Utf8PathBuf>) -> Result<(), ServeError> {
169-
let state = AppState::load(config_path).await?;
168+
pub async fn serve(config: Config) -> Result<(), ServeError> {
169+
let state = AppState::load(&config).await?;
170170

171171
// a plain Axum router
172172
let hello_router = Router::new().route("/health", axum::routing::get(health_check));
@@ -178,6 +178,7 @@ pub async fn serve(pipe_name: &'static str, config_path: Option<Utf8PathBuf>) ->
178178

179179
let mut make_service = app.into_make_service_with_connect_info::<RawNamedPipeConnectInfo>();
180180

181+
let pipe_name = &config.pipe_name;
181182
let mut server = create_pipe(pipe_name)?;
182183

183184
// Log the server startup.

crates/devolutions-pedm/src/api/state.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use std::sync::Arc;
44

55
use axum::extract::{FromRef, FromRequestParts};
66
use axum::http::request::Parts;
7-
use camino::Utf8PathBuf;
87
use hyper::StatusCode;
98
use parking_lot::RwLock;
109
use tracing::info;
@@ -41,18 +40,12 @@ pub(crate) struct AppState {
4140
}
4241

4342
impl AppState {
44-
pub(crate) async fn load(config_path: Option<Utf8PathBuf>) -> Result<Self, AppStateError> {
45-
let config = if let Some(path) = config_path {
46-
Config::load_from_path(&path)
47-
} else {
48-
Config::load_from_default_path()
49-
}?;
50-
43+
pub(crate) async fn load(config: &Config) -> Result<Self, AppStateError> {
5144
let db: Arc<dyn Database + Send + Sync> = match config.db {
5245
#[cfg(feature = "libsql")]
5346
DbBackend::Libsql => {
5447
#[expect(clippy::unwrap_used)]
55-
let c = config.libsql.unwrap(); // already checked by `Config::validate` at the end of the load function
48+
let c = config.libsql.as_ref().unwrap(); // already checked by `Config::validate` at the end of the load function
5649
let db_obj = libsql::Builder::new_local(&c.path)
5750
.build()
5851
.await
@@ -64,15 +57,15 @@ impl AppState {
6457
#[cfg(feature = "postgres")]
6558
DbBackend::Postgres => {
6659
#[expect(clippy::unwrap_used)]
67-
let c = config.postgres.unwrap(); // already checked by `Config::validate` at the end of the load function
60+
let c = config.postgres.as_ref().unwrap(); // already checked by `Config::validate` at the end of the load function
6861
let mut pg_config = tokio_postgres::Config::new();
6962
pg_config.host(&c.host);
7063
pg_config.dbname(&c.dbname);
7164
if let Some(n) = c.port {
7265
pg_config.port(n);
7366
}
74-
pg_config.user(c.user);
75-
if let Some(s) = c.password {
67+
pg_config.user(&c.user);
68+
if let Some(s) = &c.password {
7669
pg_config.password(s);
7770
}
7871
pg_config.ssl_mode(SslMode::Disable);

crates/devolutions-pedm/src/config.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,46 @@ use tracing::info;
77

88
use crate::data_dir;
99

10+
/// Specifies the default pipe name.
11+
///
12+
/// This is a workaround for `serde(default)` not taking a raw string literal or escaped backslashes.
13+
fn default_pipe_name() -> String {
14+
"\\\\.\\pipe\\DevolutionsPEDM".to_owned()
15+
}
16+
1017
/// The application config.
1118
#[derive(Serialize, Deserialize)]
1219
#[serde(rename_all = "PascalCase")]
13-
pub(crate) struct Config {
20+
pub struct Config {
1421
/// The selected database backend.
1522
///
1623
/// Only one can be active at a given time.
17-
pub(crate) db: DbBackend,
18-
pub(crate) postgres: Option<PgConfig>,
19-
pub(crate) libsql: Option<LibsqlConfig>,
24+
pub db: DbBackend,
25+
pub postgres: Option<PgConfig>,
26+
pub libsql: Option<LibsqlConfig>,
27+
/// Specify the pipe name, if desired.
28+
///
29+
/// Backslashes must be escaped, like "\\\\.\\pipe\\foo".
30+
/// This field is intentionally omitted from the example configuration.
31+
#[serde(default = "default_pipe_name")]
32+
pub pipe_name: String,
2033
}
2134

2235
impl Config {
2336
/// Creates a new config with the default values for a new setup.
24-
fn standard() -> Self {
37+
pub fn standard() -> Self {
2538
Self {
2639
db: DbBackend::default(),
2740
postgres: None,
2841
libsql: Some(LibsqlConfig {
2942
path: data_dir().join("pedm.sqlite"),
3043
}),
44+
pipe_name: default_pipe_name(),
3145
}
3246
}
3347

3448
/// Loads the config file from the specified path.
35-
pub(crate) fn load_from_path(path: &Utf8Path) -> Result<Self, ConfigError> {
49+
pub fn load_from_path(path: &Utf8Path) -> Result<Self, ConfigError> {
3650
match fs::read_to_string(path) {
3751
Ok(s) => {
3852
info!("Loading config from {path}");
@@ -51,7 +65,7 @@ impl Config {
5165
}
5266

5367
/// Loads the config file from the default path.
54-
pub(crate) fn load_from_default_path() -> Result<Self, ConfigError> {
68+
pub fn load_from_default_path() -> Result<Self, ConfigError> {
5569
let path = data_dir().join("config.toml");
5670
Self::load_from_path(&path)
5771
}
@@ -91,20 +105,20 @@ impl fmt::Display for DbBackend {
91105

92106
#[derive(Serialize, Deserialize)]
93107
#[serde(rename_all = "PascalCase")]
94-
pub(crate) struct LibsqlConfig {
108+
pub struct LibsqlConfig {
95109
/// The path to the SQLite database file.
96-
pub(crate) path: Utf8PathBuf,
110+
pub path: Utf8PathBuf,
97111
}
98112

99113
// TODO: SSL support
100114
#[derive(Serialize, Deserialize)]
101115
#[serde(rename_all = "PascalCase")]
102-
pub(crate) struct PgConfig {
103-
pub(crate) host: String,
104-
pub(crate) dbname: String,
105-
pub(crate) port: Option<u16>, // 5432 if omitted
106-
pub(crate) user: String,
107-
pub(crate) password: Option<String>,
116+
pub struct PgConfig {
117+
pub host: String,
118+
pub dbname: String,
119+
pub port: Option<u16>, // 5432 if omitted
120+
pub user: String,
121+
pub password: Option<String>,
108122
}
109123

110124
#[derive(Debug)]

crates/devolutions-pedm/src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,24 @@ use camino::Utf8PathBuf;
33

44
use devolutions_gateway_task::{ShutdownSignal, Task};
55

6+
mod config;
7+
pub use config::Config;
8+
69
cfg_if::cfg_if! {
710
if #[cfg(target_os = "windows")] {
811
pub mod api;
912
mod db;
10-
mod config;
13+
1114
mod elevations;
1215
mod elevator;
1316
mod error;
1417
mod log;
1518
mod policy;
1619
mod utils;
17-
use tokio::select;
1820

21+
pub use api::serve;
22+
23+
use tokio::select;
1924
use tracing::error;
2025
}
2126
}
@@ -39,7 +44,7 @@ impl Task for PedmTask {
3944
cfg_if::cfg_if! {
4045
if #[cfg(target_os = "windows")] {
4146
select! {
42-
res = api::serve(r"\\.\pipe\DevolutionsPEDM", None) => {
47+
res = serve(Config::standard()) => {
4348
if let Err(error) = &res {
4449
error!(%error, "Named pipe server got error");
4550
}

0 commit comments

Comments
 (0)