Implement Unbound Apply

This commit is contained in:
Samuel Lorch 2024-02-11 03:52:43 +01:00
parent 371b3d9fdf
commit e3ab77008a
5 changed files with 95 additions and 0 deletions

View file

@ -319,6 +319,7 @@ export const editTypes: { [key: string]: { [key: string]: any } } = {
name: 'DNS Server',
idType: 'Number',
fields: {
name: { is: 'TextBox', label: 'Name'},
interface: { is: 'SingleSelect', label: 'Interface', props: { searchProvider: GetInterfaces} },
comment: { is: 'MultilineTextBox', label: 'Comment'},
},

View file

@ -2,6 +2,7 @@ use thiserror::Error;
pub mod chrony;
pub mod networkd;
pub mod unbound;
#[derive(Error, Debug)]
pub enum ApplyError {

77
src/apply/unbound.rs Normal file
View file

@ -0,0 +1,77 @@
use super::ApplyError;
use crate::{
definitions::{
config::Config,
network::{AddressingMode, NetworkInterfaceType},
},
templates,
};
use ipnet::IpNet;
use std::process::Command;
use std::str::FromStr;
use std::{error::Error, io::Write};
use tera::Context;
use tracing::{error, info};
const UNBOUND_CONFIG_PATH: &str = "/etc/unbound/unbound.conf";
const UNBOUND_TEMPLATE_PATH: &str = "unbound/unbound.conf";
pub fn apply_unbound(pending_config: Config, _current_config: Config) -> Result<(), ApplyError> {
let config_data;
let mut context = Context::new();
let mut interfaces = vec![];
let mut subnets = vec![];
for server in &pending_config.service.dns_servers {
let interface = server.interface(pending_config.clone());
if let NetworkInterfaceType::Hardware { device } = interface.interface_type.clone() {
interfaces.push(device);
} else {
interfaces.push(interface.name.clone());
}
if let AddressingMode::Static { address } =
&server.interface(pending_config.clone()).addressing_mode
{
subnets.push(IpNet::from_str(address)?.network().to_string());
}
}
context.insert("interfaces", &interfaces);
context.insert("subnets", &subnets);
match templates::TEMPLATES.render(UNBOUND_TEMPLATE_PATH, &context) {
Ok(s) => config_data = s,
Err(e) => {
error!("Error: {}", e);
let mut cause = e.source();
while let Some(e) = cause {
error!("Reason: {}", e);
cause = e.source();
}
return Err(ApplyError::TemplateError(e));
}
}
info!("Deleting old Unbound Config");
std::fs::remove_file(UNBOUND_CONFIG_PATH)?;
info!("Writing new Unbound Config");
let mut f = std::fs::File::create(UNBOUND_CONFIG_PATH)?;
f.write_all(config_data.as_bytes())?;
info!("Restarting Unbound");
match Command::new("systemctl")
.arg("restart")
.arg("unbound")
.output()
{
Ok(out) => {
if out.status.success() {
Ok(())
} else {
Err(ApplyError::ServiceRestartFailed)
}
}
Err(err) => Err(ApplyError::IOError(err)),
}
}

View file

@ -38,6 +38,7 @@ static APPLY_FUNCTIONS: &'static [fn(
) -> Result<(), super::apply::ApplyError>] = &[
super::apply::networkd::apply_networkd,
super::apply::chrony::apply_chrony,
super::apply::unbound::apply_unbound,
];
#[derive(Clone)]

View file

@ -0,0 +1,15 @@
server:
# Listen Interfaces
{% for interface in interfaces -%}
interface: {{ interface }}
{% endfor -%}
# Allowed Networks
{% for subnet in subnets -%}
access-control: {{ subnet }} allow
{% endfor -%}
remote-control:
control-enable: yes