python脚本
有时候我们会有一些需求,需要批量检查自己的域名证书的到期时间,用于提前告警续费,使用python可以轻松的完成这个任务;
这里有用到第三方库pip install -U cryptography
,没有考虑站点重定向等情况,低版本python或cryptography需要改一些内容。
import socket
import ssl
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Sequence
from zoneinfo import ZoneInfo
from cryptography import x509
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
context.load_default_certs()
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
def get_certificate(domain, port=443, timeout=5) -> dict:
"""https://docs.python.org/3/library/ssl.html"""
with socket.create_connection((domain, port), timeout=timeout) as _sock:
with context.wrap_socket(_sock, server_hostname=domain) as sslsock:
# cert = ssl.DER_cert_to_PEM_cert(sslsock.getpeercert(True)) # 证书加载为pem格式
cert_bytes = sslsock.getpeercert(True)
if cert_bytes is None:
return {}
certificate = x509.load_der_x509_certificate(cert_bytes)
expired = certificate.not_valid_after_utc.astimezone(ZoneInfo("Asia/Shanghai"))
created = certificate.not_valid_before_utc.astimezone(ZoneInfo("Asia/Shanghai"))
return {
"domain": domain,
"version": certificate.version.name,
"algorithm": certificate.signature_hash_algorithm.name,
"subject": certificate.subject.rfc4514_string(),
"issuer": certificate.issuer.rfc4514_string(),
"expired_at": expired.strftime("%F %T"),
"created_at": created.strftime("%F %T"),
}
def multi_get_certificate(domains: Sequence[str]) -> list[dict]:
result = []
with ThreadPoolExecutor(max_workers=3) as pool:
tasks = {pool.submit(get_certificate, domain): domain for domain in domains}
for task in as_completed(tasks):
domain = tasks[task]
try:
result.append(task.result(timeout=10)) # 10s强行断开
except Exception as exc:
print(f"{domain=}: failed to get certificate: {exc}")
return result
if __name__ == "__main__":
domains = ("baidu.com", "jd.com", "qq.com", "aliyun.com")
print(multi_get_certificate(domains))
如果要检查的是本地证书只需要读取证书,传入x509.load_pem_x509_certificate
方法即可。
脚本运行
输出以下内容
[
{"domain": "qq.com", "version": "v3", "algorithm": "sha256", "subject": "CN=qq.com,O=Shenzhen Tencent Computer Systems Company Limited,L=Shenzhen,ST=Guangdong Province,C=CN", "issuer": "CN=DigiCert Secure Site CN CA G3,O=DigiCert Inc,C=US", "expired_at": "2024-06-10 07:59:59", "created_at": "2023-05-10 08:00:00"},
{"domain": "jd.com", "version": "v3", "algorithm": "sha256", "subject": "CN=*.jd.com,O=BEIJING JINGDONG SHANGKE INFORMATION TECHNOLOGY CO.\\, LTD.,L=Beijing,ST=Beijing,C=CN", "issuer": "CN=GlobalSign RSA OV SSL CA 2018,O=GlobalSign nv-sa,C=BE", "expired_at": "2024-12-09 09:34:41", "created_at": "2023-11-08 09:34:42"},
{"domain": "baidu.com", "version": "v3", "algorithm": "sha256", "subject": "CN=www.baidu.cn,O=BeiJing Baidu Netcom Science Technology Co.\\, Ltd,ST=\u5317\u4eac\u5e02,C=CN", "issuer": "CN=DigiCert Secure Site Pro CN CA G3,O=DigiCert Inc,C=US", "expired_at": "2025-03-02 07:59:59", "created_at": "2024-01-30 08:00:00"}, {"domain": "aliyun.com", "version": "v3", "algorithm": "sha256", "subject": "CN=*.aliyun.com,O=Alibaba (China) Technology Co.\\, Ltd.,L=HangZhou,ST=ZheJiang,C=CN", "issuer": "CN=GlobalSign Organization Validation CA - SHA256 - G3,O=GlobalSign nv-sa,C=BE", "expired_at": "2024-12-30 16:21:02", "created_at": "2023-12-07 15:21:04"}
]