added automatic key-rollover-function in new update-serial-script
authorasuess@dns.net.schlittermann.de
Thu, 02 Dec 2010 16:46:17 +0100
changeset 37 d3158de72598
parent 36 6847290f1155
child 38 d50f6874b7ab
added automatic key-rollover-function in new update-serial-script
dnstools.conf
update-serial
--- a/dnstools.conf	Thu Dec 02 09:38:16 2010 +0100
+++ b/dnstools.conf	Thu Dec 02 16:46:17 2010 +0100
@@ -2,7 +2,7 @@
 master_dir = /etc/bind/master		# Verzeichnis für die einzelnen Zonen-Verzeichnisse
 zone_conf_dir = /etc/bind/zones.d	# Verzeichnis für die Zonen-Konfigurationdateien
 
-key_counter_end = 40			# Anzahl der Signierungen bis zum Key-Rollover
+key_counter_end = 15			# Anzahl der Signierungen bis zum Key-Rollover
 sign_alert_time = 168			# Warn-Zeitraum vor dem Ablauf einer Zone-Signatur in h
 abl_zeit = 24				# Dauer des Key-Rollover (2 Schluessel) in h
 
--- a/update-serial	Thu Dec 02 09:38:16 2010 +0100
+++ b/update-serial	Thu Dec 02 16:46:17 2010 +0100
@@ -304,21 +304,239 @@
     if (`rndc reload`) {print "** reload dns-server \n"};
 }
 
