#!/usr/bin/env python # -*- coding: utf-8 -*- # # Copyright (c) 2015, NORDUnet A/S. # See LICENSE for licensing information. import sys import argparse import json import errno import shutil from datetime import datetime, timedelta from certtools import get_sth NAGIOS_OK = 0 NAGIOS_WARN = 1 NAGIOS_CRIT = 2 NAGIOS_UNKNOWN = 3 DEFAULT_CUR_FILE = 'cur-sth.json' DEFAULT_PREV_FILE = 'prev-sth.json' parser = argparse.ArgumentParser(description="") parser.add_argument('--cur-sth', default=DEFAULT_CUR_FILE, help="File containing current STH (default=%s)" % DEFAULT_CUR_FILE) parser.add_argument('--prev-sth', default=DEFAULT_PREV_FILE, help="File containing previous STH (default=%s" % DEFAULT_PREV_FILE) parser.add_argument('baseurl', help="Base URL for CT server") def print_sth(sth): if sth is None: print "NONE" else: print sth['timestamp'] print sth['sha256_root_hash'] print sth['tree_size'] print sth['tree_head_signature'] def get_new_sth(baseurl): try: sth = get_sth(baseurl) except Exception, e: print e sys.exit(NAGIOS_UNKNOWN) return sth def read_sth(fn): try: f = open(fn) except IOError, errno.ENOENT: return None return json.loads(f.read()) def mv_file(fromfn, tofn): shutil.move(fromfn, tofn) def write_file(fn, sth): open(fn, 'w').write(json.dumps(sth)) def check_age(sth): now = datetime.now() sth_time = datetime.fromtimestamp(sth['timestamp'] / 1000) if now > sth_time + timedelta(0, 6 * 3600): print "CRITICAL: STH older than 6h: ", sth_time sys.exit(NAGIOS_CRIT) if now > sth_time + timedelta(0, 2 * 3600): print "WARNING: STH older than 2h: ", sth_time sys.exit(NAGIOS_WARN) def check_treesize(cur, prev): if prev is not None: if cur['tree_size'] < prev['tree_size']: print "CRITICAL: new tree smaller than previous tree (%d < %d)" % \ (cur['tree_size'], prev['tree_size']) sys.exit(NAGIOS_CRIT) def main(args): if args.cur_sth is None: args.cur_sth = "cur-sth.json" if args.prev_sth is None: args.prev_sth = "prev-sth.json" new = get_new_sth(args.baseurl) cur = read_sth(args.cur_sth) if cur is None or new['sha256_root_hash'] != cur['sha256_root_hash']: if cur is not None: mv_file(args.cur_sth, args.prev_sth) write_file(args.cur_sth, new) cur = new prev = read_sth(args.prev_sth) #print_sth(cur) #print_sth(prev) check_age(cur) check_treesize(cur, prev) # TODO: verify signature # TODO: get and verify consistency proof sys.exit(NAGIOS_OK) if __name__ == '__main__': main(parser.parse_args())