--- /dev/null
+#!/usr/bin/python
+
+import ldns
+import unbound
+from optparse import OptionParser
+import sys
+from datetime import datetime, timedelta
+
+def parse_rrsig_expire(expirestring):
+ expires = datetime(int(expirestring[:4]),
+ int(expirestring[4:6]),
+ int(expirestring[6:8]),
+ int(expirestring[8:10]),
+ int(expirestring[10:12]),
+ int(expirestring[12:14]))
+
+ delta = expires - datetime.utcnow()
+ return delta
+
+def check_dnssec_expire(resolver, name, warn, crit):
+ s, result = resolver.resolve(name)
+ if 0 != s:
+ pass
+
+ s, packet = ldns.ldns_wire2pkt(result.packet)
+ rrsigs = packet.rr_list_by_type(unbound.RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER).rrs()
+ for rrsig in rrsigs:
+ delta = parse_rrsig_expire(str(rrsig.rrsig_expiration()))
+
+ if delta < crit:
+ print "CRIT (%s) %s" % (delta, name)
+ elif delta < warn:
+ print "WARN (%s) %s" % (delta, name)
+
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-n", "--name",
+ action="append", type="string", dest="names",
+ help="DNS Names to check")
+ parser.add_option("-a", "--ancor",
+ action="store", type="string", dest="ancor",
+ default="/etc/unbound/root.key",
+ help="DNSSEC root ancor")
+ parser.add_option("-w", "--warning-days",
+ action="store", type=int, dest="warn", default=5,
+ help="minimum remaining validity in days before a warning is issued")
+ parser.add_option("-c", "--critical-days",
+ action="store", type=int, dest="crit", default=2,
+ help="minimum remaining validity in days before a warning is issued")
+
+
+ opts, _args = parser.parse_args()
+ resolver = unbound.ub_ctx()
+ resolver.add_ta_file(opts.ancor)
+
+ for name in opts.names:
+ check_dnssec_expire(resolver, name, timedelta(opts.warn), timedelta(opts.crit))
+
+if __name__ == "__main__":
+ main()