#!/usr/bin/python # -*- coding: utf-8 -*- import sys import time import datetime from josef_lib import * import argparse import json import base64 import subprocess try: from josef_leveldb import * import leveldb except: print "No database support found." from datetime import datetime as dt import ast from monitor_conf import DB_PATH, MONITORED_DOMAINS, OUTPUT_DIR, ERROR_STR 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 = compare_lists(new,old) if len(added_items) != 0: self.log(str(len(added_items)) + " new item(s):") for item in added_items: self.log("(ADDED) " + str(item)) if len(removed_items) != 0: self.log(str(len(removed_items)) + " expired item(s):") for item in removed_items: self.log("(EXPIRED) " + 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 + ") " return s # 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, issuer=None): # print domain try: raw = db_lookup_domain(DB_PATH, domain) except: return [] 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: try: tmp_issuer = entry["issuer"].split("CN=")[1] except: if "issuer" in entry: tmp_issuer = entry["issuer"] else: tmp_issuer = "No Issuer Found" try: tmp_subject = entry["subject"].split("CN=")[1] except: if "subject" in entry: tmp_subject = entry["subject"] else: tmp_subject = "No Subject Found" me = monitored_entry(tmp_subject, \ tmp_issuer, \ entry["log"], \ valid, \ entry["leaf_hash"]) if get_cert: print get_full_cert(entry) if "index" in entry: print "INDEX:", entry["index"] 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, args.issuer) 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()