[pbs-devel] [REBASED backup 14/14] validate node config before writing

Wolfgang Bumiller w.bumiller at proxmox.com
Thu Apr 29 15:13:22 CEST 2021


this prevents duplicate domain entries and makes sure they
can actually be deserialized into AcmeDomain structs

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/config/node.rs | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/config/node.rs b/src/config/node.rs
index b6abeef3..18c61a45 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -1,7 +1,8 @@
+use std::collections::HashSet;
 use std::fs::File;
 use std::time::Duration;
 
-use anyhow::{format_err, Error};
+use anyhow::{bail, format_err, Error};
 use nix::sys::stat::Mode;
 use serde::{Deserialize, Serialize};
 
@@ -37,6 +38,8 @@ pub fn config() -> Result<(NodeConfig, [u8; 32]), Error> {
 
 /// Write the Node Config, requires the write lock to be held.
 pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
+    config.validate()?;
+
     let raw = crate::tools::config::to_bytes(config, &NodeConfig::API_SCHEMA)?;
 
     let backup_user = crate::backup::backup_user()?;
@@ -147,6 +150,19 @@ impl NodeConfig {
     pub fn acme_domains(&self) -> AcmeDomainIter {
         AcmeDomainIter::new(self)
     }
+
+    /// Validate the configuration.
+    pub fn validate(&self) -> Result<(), Error> {
+        let mut domains = HashSet::new();
+        for domain in self.acme_domains() {
+            let domain = domain?;
+            if !domains.insert(domain.domain.to_lowercase()) {
+                bail!("duplicate domain '{}' in ACME config", domain.domain);
+            }
+        }
+
+        Ok(())
+    }
 }
 
 pub struct AcmeDomainIter<'a> {
-- 
2.20.1






More information about the pbs-devel mailing list