Skip to content

Commit

Permalink
feat: added the new configuration file to handle correct domain creat…
Browse files Browse the repository at this point in the history
…ion for acme
  • Loading branch information
thibault-cne committed Jul 30, 2024
1 parent 36cc604 commit 873211f
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 26 deletions.
15 changes: 12 additions & 3 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ log:

keys:
key1:
- thibault-cne.fr
sub.example.fr:
mname: ns-acme.example.fr.
rname: postmaster.example.fr.
example.fr:
mname: ns-acme.example.fr.
rname: postmaster.example.fr.
key2:
- example.com
- example.org
another-example.fr:
mname: ns-acme.another-example.fr.
rname: postmaster.another-example.fr.
fake.another-example.fr:
mname: ns-acme.another-example.fr.
rname: postmaster.another-example.fr.
9 changes: 9 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ impl From<domain::zonetree::error::ZoneTreeModificationError> for Error {
}
}

impl From<domain::zonetree::error::OutOfZone> for Error {
fn from(_: domain::zonetree::error::OutOfZone) -> Self {
Self {
kind: ErrorKind::DomainZone,
message: Some("out of zone".to_string()),
}
}
}

impl From<std::io::Error> for Error {
fn from(value: std::io::Error) -> Self {
Self {
Expand Down
75 changes: 60 additions & 15 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,92 @@ use std::ops::Deref;
use std::path::PathBuf;

use domain::base::iana::Class;
use domain::zonetree::types::StoredName;
use domain::zonetree::{Zone, ZoneBuilder};
use domain::base::{Record, Serial, Ttl};
use domain::rdata::Soa;
use domain::zonetree::types::{StoredName, StoredRecord};
use domain::zonetree::{Rrset, SharedRrset, Zone, ZoneBuilder};
use serde::Deserialize;

use crate::error::Result;

#[derive(Debug, Clone, Deserialize, Default)]
pub struct Keys(HashMap<KeyFile, Vec<Domain>>);
pub struct Keys(HashMap<KeyFile, HashMap<String, DomainInfo>>);

impl Deref for Keys {
type Target = HashMap<KeyFile, Vec<Domain>>;
type Target = HashMap<KeyFile, HashMap<String, DomainInfo>>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
#[serde(untagged)]
pub enum Domain {
Unamed(String),
pub struct DomainInfo {
mname: String,
rname: String,
}

pub trait TryIntoZone {
fn try_into_zone(self) -> Result<Zone>;
}

pub trait TryIntoZones {
fn try_into_zones(self) -> Result<Vec<domain::zonetree::Zone>>;
}

impl TryIntoZones for &[Domain] {
trait TryIntoStoredName {
fn try_into_stored_name(self) -> Result<StoredName>;
}

impl TryIntoZones for &HashMap<String, DomainInfo> {
fn try_into_zones(self) -> Result<Vec<domain::zonetree::Zone>> {
self.iter().map(|d| d.try_into()).collect()
self.iter().map(|d| d.try_into_zone()).collect()
}
}

impl TryFrom<&Domain> for Zone {
impl TryFrom<&DomainInfo> for SharedRrset {
type Error = crate::error::Error;

fn try_from(value: &Domain) -> Result<Self> {
let apex_name = match value {
Domain::Unamed(name) => StoredName::bytes_from_str(name)?,
};
Ok(ZoneBuilder::new(apex_name, Class::IN).build())
fn try_from(value: &DomainInfo) -> std::result::Result<Self, Self::Error> {
let record: StoredRecord = Record::new(
(&value.mname).try_into_stored_name()?,
Class::IN,
Ttl::HOUR,
Soa::new(
(&value.mname).try_into_stored_name()?,
(&value.rname).try_into_stored_name()?,
Serial::now(),
Ttl::HOUR,
Ttl::HOUR,
Ttl::HOUR,
Ttl::HOUR,
)
.into(),
);
let rset: Rrset = record.into();

Ok(rset.into_shared())
}
}

impl<S> TryIntoZone for (S, &DomainInfo)
where
S: AsRef<str>,
{
fn try_into_zone(self) -> Result<Zone> {
let (name, info) = self;
let mut builder = ZoneBuilder::new((&name).try_into_stored_name()?, Class::IN);
builder.insert_rrset(&name.try_into_stored_name()?, info.try_into()?)?;
Ok(builder.build())
}
}

impl<S> TryIntoStoredName for S
where
S: AsRef<str>,
{
fn try_into_stored_name(self) -> Result<StoredName> {
Ok(StoredName::bytes_from_str(self.as_ref())?)
}
}

Expand Down
22 changes: 14 additions & 8 deletions src/watcher.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::fs::File;
use std::path::Path;
use std::sync::mpsc::channel;
Expand All @@ -8,7 +9,7 @@ use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher as NotifyWatcher

use crate::dns::State;
use crate::error::{ErrorKind, Result};
use crate::key::{Domain, KeyFile, Keys, TryIntoZones};
use crate::key::{DomainInfo, KeyFile, Keys, TryIntoZone, TryIntoZones};

#[derive(Debug, Clone)]
pub struct Watcher;
Expand Down Expand Up @@ -85,7 +86,7 @@ fn handle_file_change(keys: &Keys, config_path: &Path, state: &Arc<State>) -> Re

fn handle_deleted_keys<'i, I>(state: &Arc<State>, deleted_keys: I) -> Result<()>
where
I: IntoIterator<Item = (&'i KeyFile, &'i Vec<Domain>)>,
I: IntoIterator<Item = (&'i KeyFile, &'i HashMap<String, DomainInfo>)>,
{
for (k, v) in deleted_keys {
v.try_into_zones()?.into_iter().for_each(|z| {
Expand All @@ -101,7 +102,7 @@ where

fn handle_added_keys<'i, I>(state: &Arc<State>, added_keys: I) -> Result<()>
where
I: IntoIterator<Item = (&'i KeyFile, &'i Vec<Domain>)>,
I: IntoIterator<Item = (&'i KeyFile, &'i HashMap<String, DomainInfo>)>,
{
for (k, v) in added_keys {
v.try_into_zones()?.into_iter().for_each(|z| {
Expand All @@ -117,20 +118,25 @@ where

fn handle_modified_keys<'i, I>(state: &Arc<State>, modified_keys: I) -> Result<()>
where
I: IntoIterator<Item = (&'i Vec<Domain>, &'i Vec<Domain>)>,
I: IntoIterator<
Item = (
&'i HashMap<String, DomainInfo>,
&'i HashMap<String, DomainInfo>,
),
>,
{
for (nv, ov) in modified_keys {
ov.iter()
.filter(|d| !nv.contains(d))
.filter(|&(d, _)| nv.get(d).is_none())
.try_for_each(|d| -> Result<()> {
let zone: Zone = d.try_into()?;
let zone: Zone = d.try_into_zone()?;
let _ = state.remove_zone(zone.apex_name(), zone.class());
Ok(())
})?;
nv.iter()
.filter(|d| !ov.contains(d))
.filter(|&(d, _)| ov.get(d).is_none())
.try_for_each(|d| -> Result<()> {
let zone: Zone = d.try_into()?;
let zone: Zone = d.try_into_zone()?;
let _ = state.insert_zone(zone);
Ok(())
})?;
Expand Down

0 comments on commit 873211f

Please sign in to comment.