Skip to content

Commit 16cebe1

Browse files
Merge pull request #11 from software-artificer/stable-cookie-key
Add support for stable cookie signing key
2 parents 18c50b3 + 66fe7db commit 16cebe1

File tree

4 files changed

+44
-6
lines changed

4 files changed

+44
-6
lines changed

config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ users_file_path: /var/lib/minecraft/users.yml
77
base_url: http://127.0.0.1:9753/
88
min_password_length: 10
99
max_password_length: 128
10+
cookie_key: NKZW9j1Q7ABNv01xF5NSI3gmyKDaTrVb

src/core/config.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::properties;
2+
use actix_web::cookie;
3+
use secrecy::ExposeSecret;
24
use std::{env, fs, io, net, num, path};
35

46
#[derive(serde::Deserialize)]
@@ -15,6 +17,7 @@ struct ConfigFile {
1517
tls_key: Option<path::PathBuf>,
1618
tls_chain: Option<path::PathBuf>,
1719
worker_count: Option<num::NonZeroUsize>,
20+
cookie_key: Option<secrecy::SecretString>,
1821
}
1922

2023
fn default_min_password_len() -> u8 {
@@ -39,12 +42,12 @@ pub enum LoadConfigError {
3942
#[source]
4043
source: io::Error,
4144
},
42-
#[error("Failed to canonicalize the path {}: {source}", .path.display())]
45+
#[error("Failed to canonicalize the path {}", .path.display())]
4346
CanonicalizePath {
4447
path: path::PathBuf,
4548
source: io::Error,
4649
},
47-
#[error("Failed to validate configuration file: {0}")]
50+
#[error("Failed to validate configuration file")]
4851
Validate(#[from] ConfigValidationError),
4952
}
5053

@@ -58,10 +61,12 @@ pub enum ConfigValidationError {
5861
InvalidBaseUrl(url::Url),
5962
#[error("Invalid server.properties path: {}", .0.display())]
6063
PropertiesPath(path::PathBuf),
61-
#[error("Unable to load server.properties file: {0}")]
64+
#[error("Unable to load server.properties file")]
6265
LoadProperties(#[source] properties::Error),
6366
#[error("Invalid TLS configuration: {0}")]
6467
Tls(String),
68+
#[error("Cookie key must be at least 32 bytes long, got: {0}")]
69+
CookieKey(usize),
6570
}
6671

6772
pub struct AppConfig {
@@ -85,6 +90,17 @@ pub struct Config {
8590
pub app_config: AppConfig,
8691
pub tls: Option<TlsConfig>,
8792
pub worker_count: Option<num::NonZeroUsize>,
93+
pub cookie_key: Option<secrecy::SecretBox<str>>,
94+
}
95+
96+
impl Config {
97+
pub fn cookie_key(&self) -> Option<cookie::Key> {
98+
if let Some(key) = &self.cookie_key {
99+
Some(cookie::Key::derive_from(key.expose_secret().as_bytes()))
100+
} else {
101+
cookie::Key::try_generate()
102+
}
103+
}
88104
}
89105

90106
impl Config {
@@ -112,6 +128,7 @@ impl TryFrom<ConfigFile> for Config {
112128
resolve_server_properties_file_path(config.server_properties_path)?;
113129
let rcon_properties = load_server_properties(&server_properties_path)?;
114130
let tls = resolve_tls_config(config.tls_key, config.tls_chain)?;
131+
let cookie_key = check_cookie_key(config.cookie_key)?;
115132

116133
Ok(Self {
117134
listen_on: config.listen_on,
@@ -130,6 +147,7 @@ impl TryFrom<ConfigFile> for Config {
130147
rcon_password: rcon_properties.password,
131148
},
132149
worker_count: config.worker_count,
150+
cookie_key,
133151
})
134152
}
135153
}
@@ -228,3 +246,19 @@ fn relative_path_to_absolute<P: AsRef<path::Path>>(
228246
};
229247
Ok(path)
230248
}
249+
250+
fn check_cookie_key(
251+
key: Option<secrecy::SecretString>,
252+
) -> Result<Option<secrecy::SecretString>, ConfigValidationError> {
253+
if let Some(key) = key {
254+
let key_len = key.expose_secret().len();
255+
256+
if key_len < 32 {
257+
Err(ConfigValidationError::CookieKey(key_len))
258+
} else {
259+
Ok(Some(key))
260+
}
261+
} else {
262+
Ok(None)
263+
}
264+
}

src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ use std::path;
1111
struct Args {
1212
#[command(subcommand)]
1313
cmd: Commands,
14-
#[arg(short, long, default_value = "mctrlrs.toml")]
14+
#[arg(short, long, default_value = "mctrlrs.yaml")]
1515
/// Path to the YAML configuration file. If absolute path is provided it will be used as is.
1616
/// The relative path starting from "./" or "../" will be resolved using current working
17-
/// directory as a base path. The relative path that starts from something other than "./" or "../" will be resolved against the binary location.
17+
/// directory as a base path. The relative path that starts from something other than
18+
/// "./" or "../" will be resolved against the binary location.
1819
config: path::PathBuf,
1920
}
2021

src/web/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub enum Error {
2424
Actix(#[from] std::io::Error),
2525
#[error("Failed to configure TLS: {0}")]
2626
Tls(String),
27+
#[error("Failed to generate the cookie signing key")]
28+
CookieKey,
2729
}
2830

2931
pub fn start_server(config: core::Config) -> Result<(), Error> {
@@ -50,7 +52,7 @@ async fn run_server(config: core::Config) -> Result<(), Error> {
5052
handlebars::DirectorySourceOptions::default(),
5153
)?;
5254
let templates = web::Data::new(templates);
53-
let secret_key = cookie::Key::generate();
55+
let secret_key = config.cookie_key().ok_or(Error::CookieKey)?;
5456
let session_store = session::SessionStore::default();
5557
let app_config = web::Data::new(config.app_config);
5658
let client = web::Data::new(server::Client::new(

0 commit comments

Comments
 (0)