Hello,

I've created three scripts that parse the XML config from ODS and
create a BIND9 dnssec-signzone commandline that is (or should be)
identical to the ODS signer.

Disclaimer: these scripts are not tested by SIDN and haven't seen
production (yet).

The included README reads:

    BIND Alternative (Altbind)

    These scripts look at the XML from OpenDNSSEC and use that
    to import the relevant keys from our HSM (Luna's from SafeNet).
    The keys are formatted for BIND9 consumption (.key/.private files).

    Timing meta data from OpenDNSSEC is applied to the keys, then
    dnssec-signzone -S (smart signing) is executed.

    Scripts:
    keyconf.pl
            Create a dnssec-keyfromlabel command line according to
            the signconf.xml from ODS. Notably it sets the publish 
            and active times.

    signconf.pl
            Creates a dnssec-signzone command line equivalent to
            the settings in signconf.xml

    sign-nl:
            Script that calls the above scripts to sign a .nl zone.

The sign-nl script is useless, unless you want to sign a .nl zone, but
it does show how to use keyconf.pl and signconf.pl together.

Feedback (bugs/feature requests) are welcome. The scripts are attached
to this mail.

Kind regards,

--
 Miek Gieben
 Technical Advisor SIDN
#!/usr/bin/perl

# (c) Miek Gieben, SIDN 2011
# GPL v2

use XML::LibXML;
use Getopt::Long;
use warnings;
use strict;

my $xmlfile;
GetOptions("x=s" => \$xmlfile);
my $parser = XML::LibXML->new();
my $dom = $parser->parse_file($xmlfile) or die "Error parsing xml: $!\n";

if ($#ARGV < 2) {
    print "$0: -x xmlconf ENGINE KEYDIR ZONE\n";
    exit 1
}
my $e=" -E $ARGV[0]";
my $keydir=" -K $ARGV[1]";
my $z=" $ARGV[2]";
my $kfl="dnssec-keyfromlabel";

# Look for the keys
#
# Clean old keys and then 
# -P date/offset - publish date, after this date INCLUDE the key
# -A date/offset - active  date, after this date USE the key
my @nodes = $dom->getElementsByTagName("Keys");
my @keys = $nodes[0]->getChildrenByTagName("Key");

foreach my $k (@keys) {
    my $keygen = "";
    my $locator = ($k->getChildrenByTagName("Locator"))[0]->textContent;
    $keygen .= " -l $locator";
    my $flags = ($k->getChildrenByTagName("Flags"))[0]->textContent;
    if ($flags == 257) {
        $keygen .= " -f KSK";
    }

    my $alg = ($k->getChildrenByTagName("Algorithm"))[0]->textContent;
    if ($alg == 8) {
        $keygen .= " -a RSASHA256";
    }
    if ($alg == 10) {
        $keygen .= " -a RSASHA512";
    }

    my $publish = ($k->getChildrenByTagName("Publish"))[0];
    if (defined $publish) {
        $keygen .= " -P now";
    } else {
        $keygen .= " -P none";
        # don't know what bind9 does if a keys is not published AND active?
    }

    my $ksk = ($k->getChildrenByTagName("KSK"))[0];
    my $zsk = ($k->getChildrenByTagName("ZSK"))[0];
    if (defined $zsk or defined $ksk) {
        $keygen .= " -A now";
    } else {
        $keygen .= " -A none";
    }

    print $kfl, $e, $keydir, $keygen, $z, "\n";
}
#!/usr/bin/perl

# (c) Miek Gieben, SIDN 2011
# GPL v2

use XML::LibXML;
use warnings;
use strict;

if ($#ARGV < 3) {
    print "$0: -x xmlconf ENGINE KEYDIR ZONE ZONEFILE\n";
    exit 1
}

my $xmlfile;
GetOptions("x=s" => \$xmlfile);
my $e=" -E $ARGV[0]";
my $keydir=" -K $ARGV[1]";
my $z="-o $ARGV[2]";
my $file=" $ARGV[3]";

# convert a timetstamp PTxx[smh] to seconds
sub timestamp2sec($) {
    my $stamp = shift;
    my ($amount,$what) = $stamp =~ m/PT([0-9]+)([SMH])/;
    if ($what eq "S") { ; } # do nothing
    if ($what eq "M") { $amount *= 60 }
    if ($what eq "H") { $amount *= 3600 }
    $amount
}

print "dnssec-signzone ";
my $parser = XML::LibXML->new();
my $dom = $parser->parse_file($xmlfile) or die "Error parsing xml: $!\n";

#
# Sign the KEYSET only with the KSK
#
print "-x ";

#
# Look for NSEC3
#
my @nodes = $dom->getElementsByTagName("NSEC3");

my @opt = $nodes[0]->getChildrenByTagName("OptOut");
# should only be 1
if (@opt + 0 == -1) {
    print STDERR "$0: No OptOut?\n";
    exit 1
}
if ($opt[0]->toString eq "<OptOut/>") {
    print "-A "
} else {
    print STDERR "$0: No OptOut?\n";
    exit 1;
}

my @h = $nodes[0]->getChildrenByTagName("Hash");
my $algo = ($h[0]->getChildrenByTagName("Algorithm"))[0]->textContent;
my $iter = ($h[0]->getChildrenByTagName("Iterations"))[0]->textContent;
my $salt = ($h[0]->getChildrenByTagName("Salt"))[0]->textContent;
if ($algo eq "" or $iter eq "" or $salt eq "") {
    print STDERR "$0: Some (or all) NSEC3 options are not set\n";
    exit 1
}
print " -3 $salt";
#print " $algo"; # no BIND equivalent
print " -H $iter";

#
# DNS KEY TTL
#
@nodes = $dom->getElementsByTagName("Keys");
my $keyttl = ($nodes[0]->getChildrenByTagName("TTL"))[0]->textContent;
if ($keyttl eq "") {
    print STDERR "$0: No Key TTL found\n";
    exit 1
} else {
    $keyttl = timestamp2sec($keyttl);
    print " -T $keyttl";
}

#
# Signature Jitter
#
@nodes = $dom->getElementsByTagName("Signatures");
my $jitter = ($nodes[0]->getChildrenByTagName("Jitter"))[0]->textContent;
if ($jitter eq "") {
    print STDERR "$0: No Sig jitter found\n";
    exit 1
} else {
    $jitter = timestamp2sec($jitter);
    print " -j $jitter";
}
#
# Offset -> start-time
#
my $starttime = ($nodes[0]->getChildrenByTagName("InceptionOffset"))[0]->textContent;
if ($starttime eq "") {
    print STDERR "$0: No Sig offset found\n";
    exit 1
} else {
    $starttime = timestamp2sec($starttime);
    print " -s -$starttime";
}
#
# Validity -> end-time
my @validity = $nodes[0]->getChildrenByTagName("Validity");
my $endtime = ($validity[0]->getChildrenByTagName("Default"))[0]->textContent;
if ($endtime eq "") {
    print STDERR "$0: No Sig Validity found\n";
    exit 1
} else {
    $endtime = timestamp2sec($endtime);
    print " -e +$endtime";
}

#
# SOA parameters
#
@nodes = $dom->getElementsByTagName("SOA");
my $serial = ($nodes[0]->getChildrenByTagName("Serial"))[0]->textContent;
if ($serial eq "") {
    print STDERR "$0: No serial option found\n";
    exit 1
} else {
    if ($serial ne "keep") {
        print STDERR "$0: serial option should ke \'keep\'\n";
        exit 1
    }
    print " -N $serial";
}

# -S: smart signing, always
# -P: post verify disabled - we have other tools
# -n 10: 10 threads available on the signer
print " -S -P -n 10 ", $e, "$keydir", " $z ", $file, "\n";
#!/bin/bash

DEBUG=false
ZONE=nl
ZONEFILE=/var/lib/opendnssec/unsigned/nl
ENGINE=LunaCA3
KEYDIR="/tmp/keys-$(date +%s)"
XML=/var/lib/opendnssec/signconf/nl.xml

mkdir $KEYDIR

# extremely dumb PIN extractor
PIN=$(grep PIN /etc/opendnssec/conf.xml | sed 's/<PIN>'// | sed 's|</PIN>||' | 
awk '{ print $1 }')

# Login to the SafeNet HSM
echo "Opening connection to the HSM"
if $DEBUG; then
    echo /usr/local/sautil/bin/sautil -v -s 1 -i 10:11 -o -p "<PIN>"
else
    /usr/local/sautil/bin/sautil -v -s 1 -i 10:11 -o -p "$PIN"
fi

keyconf.pl -x $XML $ENGINE $KEYDIR $ZONE | while read line; do
    if $DEBUG; then
        echo $line
    else
        echo $line
        $line
    fi
done

# should have the keys in the right directory now
if $DEBUG; then
    signconf.pl -x $XML $ENGINE $KEYDIR $ZONE $ZONEFILE
else
    signconf.pl -x $XML $ENGINE $KEYDIR $ZONE $ZONEFILE | while read line; do
    echo $line
    $line
done
fi

if [ -f $ZONEFILE.signed ]; then
    echo "Copying zone file"
    Z="$(basename $ZONEFILE)"
    cp "$ZONEFILE".signed /var/lib/opendnssec/signed/"$Z".$$
    mv /var/lib/opendnssec/signed/"$Z".$$ /var/lib/opendnssec/signed/"$Z"
    rm $ZONEFILE.signed
fi

# remove DS set
if [ -f dsset-$ZONE. ]; then
    rm dsset-$ZONE.
fi

# No matter what remove our garbage
if ! $DEBUG; then rm -rf $KEYDIR; fi

echo "Closing connection to the HSM"
if $DEBUG; then
    echo /usr/local/sautil/bin/sautil -v -s 1 -i 10:11 -c
else
    /usr/local/sautil/bin/sautil -v -s 1 -i 10:11 -c
fi
_______________________________________________
Opendnssec-user mailing list
[email protected]
https://lists.opendnssec.org/mailman/listinfo/opendnssec-user

Reply via email to