11use super :: properties;
2+ use actix_web:: cookie;
3+ use secrecy:: ExposeSecret ;
24use 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
2023fn 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
6772pub 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
90106impl 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+ }
0 commit comments