+sub to_begin_ro {
+    # gibt alle zonen mit abgelaufenen keycounter in die liste @begin_ro_list
+    our @begin_ro_list;
+    our $master_dir;
+    our $key_counter_end;
+    our @new_serial;
+    my $zone;
+
+    while (<$master_dir/*>) {
+        chomp( $zone = $_ );
+        my $key;
+
+        unless (-f "$zone/.keycounter" ) {next;}
+
+        open( KEY, "$zone/.keycounter" ) or die "$zone/.keycounter: $!\n";
+        $key = <KEY>;
+        close(KEY);
+
+        # vergleicht den wert aus der keycount-datei mit dem wert aus der
+        #dnstools.conf (key_counter_end)
+        if ( $key_counter_end <= $key ) {
+            $zone =~ s#($master_dir/)(.*)#$2#;
+            push @begin_ro_list, $zone;
+        }
+    }
+}
+
+sub to_end_ro {
+    # funktion ueberprueft ob ein keyrollover fertig ist
+    # die bedingung dafuer ist das:
+    # - eine datei .index.zsk vorhanden ist
+    # - die datei .index.zsk vor mehr x stunden geaendert wurde
+    # - die datei .index.zsk ueber mehr als zwei zeilen gross ist
+    our $master_dir;
+    our @end_ro_list;
+    our $ablauf_zeit;
+    chomp( my $now_time = `date +%s` );
+
+    for (<$master_dir/*>) {
+        my $zone = $_;
+        $zone =~ s#($master_dir/)(.*)#$2#;
+
+        my @index = ();
+        my $index_wc;
+        my @status;
+
+        # prueft nach der ".index.zsk"-datei und erstellt den zeitpunkt
+        # an dem das key-rollover endet. - $status[9]
+        if ( -e "$master_dir/$zone/.index.zsk" ) {
+            @status = stat("$master_dir/$zone/.index.zsk");
+            $status[9] += ( 3600 * $ablauf_zeit );
+        }
+        else { next; }
+
+        # $status[9] ist der zeitpunkt an dem der key-rollover endet
+        # prueft ob das key-rollover-ende erreicht ist
+        unless ( $status[9] < $now_time ) { next;}
+
+        # prueft die anzahl der schluessel in der .index.zsk
+        open( INDEX, "$master_dir/$zone/.index.zsk" )
+            or die "$master_dir/$zone/.index.zsk: $!\n";
+        @index    = <INDEX>;
+        $index_wc = @index;
+        close(INDEX);
+        if ( $index_wc > 1 ) {push @end_ro_list, $zone;}
+    }
+}
+
+sub begin_ro {
+    # anfang des key-rollovers
+    our @begin_ro_list;
+    our $master_dir;
+    our @new_serial;
+
+    for ( &del_double( @begin_ro_list ) ) {
+        #erzeugt zsks
+        my $zone = $_;
+        my $zpf   = "$master_dir/$zone";
+        my @index;
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        my $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
+
+        open( INDEX, ".index.zsk" ) or die "$zpf/.index.zsk: $!\n";
+        @index = <INDEX>;
+        close(INDEX);
+
+        push @index, $keyname;
+        if ( @index > 2 ) { shift(@index); }
+
+        open( INDEX, ">.index.zsk" ) or die "$zpf/.index.zsk: $!\n";
+        print INDEX @index;
+        close(INDEX);
+
+        chomp($keyname);
+        print " * $zone: neuer ZSK $keyname erstellt\n";
+
+        open( KC, ">.keycounter" ) or die "$zpf/keycounter: $!\n";
+        print KC "0";
+        close(KC);
+
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+        push @new_serial, $zone;
+    }
+}
+
+sub key_to_zonefile {
+    our $master_dir;
+    my $zone = $_[0];
+    my $zpf = "$master_dir/$zone";
+    my @old_content;
+    my @new_content = ();
+
+    open(ZONEFILE, "<$zpf/$zone");
+    @old_content = <ZONEFILE>;
+    close(ZONEFILE);
+
+    for (@old_content) {
+        unless (m#INCLUDE.*key#) { push @new_content, $_; }
+    }
+
+    for (<$zpf/*>) {
+        if (m#(.*\/)(K.*\.key)#) {
+            push @new_content, "\$INCLUDE \"$2\"\n";
+        }
+    }
+    open( ZONEFILE, ">$zpf/$zone" ) or die "$zpf/$zone: $!\n";
+    print ZONEFILE @new_content;
+    close(ZONEFILE);
+}
+
+sub kill_useless_keys {
+    # die funktion loescht alle schluessel die nicht in der index.zsk
+    # der uebergebenen zone stehen
+    our $master_dir;
+    my $zone     = $_[0];
+    my @keylist  = ();
+    my $zpf      = "$master_dir/$zone";
+
+    open (INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
+    @keylist = <INDEX>;
+    close(INDEX);
+    open (INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
+    push @keylist, <INDEX>;
+
+    # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie
+    # besser vergleichen zu koennen.
+    for ( @keylist ) {
+        chomp;
+        s#K.*\+.*\+(.*)#$1#;
+    }
+
+    # prueft alle schluesseldateien (ksk, zsk) ob sie in der jeweiligen
+    # indexdatei beschrieben sind. wenn nicht werden sie geloescht.
+    for (`ls $master_dir/$zone/K*[key,private]`) {
+        chomp;
+        my $file = $_;
+        my $rm_count = 1;
+        my $keyname;
+        for (@keylist) {
+            if ( $file =~ /$_/ ) { $rm_count = 0;}
+        }
+        if ($rm_count == 1) {
+            unlink "$file";
+            if ($file =~ /$zpf\/(.*\.key)/ ) {
+                print " * $zone: Schluessel $1 entfernt \n";
+            }
+        }       
+    }
+}
+
+sub end_ro {
+    our @end_ro_list;
+    our $master_dir;
+    our @new_serial;
+    my @content;
+
+    for (@end_ro_list) {
+        my $zone = $_;
+        my $count = 0;
+        my @content;
+        my $last_key;
+
+        open (INDEX, "<$master_dir/$zone/.index.zsk");
+        @content = <INDEX>;
+        close(INDEX);
+
+        for (@content) {
+            $count++;
+            $last_key = $_;
+        }
+        if ($count > 1) {
+            open (INDEX, ">$master_dir/$zone/.index.zsk");
+            print INDEX $last_key;
+            close (INDEX);
+        }
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+        push @new_serial, $zone;
+    }
+}
+
 
 &read_conf;
 
 our %config;
 our @new_serial;     # liste fuer neuen serial
+our @begin_ro_list;  # liste mit zonen deren key-rollover beginnt
+our @end_ro_list;    # liste mit zonen deren key-rollover fertig ist
 our $master_dir      = $config{master_dir};
 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;
 &changed_zone;
 &sign_end;
 
+&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
+}
+
+if (@end_ro_list) {
+    &end_ro; # eine rollover-end-squenz
+}
+
 if (@new_serial) {
     &update_index; # index zone aktuallisieren
     &update_serial; # serial aktuallisieren
@@ -328,4 +546,3 @@
 &file_entry;  # bearbeitet die file-eintraege der konfigurations-datei
 &mk_zone_conf; # konfiguration zusammenfuegen
 &server_reload; # server neu laden
-