sign_expired hs12
authorHeiko Schlittermann <hs@schlittermann.de>
Tue, 28 Dec 2010 15:23:35 +0100
branchhs12
changeset 56 6af96ec29ada
parent 55 ee22798cf2c3
child 57 d33fd3eee469
sign_expired
update-serial.pl
--- a/update-serial.pl	Fri Dec 24 00:15:54 2010 +0100
+++ b/update-serial.pl	Tue Dec 28 15:23:35 2010 +0100
@@ -7,16 +7,20 @@
 use File::Basename;
 use Pod::Usage;
 use Getopt::Long;
+use Smart::Comments;
+use File::Temp;
+use POSIX qw(strftime);
 
 sub uniq(@);
 sub read_conf(@);
-sub add_argv;
-sub changed_zone;
-sub sign_end;
+sub zones(@);
+sub changed_zones();
+sub update_index($);
+sub sign_expired($);
+
 sub sign_zone;
 sub update_serial;
 sub mk_zone_conf;
-sub update_index;
 sub file_entry;
 sub server_reload;
 sub to_begin_ro;
@@ -27,12 +31,14 @@
 sub end_ro;
 
 my %config;
+my %opt;
 
 MAIN: {
 
     GetOptions(
-        "h|help" => sub { pod2usage(-exit 0, -verbose => 1) },
-        "m|man"  => sub {
+        "sign-alert-time=i" => \$opt{sign_alert_time},
+        "h|help"            => sub { pod2usage(-exit 0, -verbose => 1) },
+        "m|man"             => sub {
             pod2usage(
                 -exit 0,
                 -verbose   => 2,
@@ -41,38 +47,42 @@
         },
     ) or pod2usage;
 
-    %config = read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf");
+    # merge the config and the defined options from commandline
+    %config = (
+        read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf"),
+        map { $_ => $opt{$_} } grep { defined $opt{$_} } keys %opt
+    );
 
-    our @new_serial;       # liste fuer neuen serial
+    our @new_serial;       # DO NOT USE
     our @begin_ro_list;    # liste mit zonen deren key-rollover beginnt
     our @end_ro_list;      # liste mit zonen deren key-rollover fertig ist
     our $bind_dir        = $config{bind_dir};
     our $conf_dir        = $config{zone_conf_dir};
-    our $sign_alert_time = $config{sign_alert_time};
-    our $indexzone       = $config{indexzone};
     our $key_counter_end = $config{key_counter_end};
     our $ablauf_zeit     = $config{abl_zeit};
 
-    add_argv;
+    my @candidates = @ARGV ? zones(@ARGV) : changed_zones;
+    push @candidates, update_index($config{indexzone});
+    push @candidates, sign_expired($config{sign_alert_time});
+    ### @candidates
+    exit;
 
-    changed_zone;
-    sign_end;
-
-    to_begin_ro;    # prueft nach beginnenden rollover-verfahren
-    to_end_ro;      # prueft nach endenden rollover-verfahren
+    to_begin_ro;           # prueft nach beginnenden rollover-verfahren
+    to_end_ro;             # prueft nach endenden rollover-verfahren
 
     if (@begin_ro_list) {
-        begin_ro;    # eine rollover-beginn-sequenz
+        begin_ro;          # eine rollover-beginn-sequenz
     }
 
     if (@end_ro_list) {
-        end_ro;      # eine rollover-end-squenz
+        end_ro;            # eine rollover-end-squenz
     }
 
     if (@new_serial) {
-        update_index;     # index zone aktuallisieren
-        update_serial;    # serial aktuallisieren
-        sign_zone;        # zone signieren
+
+        #--update_index;     # index zone aktuallisieren
+        update_serial;     # serial aktuallisieren
+        sign_zone;         # zone signieren
     }
 
     file_entry;       # bearbeitet die file-eintraege der konfigurations-datei
@@ -82,6 +92,7 @@
 }
 
 sub uniq(@) {
+
     # remove duplicate entries
     my %all;
     @all{@_} = ();
@@ -108,74 +119,72 @@
     return %config;
 }
 
-sub add_argv {
-    # checked whether the zones in argv are managed zones and
-    #inserted them into the list new_serial
-    our @new_serial;
-    my $zone;
+sub zones(@) {
+
+    # check whether the zones in argv are managed zones and
+    # insert them into the list new_serial
+
+    my @r;
 
-    for (@ARGV) {
-        chomp($zone = `idn --quiet "$_"`);
-        if (-e "$config{master_dir}/$zone/$zone") {
-            push @new_serial, $zone;
-        }
+    foreach (@_) {
+        chomp(my $zone = `idn --quiet "$_"`);
+        die "$zone is not managed\n"
+          if not -e "$config{master_dir}/$zone/$zone";
+        push @r, $zone;
     }
+
+    return @r;
 }
 
-sub changed_zone {
-    our @new_serial;
+sub changed_zones() {
+
+    # find candidates in our master dir
+    my @r;
 
     while (glob "$config{master_dir}/*") {
         my $zone = basename($_);
 
-        if (-e "$config{master_dir}/$zone/.stamp") {
-            my $stamptime = (-M "$config{master_dir}/$zone/.stamp");
-            my $filetime  = (-M "$config{master_dir}/$zone/$zone");
-            if ($stamptime > $filetime) {
-                push @new_serial, $zone;
-                print " * $zone: zonedatei wurde geaendert\n";
-            }
+        if (not -e "$_/.stamp") {
+            say " * $zone: no .stamp file found";    # NOCH IN NEW_SERIAL PUSHEN
+            push @r, $zone;
+            next;
         }
-        else {
-            print " * $zone: keine .stamp-datei gefunden\n"
-              ;    # NOCH IN NEW_SERIAL PUSHEN
-            push @new_serial, $zone;
-        }
+
+        my $stamp_age = -M _;
+        my $file_age  = -M "$_/$zone";
+
+        next if $stamp_age <= $file_age;             # should be only <
+
+        push @r, $zone;
+        say " * $zone: zone file modified";
     }
-
+    return @r;
 }
 
-sub sign_end {
-    our $sign_alert_time;    # the time between the end and the new signing
-                             # (see external configuration)
-    our @new_serial;
+sub sign_expired($) {
+    my $sign_alert_time = shift;  # the time between the end and the new signing
+                                  # (see external configuration)
+    my @r;
 
     # erzeugt $time (die zeit ab der neu signiert werden soll)
-    my $unixtime = time + (3600 * $sign_alert_time);
-    my $time = `date -d \@$unixtime +%Y%m%d%H`;
+    # ... warum eigentlich nur bis zu den Stunden und nicht auch Minuten und Sekunden?
+    my $time = strftime("%Y%m%d%H" => localtime time + 3600 * $sign_alert_time);
 
     ## vergleicht fuer alle zonen im ordner $config{master_dir} mit einer
     ## <zone>.signed-datei den zeitpunkt in $time mit dem ablaufdatum der
     ## signatur, welcher aus der datei <zone>.signed ausgelesen wird.
-    while (glob "$config{master_dir}/*") {
-        s#($config{master_dir}/)(.*)#$2#;
-        my $zone = $_;
+    ZONE: while (my $dir = glob "$config{master_dir}/*") {
+        my $zone = basename $dir;
 
-        if (-e "$config{master_dir}/$zone/$zone.signed") {
-            open(ZONE, "$config{master_dir}/$zone/$zone.signed");
-            my @zone_sig_content = <ZONE>;
-            close(ZONE);
+	next if not -e "$dir/$zone.signed";
 
-            for (@zone_sig_content) {
-                if (m#SOA.*[0-9]{14}#) {
-                    s#.*([0-9]{10})([0-9]{4}).*#$1#;
-                    if ($_ < $time) {
-                        push @new_serial, $zone;
-                    }
-                }
-            }
-        }
+	open(my $fh, "$dir/$zone.signed") or die "Can't open $dir/$zone.signed: $!\n";
+	push @r, $zone if
+	    /RRSIG\s+SOA[\d ]+(\d{10})\d{4}\s+\(/ ~~ [<$fh>]
+	    and $1 < $time;
     }
+
+    return @r;
 }
 
 sub sign_zone {
@@ -279,47 +288,35 @@
     print "** zonekonfiguration erzeugt\n";
 }
 
-sub update_index {
+sub update_index($) {
+    my $indexzone = shift;
 
-    # aktualisiert die indexzone;
-    our @new_serial;
-    our $indexzone;
-    my @iz_content_old;
-    my @iz_content_new;
+    my @iz;
 
-    open(INDEXZONE, "$config{master_dir}/$indexzone/$indexzone")
-      or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
-    @iz_content_old = <INDEXZONE>;
-    close(INDEXZONE);
-
-    for (@iz_content_old) {
-        unless (m#ZONE::#) {
-            push @iz_content_new, $_;
-        }
+    {
+        open(my $fh, "$config{master_dir}/$indexzone/$indexzone")
+          or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
+        chomp(@iz = grep !/ZONE::/ => <$fh>);
     }
 
     for my $dir (glob "$config{master_dir}/*") {
-        my $zone     = basename($dir);
-        my $info_end = "::sec-off";
-
-        if (-e "$dir/.keycounter") {
-            $info_end = "::sec-on";
-        }
-
-        my $iz_line = "\t\tIN TXT\t\t\"ZONE::$zone$info_end\"\n";
-
-        push @iz_content_new, $iz_line;
+        my $zone = basename($dir);
+        my $info = -e ("$dir/.keycounter") ? "sec-on" : "sec-off";
+        push @iz, join "::", "\t\tIN TXT\t\t\"ZONE", $zone, $info;
     }
 
-    open(INDEXZONE, ">$config{master_dir}/$indexzone/$indexzone")
-      or die "$config{master_dir}/$indexzone/$indexzone: $!\n";
-    print INDEXZONE @iz_content_new;
-    close(INDEXZONE);
+    {
+        my $fh = File::Temp->new(DIR => "$config{master_dir}/$indexzone")
+          or die "Can't create tmpdir: $!\n";
+        print $fh join "\n" => @iz, "";
+        rename($fh->filename => "$config{master_dir}/$indexzone/$indexzone")
+          or die "Can't rename "
+          . $fh->filename
+          . " to $config{master_dir}/$indexzone/$indexzone: $!\n";
+    }
 
-    # fuegt die index-zone in die liste damit der serial erhoet wird
-    push @new_serial, $indexzone;
-
-    print "** index-zone aktualisiert \n";
+    say "** index-zone aktualisiert";
+    return $indexzone;
 }
 
 sub file_entry {
@@ -589,7 +586,7 @@
 
 =head1 SYNOPSIS
 
- update-serial [zone...]
+ update-serial [options] [zone...]
 
 =head1 DESCRIPTION
 
@@ -598,6 +595,13 @@
 
 =head1 OPTIONS
 
+=over
+
+=item B<--sign-alert-time> I<days>
+
+
+=back
+
 The common options B<-h>|B<--help>|B<-m>|B<--man> are supported.
 
 =head1 AUTHOR