whoisとopensslコマンドで、dnsやssl証明書の有効期限を確認 - end0tknr's kipple - web写経開発
以前、記載したperl版の上記entryを pythonで書いてみました。
#!/usr/local/bin/python3 # -*- coding: utf-8 -*- import datetime import dateutil.parser import os import re import subprocess import sys HOSTNAMES = [ "www.xxxx-xxxx.com" ] TLDS = { "" :['.com', '.org', '.net'], "whois.jprs.jp" :['.co.jp','.gr.jp','.ne.jp','.or.jp','.jp'] } TIMEOUT = 10; SSL_PORT = 443; WHOIS_CMD = "/usr/bin/whois"; OPENSSL_CMD = "/usr/bin/openssl"; def main(): disp_strs = "\t".join([ "%-30s" % ("HOSTNAME"), "DNS_START","DNS_LAST", "SSL_START","SSL_LAST" ]) print( disp_strs ) for hostname in HOSTNAMES: (dns_start,dns_last) = get_whois_expire( hostname ) (ssl_start,ssl_last) = get_ssl_expire( hostname ) disp_strs = "\t".join([ "%-30s" % (hostname), dns_start,dns_last, ssl_start,ssl_last ]) print( disp_strs ) def get_ssl_expire( hostname ): print( hostname ) def get_whois_expire( hostname ): (domain_tmp,whois_host) = extract_domain(hostname) cmd = None if whois_host: cmd = " ".join([WHOIS_CMD,"-h",whois_host, domain_tmp]) else: cmd = " ".join([WHOIS_CMD,domain_tmp]) (stdout,stderr,return_code) = exec_subprocess(cmd) if not stdout: return None re_compiles = [ re.compile("Updated Date: (.+)"), re.compile("\[Last Update?d?\]\s+([^\s]+)"), re.compile("Registry Expiry Date: (.+)"), re.compile("\[State\]\s+Connected\s+\(([^\s]+)\)"), re.compile("\[Expires on\]\s+([^\s]+)") ] stdout_lines = stdout.decode().split("\n") start_date = None last_date = None for stdout_line in stdout_lines: for i, re_compile in enumerate(re_compiles): re_result = re_compile.search( stdout_line ) if not re_result: continue if i == 0: start_date = parse_date( re_result.group(1) ) break elif i == 1: start_date = parse_date( re_result.group(1) ) break elif i == 2: last_date = parse_date( re_result.group(1) ) break elif i in [3,4]: last_date = parse_date( re_result.group(1) ) break return (start_date,last_date) def parse_date( org_str ): parsed_date = dateutil.parser.parse(org_str) return parsed_date.strftime("%Y-%m-%d") def extract_domain( hostname ): for whois_host, tlds in TLDS.items(): for tld in tlds : re_compile = re.compile("([^\.]+)"+tld + "$",re.IGNORECASE) re_result = re_compile.search( hostname ) if not re_result: continue return (re_result.group(1)+tld, whois_host) return ("","") # cf. https://qiita.com/fetaro/items/a3b3bd4ea197b600ac45 def exec_subprocess(cmd: str, raise_error=True): child = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = child.communicate() rt = child.returncode if rt != 0 and raise_error: print("ERROR",stderr,file=sys.stderr) return (None,None,None) return stdout, stderr, rt def get_ssl_expire( host ): cmd = " ".join( ["echo |", "%s s_client -connect %s:%s -showcerts" % (OPENSSL_CMD,host,SSL_PORT), "2> /dev/null | ", "%s x509 -dates -noout 2> /dev/null" % (OPENSSL_CMD)]) (stdout,stderr,return_code) = exec_subprocess(cmd) stdout_lines = stdout.decode().split("\n") re_compiles = [ re.compile("^notBefore\=(.+)"), re.compile("^notAfter\=(.+)" ) ] start_date = None last_date = None for stdout_line in stdout_lines: for i, re_compile in enumerate(re_compiles): re_result = re_compile.search( stdout_line ) if not re_result: continue date_str = re_result.group(1) date_str = parse_date( date_str ) if i == 0: start_date = date_str else: last_date = date_str return (start_date,last_date) if __name__ == '__main__': main()