diff --git a/CHANGES b/CHANGES
index 394e45f879..5014103180 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+3702. [func] 'dnssec-coverage -l' option specifies a length
+ of time to check for coverage; events further into
+ the future are ignored. 'dnssec-coverage -z'
+ checks only ZSK events, and 'dnssec-coverage -k'
+ checks only KSK events. (Thanks to Peter Palfrader.)
+ [RT #35168]
+
3701. [func] named-checkconf can now obscure shared secrets
when printing by specifying '-x'. [RT #34465]
diff --git a/bin/python/dnssec-coverage.docbook b/bin/python/dnssec-coverage.docbook
index 7657b080de..91b028de22 100644
--- a/bin/python/dnssec-coverage.docbook
+++ b/bin/python/dnssec-coverage.docbook
@@ -44,11 +44,14 @@
dnssec-coverage
+
+
+ zone
@@ -86,6 +89,16 @@
OPTIONS
+
+ -K directory
+
+
+ Sets the directory in which keys can be found. Defaults to the
+ current working directory.
+
+
+
+
-f file
@@ -100,11 +113,18 @@
- -K directory
+ -l duration
- Sets the directory in which keys can be found. Defaults to the
- current working directory.
+ The length of time to check for DNSSEC coverage. Key events
+ scheduled further into the future than
+ will be ignored, and assumed to be correct.
+
+
+ The value of can be set in seconds,
+ or in larger units of time by adding a suffix: 'mi' for minutes,
+ 'h' for hours, 'd' for days, 'w' for weeks, 'mo' for months,
+ 'y' for years.
@@ -185,6 +205,27 @@
+
+ -k
+
+
+ Only check KSK coverage; ignore ZSK events. Cannot be
+ used with .
+
+
+
+
+
+ -z
+
+
+ Only check ZSK coverage; ignore KSK events. Cannot be
+ used with .
+
+
+
+
+
-c compilezone path
diff --git a/bin/python/dnssec-coverage.py.in b/bin/python/dnssec-coverage.py.in
index 5d2714dedb..da00326990 100755
--- a/bin/python/dnssec-coverage.py.in
+++ b/bin/python/dnssec-coverage.py.in
@@ -15,6 +15,10 @@
# PERFORMANCE OF THIS SOFTWARE.
############################################################################
+# changes 2014-01-08, Peter Palfrader:
+# - support checking only X days into the future.
+# - support checking only KSK keys or only ZSK keys.
+
import argparse
import os
import glob
@@ -506,6 +510,13 @@ def check_events(eventsList, ksk):
eventgroups.append(eventgroup)
for eventgroup in eventgroups:
+ if (args.checklimit and
+ calendar.timegm(eventgroup[0].when) > args.checklimit):
+ print("Ignoring events after %s" %
+ time.strftime("%a %b %d %H:%M:%S UTC %Y",
+ time.gmtime(args.checklimit)))
+ return True
+
(active, published) = \
process_events(eventgroup, active, published)
@@ -548,21 +559,23 @@ def check_zones(eventsList):
zonesfound = True
for alg in eventsList[zone]:
- vspace()
- print("Checking scheduled KSK events for zone %s, algorithm %s..." %
- (zone, algname(alg)))
- if not check_events(eventsList[zone][alg], True):
- foundprob = True
- else:
- print ("No errors found")
+ if not args.no_ksk:
+ vspace()
+ print("Checking scheduled KSK events for zone %s, algorithm %s..." %
+ (zone, algname(alg)))
+ if not check_events(eventsList[zone][alg], True):
+ foundprob = True
+ else:
+ print ("No errors found")
- vspace()
- print("Checking scheduled ZSK events for zone %s, algorithm %s..." %
- (zone, algname(alg)))
- if not check_events(eventsList[zone][alg], False):
- foundprob = True
- else:
- print ("No errors found")
+ if not args.no_zsk:
+ vspace()
+ print("Checking scheduled ZSK events for zone %s, algorithm %s..." %
+ (zone, algname(alg)))
+ if not check_events(eventsList[zone][alg], False):
+ foundprob = True
+ else:
+ print ("No errors found")
if not zonesfound:
print("ERROR: No key events found for %s in '%s'" %
@@ -637,17 +650,28 @@ def parse_args():
help='zone master file', metavar='file')
parser.add_argument('-m', dest='maxttl', type=str,
help='the longest TTL in the zone(s)',
- metavar='int')
+ metavar='time')
parser.add_argument('-d', dest='keyttl', type=str,
- help='the DNSKEY TTL', metavar='int')
+ help='the DNSKEY TTL', metavar='time')
parser.add_argument('-r', dest='resign', default='1944000',
type=int, help='the RRSIG refresh interval '
'in seconds [default: 22.5 days]',
- metavar='int')
+ metavar='time')
parser.add_argument('-c', dest='compilezone',
default=compilezone, type=str,
help='path to \'named-compilezone\'',
metavar='path')
+ parser.add_argument('-l', dest='checklimit',
+ type=str, default='0',
+ help='Length of time to check for '
+ 'DNSSEC coverage [default: 0 (unlimited)]',
+ metavar='time')
+ parser.add_argument('-z', dest='no_ksk',
+ action='store_true', default=False,
+ help='Only check zone-signing keys (ZSKs)')
+ parser.add_argument('-k', dest='no_zsk',
+ action='store_true', default=False,
+ help='Only check key-signing keys (KSKs)')
parser.add_argument('-D', '--debug', dest='debug_mode',
action='store_true', default=False,
help='Turn on debugging output')
@@ -655,6 +679,10 @@ def parse_args():
args = parser.parse_args()
+ if args.no_zsk and args.no_ksk:
+ print("ERROR: -z and -k cannot be used together.");
+ exit(1)
+
# convert from time arguments to seconds
try:
if args.maxttl:
@@ -677,6 +705,17 @@ def parse_args():
except:
pass
+ try:
+ if args.checklimit:
+ lim = args.checklimit
+ r = parse_time(args.checklimit)
+ if r == 0:
+ args.checklimit = None
+ else:
+ args.checklimit = time.time() + r
+ except:
+ pass
+
# if we've got the values we need from the command line, stop now
if args.maxttl and args.keyttl:
return
diff --git a/bin/tests/system/coverage/setup.sh b/bin/tests/system/coverage/setup.sh
index 95b35dd387..0c0fdbc2ff 100644
--- a/bin/tests/system/coverage/setup.sh
+++ b/bin/tests/system/coverage/setup.sh
@@ -105,3 +105,33 @@ zsk2=`$KEYGEN -K $dir -S $zsk1`
# allow only 1 day between publication and activation
$SETTIME -K $dir -P +269d $zsk2 > /dev/null 2>&1
ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 9: KSK goes inactive before successor is active, but checking ZSKs
+dir=09-check-zsk
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+$SETTIME -K $dir -I +9mo -D +1y $ksk1 > /dev/null 2>&1
+ksk2=`$KEYGEN -K $dir -S $ksk1`
+$SETTIME -K $dir -I +7mo $ksk1 > /dev/null 2>&1
+zsk1=`$KEYGEN -K $dir -3 example.com`
+
+# Test 10: ZSK goes inactive before successor is active, but checking KSKs
+dir=10-check-ksk
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +9mo -D +1y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +7mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
+
+# Test 11: ZSK goes inactive before successor is active, but after cutoff
+dir=11-cutoff
+rm -f $dir/K*.key
+rm -f $dir/K*.private
+zsk1=`$KEYGEN -K $dir -3 example.com`
+$SETTIME -K $dir -I +18mo -D +2y $zsk1 > /dev/null 2>&1
+zsk2=`$KEYGEN -K $dir -S $zsk1`
+$SETTIME -K $dir -I +16mo $zsk1 > /dev/null 2>&1
+ksk1=`$KEYGEN -K $dir -3fk example.com`
diff --git a/bin/tests/system/coverage/tests.sh b/bin/tests/system/coverage/tests.sh
index bbc72a062f..a404a4665f 100644
--- a/bin/tests/system/coverage/tests.sh
+++ b/bin/tests/system/coverage/tests.sh
@@ -42,22 +42,38 @@ for dir in [0-9][0-9]-*; do
$COVERAGE $args -K $dir example.com > coverage.$n 2>&1
# check that return code matches expectations
- [ $? -eq $retcode ] || ret=1
+ found=$?
+ if [ $found -ne $retcode ]; then
+ echo "retcode was $found expected $retcode"
+ ret=1
+ fi
# check for correct number of errors
found=`grep ERROR coverage.$n | wc -l`
- [ $found -eq $error ] || ret=1
+ if [ $found -ne $error ]; then
+ echo "error count was $found expected $error"
+ ret=1
+ fi
# check for correct number of warnings
found=`grep WARNING coverage.$n | wc -l`
- [ $found -eq $warn ] || ret=1
+ if [ $found -ne $warn ]; then
+ echo "warning count was $found expected $warn"
+ ret=1
+ fi
# check for correct number of OKs
found=`grep "No errors found" coverage.$n | wc -l`
- [ $found -eq $ok ] || ret=1
+ if [ $found -ne $ok ]; then
+ echo "good count was $found expected $ok"
+ ret=1
+ fi
found=`matchall coverage.$n "$match"`
- [ "$found" = "FAIL" ] && ret=1
+ if [ "$found" = "FAIL" ]; then
+ echo "no match on '$match'"
+ ret=1
+ fi
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi