(Optionally) check zones with nsd before they are written, to ensure safety

This commit is contained in:
Al Beano 2017-09-14 17:15:02 +01:00
parent 32c5b712d7
commit 42e30a2bc0
8 changed files with 70 additions and 19 deletions

View File

@ -10,6 +10,7 @@ use feature 'say';
use FindBin qw($Bin);
use YAML::Tiny;
use DBI;
use Capture::Tiny ':all';
my $yml = YAML::Tiny->read("$Bin/../config.yml");
my $tld = $yml->[0]->{"tld"};
@ -25,30 +26,27 @@ $sth->execute;
my $cyberman = $sth->fetchrow_hashref;
exit unless $cyberman->{"intserial"} > $cyberman->{"lastserial"};
open my $out, ">", $conf->{"file"} or die $!;
my $zone;
# Introduction
say $out <<'END';
$zone .= <<"END";
; File produced by cyberman. Do not edit!
$TTL 86400
$ORIGIN cyb.
\$TTL 86400
\$ORIGIN $tld.
END
# Write SOA
# Uses mostly hard-coded values for now
say $out "@ 1D IN SOA $conf->{ns} $conf->{responsible} (";
say $out time;
say $out <<'END';
$zone .= "@ 1D IN SOA $conf->{ns} $conf->{responsible} (\n" . time . "\n";
$zone .= <<'END';
1800 ; refresh
15 ; retry
604800 ; expire
1h ; nxdomain ttl
)
END
if ($conf->{"include"}->{"enabled"}) {
say $out "\$INCLUDE $conf->{include}->{file}";
}
END
# Time to get the records
$sth = $dbh->prepare("SELECT * FROM record");
@ -63,20 +61,41 @@ while (my $r = $sth->fetchrow_hashref) {
# domain name
if ($r->{"name"} eq '@') {
print $out $d->{"name"}, " ";
$zone .= $d->{"name"} . " ";
} else {
print $out $r->{"name"}, ".", $d->{"name"}, " ";
$zone .= $r->{"name"} . "." . $d->{"name"} . " ";
}
# record type
print $out "IN $r->{type} ";
$zone .= "IN $r->{type} ";
# value
say $out $r->{value};
$zone .= "$r->{value}\n";
}
if ($conf->{"validate"}) {
my $checkzone_exit;
capture {
open my $checkzone, "| nsd-checkzone $tld -" or die $!;
print $checkzone $zone;
close $checkzone;
$checkzone_exit = $?;
};
if ($checkzone_exit != 0) {
$sth = $dbh->prepare("UPDATE cyberman SET zonecheckstatus=1");
$sth->execute;
exit;
}
}
if ($conf->{"include"}->{"enabled"}) {
$zone .= "\$INCLUDE $conf->{include}->{file}\n";
}
open my $out, ">", $conf->{"file"} or die $!;
say $out $zone;
close $out;
$sth = $dbh->prepare("UPDATE cyberman SET lastserial=?");
$sth = $dbh->prepare("UPDATE cyberman SET lastserial=?, zonecheckstatus=0");
$sth->bind_param(1, $cyberman->{"intserial"});
$sth->execute;

View File

@ -42,6 +42,9 @@ zonewriter:
# in the zone, which allows you to define some records manually
enabled: 1
file: 'human_cyb'
# if true, written zones will be checked with nsd-checkzone, just in case
# requires nsd to be installed and nsd-checkzone to be in path
validate: 1
mail:
enabled: 1

View File

@ -14,6 +14,7 @@ requires "Email::Simple" => "0";
requires "Email::Simple::Creator" => "0";
requires "Email::Sender::Simple" => "0";
requires "URI::Escape" => "0";
requires "Capture::Tiny" => "0";
requires "Plack::Middleware::Deflater" => "0";
requires "Plack::Middleware::Session" => "0";

2
dbupdate/7.sql Normal file
View File

@ -0,0 +1,2 @@
alter table cyberman add column zonecheckstatus not null default 0;
update cyberman set dbrev=8;

View File

@ -57,6 +57,17 @@ hook 'before' => sub {
var admin => $user->{"admin"};
var config => config();
if ($user->{"admin"}) {
my $zone_check = database->quick_lookup(
"cyberman",
{},
"zonecheckstatus",
);
if ($zone_check != 0) {
var zone_check_alert => 1;
}
}
if ($user->{"stylesheet"} && grep {$_ eq $user->{"stylesheet"}} @{ config->{"stylesheets"}->{"available"} }) {
var stylesheet => $user->{"stylesheet"};
} else {

View File

@ -129,3 +129,7 @@ table.t tr:first-child {
border-radius: 2px;
max-width: 650px;
}
.msgBox.warning {
background-color: #ff583a;
border: 1px solid #c43d25;
}

View File

@ -3,9 +3,10 @@ create table cyberman (
id integer primary key,
dbrev integer not null,
intserial integer not null default 1,
lastserial integer not null default 0
lastserial integer not null default 0,
zonecheckstatus integer not null default 0,
);
insert into cyberman (dbrev) values (7);
insert into cyberman (dbrev) values (8);
drop table if exists user;
create table user (

View File

@ -29,7 +29,17 @@
</span>
</div>
</div>
<% END %>
<% END %>
<% IF vars.zone_check_alert %>
<div class="body">
<center>
<div class="msgBox warning">
<h3>Warning! Achtung!</h3>
The zone produced by the zone writer was found to be invalid by nsd; something has gone wrong! Please rectify the problem, and this message will disappear.
</div>
</center>
</div>
<% END %>
<% content %>
</div>
</body>