def main(): # check if there is a given file if (len(sys.argv) != 2): print("\n*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*") print("Missing an argument\nUsage: python3 certtest.py file.json") print("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n") return -1 global json_file, current_cert # delete the file if it exists try: f = open(sys.argv[1], "x") # raise an error if the file exists f.close() except: os.remove(sys.argv[1]) f = open(sys.argv[1], "x") f.close() # open and intialize the file current_cert = 0 json_file = open(sys.argv[1], "w") json_file.write('{') logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(handle_callback, url='wss://certstream.calidog.io/') json_file.write('}') json_file.close() print("There are " + str(current_cert) + " certificates in the file")
def main(): logging.basicConfig(filename='bounty_errors.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s') parser = argparse.ArgumentParser( description="Leverage certificate transparency live feed to monitor for newly issued subdomain cerficates, for domains participating in bug bounty programs", usage="python bounty_monitor.py", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("-l", "--log", dest="log_to_file", default="subdomains", action="store_true", help="Log found subdomains to all_subdomains.log and ones that are live to live_subdomains.log") parser.add_argument("--no_probe_s3_bucket", dest="probe_s3_bucket", default=True, action="store_true", help="Do not attempt to guess associated S3 buckets based on the new subdomain name") parser.add_argument("-t", "--threads", metavar="", type=int, dest="threads", default=10, help="Number of threads to spawn.") parser.add_argument("-d", "--days", metavar="", type=int, dest="subdomain_age", default=90, help="Number of days since current certificate registration.") parser.add_argument("-v", "--verbose", metavar="", type=int, dest="verbose", default=False, help="Increased verbosity, prints all identifed subdomains matching the bugbounty list") args = parser.parse_args() logging.disable(logging.WARNING) init_db() for _ in range(1, args.threads): thread = MonitorWorker(MONITOR_QUEUE,args.subdomain_age,args.log_to_file,args.verbose) thread.setDaemon(True) thread.start() # TODO: check if previously found subdomain is alive every 30 minutes print ("Waiting for certstream events - this could take a few minutes to queue up...") certstream.listen_for_events(monitor) # this is blocking, so I added some sleep.. print ("Qutting - waiting for threads to finish up...") MONITOR_QUEUE.join()
def main(): """ """ global exclusions global config global url_queue # Check if output directories exist commons.check_path(args) # Print start messages commons.show_summary(args) commons.show_networking(args) # globals: proxies, torsocks # Read config.yaml config = commons.read_config(args) # globals: config # Recompile exclusions exclusions = commons.recompile_exclusions() # globals: exclusions # Create queues url_queue = commons.create_queue("url_queue") # Create threads commons.UrlQueueManager(args, url_queue) # Listen for events via Certstream print(colored("Connecting to Certstream...\n", "yellow", attrs=["bold"])) certstream.listen_for_events(message_callback=callback, url=args.ctl_server, on_open=on_open)
def main(): args = parser.parse_args() # Ignore broken pipes signal(SIGPIPE, SIG_DFL) log_level = logging.INFO if args.verbose: log_level = logging.DEBUG logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=log_level) q = queue.Queue() t = threading.Thread(target=uploader, args=(q, )) t.start() def _handle_messages(message, context): q.put(message, block=False) #sys.stdout.flush() #sys.stdout.write(json.dumps(message) + "\n") #sys.stdout.flush() certstream.listen_for_events(_handle_messages, args.url, skip_heartbeats=True)
def main(): """ """ global exclusions global suspicious global url_queue # Check if output directories exist commons.check_path(args) # Print start messages commons.show_summary(args) commons.show_networking(args, uagent) # Read suspicious.yaml and external.yaml suspicious = commons.read_externals() # Recompile exclusions exclusions = commons.recompile_exclusions() # Create queues url_queue = commons.create_queue("url_queue") # Create threads commons.UrlQueueManager(args, url_queue, uagent) # Listen for events via Certstream print(colored("Connecting to Certstream...\n", "yellow", attrs=["bold"])) certstream.listen_for_events(message_callback=callback, url="wss://certstream.calidog.io", on_open=on_open)
def main(): logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(print_callback, url='wss://certstream.calidog.io')
def main(): parser = argparse.ArgumentParser(description="Find interesting Amazon S3 Buckets by watching certificate transparency logs.", usage="python bucket-stream.py", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("--only-interesting", action="store_true", dest="only_interesting", default=False, help="Only log 'interesting' buckets whose contents match anything within keywords.txt") parser.add_argument("--skip-lets-encrypt", action="store_true", dest="skip_lets_encrypt", default=False, help="Skip certs (and thus listed domains) issued by Let's Encrypt CA") parser.add_argument("-t", "--threads", metavar="", type=int, dest="threads", default=20, help="Number of threads to spawn. More threads = more power.") parser.add_argument("-l", "--log", dest="log_to_file", default=False, action="store_true", help="Log found buckets to a file buckets.log") parser.parse_args(namespace=ARGS) logging.disable(logging.WARNING) if not CONFIG['aws_access_key'] or not CONFIG['aws_secret']: print("Enter AWS keys in config.yaml to find even more buckets!") for _ in range(1, ARGS.threads): BucketWorker(BUCKET_QUEUE).start() print("Waiting for certstream events - this could take a few minutes to queue up...") certstream.listen_for_events(listen) #blocking print("Qutting - waiting for threads to finish up...") BUCKET_QUEUE.join()
def _consume(self): """ Start consuming the data from certstream. """ self.stopped = False # pylint: disable=unnecessary-lambda certstream.listen_for_events(lambda m, c: self._callback(m, c), url='wss://certstream.calidog.io')
def connectFireHose(requestedType): if requestedType == "single_domain": certstream.listen_for_events(retrieveOneDomain_callback, "wss://certstream.calidog.io") else: print("LID_event_retrieval.py > ERROR : Incorrect type specified", file=sys.stderr) raise (ValueError)
def run(self): event_handler = Handler() self.observer.schedule(event_handler, self.DIR, recursive=False) self.observer.start() try: #with suppressOutput(): certstream.listen_for_events(print_callback, url=url) while True: time.sleep(2) except: self.observer.stop() self.observer.join()
def main(config_file): load_config_file(config_file) # Start streaming certificates print("Starting to stream certificates... this can take a few minutes...") print("sending test") callback( { 'message_type': "certificate_update", 'data': { 'leaf_cert': { 'all_domains': ["myethrwallet.com"] } } }, {}) certstream.listen_for_events(callback, on_error=on_error) print()
def main(): global SQL try: # Config ConfAnalysis(ConfFile) P = VerifyPath() # Create files P.VerifyOrCreate(DBFile) P.VerifyOrCreate(LogFile) # Database SQL = SqliteCmd(DBFile) SQL.SQLiteCreateTable(TABLEname) # logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) # file handler (10MB, 10 rotations) format = logging.Formatter( '[%(levelname)s:%(name)s] %(asctime)s - %(message)s') file_handler = RotatingFileHandler(LogFile, 'a', 10000000, 10) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(format) logger.addHandler(file_handler) # term handler stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) logger.addHandler(stream_handler) # Work, connection to the CT logs aggregator (ACTServer), through a HTTP proxy if configured into configuration file logging.info("Looking for these strings: " + SearchKeywords + ", detection threshold: " + str(DetectionThreshold)) certstream.listen_for_events(print_callback, ACTServer, http_proxy_host=Proxy_Host, http_proxy_port=Proxy_Port, http_proxy_auth=(Proxy_Username, Proxy_Password)) print_callback() SQL.SQLiteClose() except: err = sys.exc_info() logging.error(" Main error " + str(err))
def main(): parser = argparse.ArgumentParser(description='An extension for certstream allowing for output to disk and monitoring of the stream', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('-o', dest='output_directory', type=_validate_directory, default=os.getcwd(), help='the output directory logs, alerts, and certificate information') parser.add_argument('-v', dest='logging_level', action='store_const', const=logging.DEBUG, default=logging.INFO, help='enable debug logging') parser.add_argument('-u', dest='url', default="wss://certstream.calidog.io", help='Connect to a certstream server.') storage_group = parser.add_argument_group('certificate storage', 'options related to outputting the certificate stream to disk') storage_group.add_argument('-s', dest='storage_stream', action='store_true', default=False, help='enable storage of the stream') monitor_group = parser.add_argument_group('certificate monitoring', 'options related to monitoring the certificate stream for domains of importance') monitor_group.add_argument('-m', dest='monitor_stream', action='store_true', default=False, help='enable custom monitoring of the stream') monitor_group.add_argument('-r', dest='monitor_regex', default='.+nl$|.+uk$', help='series of regular expressions joined by a |') cli_args = parser.parse_args() # setup logging logging.basicConfig(format='%(levelname)-8s %(message)s', level=cli_args.logging_level) # ignore broken pipes signal(SIGPIPE, SIG_DFL) def _process_certificate(message, context): data_source = message['data']['source']['name'] certificate_cn = message['data']['leaf_cert']['subject']['CN'] certificate_domains = '|'.join(message['data']['leaf_cert']['all_domains']) message_tuple = (data_source, certificate_cn, certificate_domains) if cli_args.storage_stream: storage_queue.put(message_tuple) if cli_args.monitor_stream: monitor_queue.put(message_tuple) # storage process if cli_args.storage_stream: storage_queue = Queue() storage_process = Process(target=_storage_process, daemon=True, args=(storage_queue,cli_args.output_directory)) storage_process.start() logging.info('starting storage process with pid %s', storage_process.pid) # monitor process if cli_args.monitor_stream: monitor_queue = Queue() monitor_process = Process(target=_monitor_process, daemon=True, args=(monitor_queue,cli_args.output_directory,cli_args.monitor_regex)) monitor_process.start() logging.info('starting monitor process with pid %s', monitor_process.pid) # certstream callback certstream.listen_for_events(_process_certificate, cli_args.url, skip_heartbeats=True)
def main(): logging.basicConfig(format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) th=config['monitor']['threads'] for _ in range(1, th): thread = MonitorWorker(MONITOR_QUEUE) thread.setDaemon(True) thread.start() print(ascii) print("Checking elasticsearch...") # utils.check_if_online() print("Config:\nThreads: "+str(config['monitor']['threads'])+"\n"+"log file: " + config['log_file']) print("Waiting for certstream events - this could take a few minutes to queue up...") certstream.listen_for_events(monitor, url='wss://certstream.calidog.io/') # this is blocking, so I added some sleep.. print("Qutting - waiting for threads to finish up...") MONITOR_QUEUE.join()
def __call__(self, mode='certstream'): """ Handler for mode of deployment (certstream or manual). Args: mode (string): Method of deployment ('certstream' or 'manual') Raises: ValueError: Invalid mode selected (must be certstream or manual). """ # Fetch config, DB, assign config parameters to objects used by this class. if mode == 'manual': self._manual_mode() elif mode == 'certstream': # Launch certstream. tqdm.tqdm.write("[*] Analysis started - press CTRL+C to quit at anytime.") certstream.listen_for_events(self._certstream_mode) else: raise ValueError("Invalid mode selected - please choose 'manual' or 'certstream'.")
def main(): global SQL try: # Config ConfAnalysis(ConfFile) P = VerifyPath() # Create files P.VerifyOrCreate(DBFile) P.VerifyOrCreate(LogFile) # Database SQL = SqliteCmd(DBFile) SQL.SQLiteCreateTable(TABLEname) # logging logger = logging.getLogger() logger.setLevel(logging.DEBUG) # file handler (10MB, 10 rotations) format = logging.Formatter( '[%(levelname)s:%(name)s] %(asctime)s - %(message)s') file_handler = RotatingFileHandler(LogFile, 'a', 10000000, 10) file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(format) logger.addHandler(file_handler) # term handler stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) logger.addHandler(stream_handler) # Work logging.info("Looking for these strings: " + SearchString) certstream.listen_for_events(print_callback, "wss://certstream.calidog.io") print_callback() SQL.SQLiteClose() except: err = sys.exc_info() logging.error(" Main error " + str(err))
def find(hostname): port = 443 cert = ssl.get_server_certificate((hostname, port), ssl_version=ssl.PROTOCOL_TLSv1) x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) rootCA = x509.get_issuer().get_components() subject = x509.get_subject().get_components() scan['signature'] = x509.get_signature_algorithm().decode("utf-8") scan['serial_number'] = x509.get_serial_number() scan['subject'] = combine(subject) scan['rootCA'] = combine(rootCA) print("\n----------------\n{}\n{}\n{}\n----------------\n\n".format( hostname, scan['subject']['O'], scan['serial_number'])) logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(similar, url='wss://certstream.calidog.io/')
def __init__(self): self.domainlookup = DomainLookup() certstream.listen_for_events(self.print_callback, url='wss://certstream.calidog.io/')
# -*- coding:utf-8 -*- import logging import sys import datetime import certstream def print_callback(message, context): logging.debug("Message -> {}".format(message)) if message['message_type'] == "heartbeat": return if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] if len(all_domains) == 0: domain = "NULL" else: domain = all_domains[0] sys.stdout.write(u"[{}] {} (SAN: {})\n".format(datetime.datetime.now().strftime('%m/%d/%y %H:%M:%S'), domain, ", ".join(message['data']['leaf_cert']['all_domains'][1:]))) sys.stdout.flush() logging.basicConfig(format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(print_callback)
def stream_handling(): logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(handle_callback, url='wss://certstream.calidog.io/')
streamdata = ujson.loads(data) if 'data' in streamdata: cert = base64.b64decode(streamdata['data']['leaf_cert']['as_der'].encode('utf-8')) cert = asn1crypto.x509.Certificate.load(cert) if cert is not None and cert.key_usage_value is not None: db.insert_cert(domain_names=streamdata['data']['leaf_cert']['all_domains'], cert_issuer=cert.issuer.human_friendly, cert_notbefore=datetime.fromtimestamp(streamdata['data']['leaf_cert']['not_before']), cert_notafter=datetime.fromtimestamp(streamdata['data']['leaf_cert']['not_after']), cert_seen=datetime.fromtimestamp(streamdata['data']['seen']), cert_source=streamdata['data']['source']['url'], cert_serial=streamdata['data']['leaf_cert']['serial_number'], cert_fingerprint=streamdata['data']['leaf_cert']['fingerprint'], cert_allowed_digitalsignature=True if 'digital_signature' in cert.key_usage_value.native else False, cert_allowed_nonrepudiation=True if 'non_repudiation' in cert.key_usage_value.native else False, cert_allowed_keyencipherment=True if 'key_encipherment' in cert.key_usage_value.native else False, cert_allowed_dataencipherment=True if 'data_encipherment' in cert.key_usage_value.native else False, cert_allowed_keyagreement=True if 'key_agreement' in cert.key_usage_value.native else False, cert_allowed_keycertsign=True if 'key_cert_sign' in cert.key_usage_value.native else False, cert_allowed_crlsign=True if 'crl_sign' in cert.key_usage_value.native else False, cert_allowed_encipheronly=True if 'encipher_only' in cert.key_usage_value.native else False, cert_allowed_decipheronly=True if 'decipher_only' in cert.key_usage_value.native else False, cert_signaturealgorithm=cert.signature_algo, cert_algorithm=cert.public_key.algorithm, cert_algorthm_bit_size=cert.public_key.bit_size ) db = MysqlDB() certstream.listen_for_events(parse_cert)
longlist = set() # Add keywords for things you are interested in keywords = {'coronavirus', 'covid'} def callback(message, context): # Callback handler for certstream events (boilerplate from CaliDog Github) if message['message_type'] == "heartbeat": return if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] for domain in all_domains: # Filter domain if we have already seen it (prevent duplication) if domain in longlist: continue longlist.add(domain) # Check if keyword exists if any(kword in domain for kword in keywords): with open(domain_log, 'a') as f: f.write("{}: {}\n".format(str(datetime.datetime.now()), domain)) print(str(datetime.datetime.now()) + ': ' + domain) if __name__ == '__main__': certstream.listen_for_events(callback, url=certstream_url)
def start_certstream(): logger.info("CertStream listener starting...") certstream.listen_for_events(message_callback=certstream_callback, on_open=on_open, on_error=on_error, url='wss://certstream.calidog.io/')
score += 20 return score def callback(message, context): """Callback handler for certstream events.""" if message['message_type'] == "heartbeat": return if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] for domain in all_domains: pbar.update(1) score = score_domain(domain) if score > 100: tqdm.tqdm.write( "\033[91mSuspicious: " "\033[4m{}\033[0m\033[91m (score={})\033[0m".format(domain, score)) with open(log_suspicious, 'a') as f: f.write("{}\n".format(domain)) checkcf(domain) elif score > 200: tqdm.tqdm.write( "Potential: " "\033[4m{}\033[0m\033[0m (score={})".format(domain, score)) certstream.listen_for_events(callback)
#!/usr/bin/python3 import certstream import json import requests import sys # Set the webhook_url to the one provided by Slack when you create the webhook at https://my.slack.com/services/new/incoming-webhook/ #WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"] WEBHOOK_URL = "https://hooks.slack.com/services/YOURSLACKWEBHOOKURL" NEEDLES = ["tesla.com","teslamotors","tyro.com","ebfe.pw","cornmbank.com"] # Search for domains with a keyword in them and write the corresponding certificate to a file def certstream_callback(message, context): if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] for NEEDLE in NEEDLES: if NEEDLE in " ".join(all_domains): sys.stderr.write(":fire: We've detected a new certificate that matches `{}`!:fire:\n```{}```".format(NEEDLE, all_domains)) cn = all_domains[0] slack_data = {'text': ":book: YO! chek this certificate that matches `{}`!:book:\n```{}```".format(NEEDLE, all_domains)} try: response = requests.post(WEBHOOK_URL, json=slack_data) sys.stderr.write(response) except Exception as e: print("Error! {}".format(e)) certstream.listen_for_events(certstream_callback)
format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) logging.info('Connecting to message broker') connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() logging.info('Creating exchange') channel.exchange_declare(exchange='domain', exchange_type='fanout') def callback(message, context): domain = message['data']['leaf_cert']['all_domains'][0] logging.info('Got {}'.format(domain)) channel.basic_publish(exchange='domain', routing_key='', body=domain) try: logging.info('Starting CertStream receiver') certstream.listen_for_events(callback, 'wss://certstream.calidog.io') finally: logging.info('Closing message broker connection') connection.close()
default='http://localhost:9200', help='elasticsearch server to send certificate information to') parser.add_argument( '-cs', default='wss://certstream.calidog.io', help='certstream server to obtain certificate information from') parser.add_argument('-v', dest='logging_level', action='store_const', const=logging.DEBUG, default=logging.WARNING, help='enable debug logging') parser.add_argument('--process_heartbeats', action='store_false', help='start processing heartbeat messages') args = parser.parse_args() # setup logging logging.basicConfig(format='%(levelname)-8s %(message)s', level=args.logging_level) # connect to elastic search logging.info('ingesting to the elastic search endpoint [%s]', args.cs) es = Elasticsearch([args.es]) # connect to and start processing certstream certificates logging.info('monitoring the certstream server [%s]', args.cs) logging.info('heartbeat status [%s]', args.process_heartbeats) certstream.listen_for_events(_process_callback, args.cs, skip_heartbeats=args.process_heartbeats)
def extract_domains(domains): res = [] for domain in domains: for keyword in keywords: if keyword in domain: res.append(domain) return res def print_callback(message, context): domains = message['data']['leaf_cert']['all_domains'] res = extract_domains(domains) if len(res) > 0: print(res) def on_open(instance): # Instance is the CertStreamClient instance that was opened print("Connection successfully established!") def on_error(instance, exception): # Instance is the CertStreamClient instance that barfed print("Exception in CertStreamClient! -> {}".format(exception)) certstream.listen_for_events(print_callback, on_open=on_open, on_error=on_error)
date = datetime.datetime.now().strftime('%m/%d/%y %H:%M:%S') date_until_valid = datetime.datetime.now() + datetime.timedelta( days=30) # add in STIXv2.0 file indicator = Indicator( name="Malicious site (phishing)", labels=["malicious-activity"], pattern="[url:value = '{}']".format(url), created="{}".format(date), valid_from="{}".format(date), valid_until="{}".format(date_until_valid), description= "score=%.2f -- mot-suspects:%.2f url:%.2f whois:%.2f antivirus:%.2f identifiants:%.2f javascript:%.2f date_domaines:%.2f)" % (score, score_suspects, sc, score_whois, score_antivirus, score_ident, score_js, score_domain_date)) mem.add(indicator) mem.save_to_file( "../database/site_database{}.json".format( datetime.datetime.now().date()) ) #end of the function, if the site is a phishing site (score > 0) -> write in STIXv2.0 file else: print(GREEN + url + WHITE + " : " + s + " (score=%.2f)" % score) print(WHITE) if __name__ == "__main__": certstream.listen_for_events(main, "wss://certstream.calidog.io") #
if "webmail." in domain: continue if "webdisk." in domain: continue resolved = await res(domain) print(domain.lower(),"-",resolved,flush = True) outfile = open("output.txt",'a') data = domain.lower()+","+str(resolved)+"\n" outfile.write(data) outfile.close() return def callback(message, context): loop = asyncio.get_event_loop() if message['message_type'] == "heartbeat": return if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] loop.run_until_complete(parse(all_domains)) if __name__ == '__main__': certstream_url = 'wss://certstream.calidog.io' while True: try: certstream.listen_for_events(callback, url=certstream_url,on_error=on_error) except ConnectionResetError: sleep(3) continue except AttributeError: sleep(2) continue
def main(): args = parser.parse_args() # Ignore broken pipes signal(SIGPIPE, SIG_DFL) log_level = logging.INFO if args.verbose: log_level = logging.DEBUG logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=log_level) def _handle_messages(message, context): if args.json: sys.stdout.flush() sys.stdout.write(json.dumps(message) + "\n") sys.stdout.flush() else: if args.disable_colors: logging.debug("Starting normal output.") payload = "{} {} - {} {}\n".format( "[{}]".format( datetime.datetime.fromtimestamp( message['data']['seen']).isoformat()), message['data']['source']['url'], message['data']['leaf_cert']['subject']['CN'], "[{}]".format(", ".join( message['data']['leaf_cert']['all_domains'])) if args.full else "") sys.stdout.write(payload) else: logging.debug("Starting colored output.") payload = "{} {} - {} {}\n".format( termcolor.colored("[{}]".format( datetime.datetime.fromtimestamp( message['data']['seen']).isoformat()), 'cyan', attrs=[ "bold", ]), termcolor.colored(message['data']['source']['url'], 'blue', attrs=[ "bold", ]), termcolor.colored( message['data']['leaf_cert']['subject']['CN'], 'green', attrs=[ "bold", ]), termcolor.colored("[", 'blue') + "{}".format( termcolor.colored(", ", 'blue').join([ termcolor.colored(x, 'white', attrs=[ "bold", ]) for x in message['data']['leaf_cert'] ['all_domains'] ])) + termcolor.colored("]", 'blue') if args.full else "", ) sys.stdout.write(payload) sys.stdout.flush() certstream.listen_for_events(_handle_messages, skip_heartbeats=True)
import sys import datetime import certstream def print_callback(message, context): logging.debug("Message -> {}".format(message)) if message['message_type'] == "heartbeat": return if message['message_type'] == "certificate_update": all_domains = message['data']['leaf_cert']['all_domains'] if len(all_domains) == 0: domain = "NULL" else: domain = all_domains[0] sys.stdout.write(u"[{}] {} (SAN: {})\n".format( datetime.datetime.now().strftime('%m/%d/%y %H:%M:%S'), domain, ", ".join(message['data']['leaf_cert']['all_domains'][1:]))) sys.stdout.flush() logging.basicConfig( format='[%(levelname)s:%(name)s] %(asctime)s - %(message)s', level=logging.INFO) certstream.listen_for_events(print_callback, url='wss://certstream.calidog.io/')