allow loading secrets from files

This commit is contained in:
Robin Appelman 2022-07-03 23:07:29 +02:00
commit ebb363c90d
2 changed files with 43 additions and 1 deletions

View file

@ -44,6 +44,14 @@ Note that this will not start an additional server is a server is already runnin
dispenser config.toml stop dispenser config.toml stop
``` ```
## Dealing with secrets
If you want to store your config file in version control but don't want to store your secrets there,
you can choose to load the secrets from other files by specifying the secret as an absolute path.
This can be done for the following config options:
`server.demostf_key`, `server.logstf_key`, `vultr.api_key`, `digitalocean.api_key` and `dyndns.password`.
## TODO ## TODO
- [x] don't blindly kill server if there are players connected - [x] don't blindly kill server if there are players connected

View file

@ -2,7 +2,8 @@ use crate::cloud::digitalocean::DigitalOcean;
use crate::cloud::vultr::Vultr; use crate::cloud::vultr::Vultr;
use crate::cloud::Cloud; use crate::cloud::Cloud;
use camino::Utf8PathBuf; use camino::Utf8PathBuf;
use serde::Deserialize; use serde::de::Error;
use serde::{Deserialize, Deserializer};
use std::fs::read_to_string; use std::fs::read_to_string;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
@ -67,13 +68,43 @@ impl Config {
} }
} }
fn deserialize_opt_secret<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
where
D: Deserializer<'de>,
{
let raw = <Option<String>>::deserialize(deserializer)?;
raw.map(load_secret)
.transpose()
.map_err(|e| D::Error::custom(e))
}
fn deserialize_secret<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let raw = String::deserialize(deserializer)?;
load_secret(raw).map_err(|e| D::Error::custom(e))
}
fn load_secret(raw: String) -> Result<String, std::io::Error> {
let path: &Path = raw.as_ref();
if raw.starts_with("/") && path.exists() {
let raw = read_to_string(raw)?;
Ok(raw.trim().into())
} else {
Ok(raw)
}
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct ServerConfig { pub struct ServerConfig {
pub rcon: String, pub rcon: String,
pub password: String, pub password: String,
#[serde(default = "server_default_image")] #[serde(default = "server_default_image")]
pub image: String, pub image: String,
#[serde(deserialize_with = "deserialize_opt_secret")]
pub demostf_key: Option<String>, pub demostf_key: Option<String>,
#[serde(deserialize_with = "deserialize_opt_secret")]
pub logstf_key: Option<String>, pub logstf_key: Option<String>,
#[serde(default = "server_default_league")] #[serde(default = "server_default_league")]
pub config_league: String, pub config_league: String,
@ -111,6 +142,7 @@ fn server_default_mode() -> String {
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct VultrConfig { pub struct VultrConfig {
#[serde(deserialize_with = "deserialize_secret")]
pub api_key: String, pub api_key: String,
/// See https://api.vultr.com/v2/regions for a list of plans /// See https://api.vultr.com/v2/regions for a list of plans
pub region: String, pub region: String,
@ -125,6 +157,7 @@ fn vultr_default_plan() -> String {
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct DigitalOceanConfig { pub struct DigitalOceanConfig {
#[serde(deserialize_with = "deserialize_secret")]
pub api_key: String, pub api_key: String,
/// See https://api.vultr.com/v2/regions for a list of plans /// See https://api.vultr.com/v2/regions for a list of plans
pub region: String, pub region: String,
@ -142,6 +175,7 @@ pub struct DynDnsConfig {
pub update_url: String, pub update_url: String,
pub hostname: String, pub hostname: String,
pub username: String, pub username: String,
#[serde(deserialize_with = "deserialize_secret")]
pub password: String, pub password: String,
} }