#!/usr/bin/python # -*- coding: utf-8 -*- import sys import time import datetime from josef_lib import * import leveldb import argparse import json import base64 import subprocess from josef_leveldb import * from datetime import datetime as dt import ast from monitor_conf import DB_PATH, MONITORED_DOMAINS, OUTPUT_DIR class monitored_domain: def __init__(self, url): self.url = url self.entries = [] def __eq__(self, other): return self.url == other.url def log(self, string): s = time.strftime('%Y-%m-%d, %H:%M:%S') + " " + string with open(OUTPUT_DIR + "monitor.log", 'a') as f: f.write(s + "\n") f.close() def set(self): self.entries = db_monitor_domain(self.url, None, True, None) self.log("Got " + str(len(self.entries)) + " certs for " + self.url) def update(self): new = db_monitor_domain(self.url, None, True, None) self.compare_and_log_entries(new, self.entries) self.entries = new def to_dict(self): d = {} d["url"] = self.url entries = [] for e in self.entries: entries.append(e.to_dict()) d["entries"] = entries return d def load_entries(self, l): entries = [] for item in l: entries.append(monitored_entry(item["subject"],item["issuer"],item["log"],item["status"],item["leaf_hash"])) self.entries = entries def compare_and_log_entries(self, new, old): added_items = [] removed_items = [] for item in new: if not item in old: added_items.append(item) for item in old: if not item in new: removed_items.append(item) if len(added_items) != 0: self.log(str(len(added_items)) + " new item(s):") for item in added_items: self.log(str(item)) if len(removed_items) != 0: self.log(str(len(removed_items)) + " removed item(s):") for item in removed_items: self.log(str(item)) class monitored_entry: def __init__(self, subject, issuer, log, status, leaf_hash): self.issuer = issuer self.subject = subject self.log = log self.status = status self.leaf_hash = leaf_hash def __eq__(self, other): return self.leaf_hash == other.leaf_hash # return self.leaf_hash == other.leaf_hash and self.status == other.status def __str__(self): s = self.subject + \ " certified by " + self.issuer + \ " (" + self.log + ") " if self.status: return "(VALID) " + s else: return "(NOT VALID) " + s def to_dict(self): d = {} d["issuer"] = self.issuer d["subject"] = self.subject d["log"] = self.log d["status"] = self.status d["leaf_hash"] = self.leaf_hash return d def db_monitor_domain(domain, log=None, exclude_invalid=None, get_cert=None): # print domain raw = db_lookup_domain(DB_PATH, domain) cur_time = dt.now() count_valid = 0 count_expired = 0 count_not_yet_valid = 0 count_all = 0 res = [] for item in raw: try: entry = ast.literal_eval(item) except: print "Failed to parse item: " + item continue success = True not_after_time = dt.strptime(entry["not_after"], "%b %d %H:%M:%S %Y GMT") not_before_time = dt.strptime(entry["not_before"], "%b %d %H:%M:%S %Y GMT") if log: if log in entry["log"]: pass else: success = False if issuer: if issuer in entry["issuer"]: pass: else: success = False if cur_time > not_after_time: valid = False expired = True elif cur_time < not_before_time: valid = False expired = False else: expired = False valid = True # Exclude expired if exclude_invalid and not valid: success = False # Set count matches if success: count_all += 1 if valid: count_valid += 1 elif expired: count_expired += 1 else: count_not_yet_valid += 1 # Print matching if success: me = monitored_entry(entry["subject"].split("CN=")[1], \ entry["issuer"].split("CN=")[1], \ entry["log"], \ valid, \ entry["leaf_hash"]) # print str(me) if get_cert: print get_full_cert(entry) if me not in res: res.append(me) print str(count_all) + " matches found. " \ + str(count_valid) + " valid, " \ + str(count_expired) + " expired and " \ + str(count_not_yet_valid) + " not yet valid for " \ + domain return res if __name__ == "__main__": parser = argparse.ArgumentParser(description="") parser.add_argument('--domain', default=None) parser.add_argument('--log', default=None) parser.add_argument('--issuer', default=None) parser.add_argument('--exclude-invalid', action='store_true') parser.add_argument('--get-cert', action='store_true') args = parser.parse_args() monitored_domains = [] for md in MONITORED_DOMAINS: monitored_domains.append(monitored_domain(md)) if args.domain: db_monitor_domain(args.domain, args.log, args.exclude_invalid, args.get_cert) else: print "Running on " + str(len(monitored_domains)) + " monitored domains." for d in monitored_domains: d.set() for d in monitored_domains: print d.to_dict()