>> Is ODS enforcer polling for a specific trigger to fire each script?
>
> It decides based on its internal state. When a KSK is ready to be
> submitted to the parent the <DelegationSignerSubmitCommand> script
> will run. After that it waits for an external signal (ds-ssen). Given
> by either the operator of a script.
>
>> Or do we need to add polling of some sort in the scripts themselves? 
>
> OpenDNSSEC does not poll the parent nameservers to see that DS
> availability. So if you fully want to automate a rollover you will need
> to do some polling yourself before you call ds-ssen.

Indeed.  To do this checking with my OpenDNSSEC 1.4.x installation, I
use the attached script as a component in the setup, and do this polling
via cron for zones where the status says "waiting for ds-seen".  It must
be run by a user which can do "ods-ksmutil key export".

Regards,

- HÃ¥vard
#! /usr/bin/perl

# $Id: ds-ok.pl,v 1.5 2016/11/30 09:31:49 he Exp $

# Verify that all the parent name servers reply with the correct DS
# record for a given zone.

use strict;

use Net::DNS;
use Net::DNS::SEC;

use Getopt::Std;

sub get_ds_from_ods {
    my($z) = @_;
    my($in);
    my(@ret);
    
    open($in, "ods-ksmutil key export --zone $z " .
         "--verbose --ds --keystate ready |") ||
        die "Could not run ods-ksmutil to get DS records from OpenDNSSEC: $!";
    while(<$in>) {
        chomp;
        @_ = split;
        if (($z . ".") =~ /^$_[0]$/) {
            my $ds = join(" ", @_[4..$#_]);
            push(@ret, $ds);
        }
    }
    close($in);
    return @ret;
}

our $local_ns = Net::DNS::Resolver->new(
    recurse => 1,
    );

sub get_parent_domain {
    my($z) = @_;

    if ($z !~ /\.$/) {
        $z .= ".";              # Absolute DNS name
    }

    my @c = split(/\./, $z);
    shift(@c);

    while(@c) {
        my $qn = join(".", @c) . ".";
        if (&has_nameservers($qn)) {
            return $qn;
        }
        shift(@c);
    }
}

sub has_nameservers {
    my($z) = @_;
    my(@ns);

    @ns = &nameservers($z);

    return ($#ns > 0);
}

sub nameservers {
    my($z) = @_;
    my(@ns);

    my $repl = $local_ns->query($z, "NS");
    if ($repl) {
        foreach my $a ($repl->answer) {
            if ($a->type eq "NS") {
                push(@ns, $a->rdstring);
            }
        }
        return @ns;
    }
    return undef;
}

sub keytag {
    my($ds) = @_;

    my @c = split(/\./, $ds);

    return $c[0];
}

sub get_dses_from {
    my($ns, $name) = @_;
    my(@dses);

    my $res = Net::DNS::Resolver->new (
        nameservers => [ $ns ],
        recurse => 0,
        );

    my $ans = $res->query($name, "DS");
    if ($ans) {
        foreach my $a ($ans->answer) {
            if ($a->type eq "DS") {
                my($ds) = join(" ",
                               ($a->keytag,
                                $a->algorithm,
                                $a->digtype,
                                $a->digest));
                push(@dses, $ds);
            }
        }
        return @dses;
    } else {
        return undef;
    }
}

sub ds_matches {
    my($ds, @match) = @_;

    foreach my $m (@match) {
        if ($ds eq $m) {
            return 1;
        }
    }
    return 0;
}

sub OK_ds_from_parent {
    my($z) = @_;

    my($p) = &get_parent_domain($z);
    my @nses = &nameservers($p);
    my @ODS_ds = &get_ds_from_ods($z);

    our($opt_a);

    my($err) = 0;

    if (!@ODS_ds) {
        printf(STDERR
               "No DS records from OpenDNSSEC for %s.\n" .
               "No keys in ready state?\n", $z);
        return 0;
    }

    foreach my $ns (@nses) {
        my @dses = &get_dses_from($ns, $z);
        my $match = 0;
        foreach my $ds (@dses) {
            if (&ds_matches($ds, @ODS_ds)) {
                $match = 1;
            }
        }
        if (! $match) {
            printf(STDERR "No matching DS for %s from %s\n", $z, $ns);
            if (!defined($opt_a)) {
                return undef;
            } else {
                $err++;
            }
        } else {
            printf("OK DS for %s from %s\n", $z, $ns);
        }
    }
    if ($opt_a) {
        return($err == 0);
    }
    return 1;
}

#
# Main
#

our $opt_a;

getopts("a");

my $z = $ARGV[0];

if (&OK_ds_from_parent($z)) {
    printf("All parent NSes return OK DS records for %s\n", $z);
    printf("KSK for %s can be signalled with ds-seen\n", $z);
    exit(0);
}
exit(1);
_______________________________________________
Opendnssec-user mailing list
[email protected]
https://lists.opendnssec.org/mailman/listinfo/opendnssec-user

Reply via email to