[Opendnssec-user] Is there script for checking if DS is in TLD

Havard Eidnes he at uninett.no
Tue Mar 8 15:35:28 UTC 2016


>> Am 28.08.2014 um 10:29 schrieb Bas van den Dikkenberg
>> <bas at Dikkenberg.net <mailto:bas at Dikkenberg.net>>:
>>>
>>> Does anyone have script to check if the DS records are published at
>>> the TLD, and if so do a ds-seen.
>>>
>>> I want to automate the ds-seen process

And to add some diversity:

The attached perl script is what we use to check if a given
zone's DS record has been published by all the name servers for
the parent zone.  It automatically figures out itself what the
parent zone is, it does not have to be a TLD.

This script must be run on the OpenDNSSEC host and the user
running it must have sufficient permissions to do "ods-ksmutil
key export".

This is then used in a wrapper script (not supplied here, could
be sent after some minor cleanup) which lists KSKs which are in a
different state than "active" and warns of any required actions
(publishing DS records e.g.).

Regards,

- Håvard
-------------- next part --------------
#! /usr/bin/perl

# $Id: ds-ok.pl,v 1.4 2015/08/13 11:37:44 he Exp he $

# 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;

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);

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

    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);
	    return undef;
	} else {
	    printf("OK DS for %s from %s\n", $z, $ns);
	}
    }
    return 1;
}

#
# Main
#

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);


More information about the Opendnssec-user mailing list