Python自动申请腾讯云免费SSL证书,并部署到CDN
2024年10月11日...大约 3 分钟
前言
由于腾讯云把免费 ssl 证书改成有效期 90 天了,为了方便我的 CDN 更换新 ssl 证书,所以写了一个小小的 Python 脚本。
脚本功能:
- 当证书快过期时,自动申请新证书
- 自动改修旧证书和新证书的备注(脚本根据证书备注识别的)
- 自动将新证书部署到 CDN 上
代码
下面是完整的代码:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File Name :index.py
@Description :自动申请腾讯云免费SSL证书
@Date :2024/08/16 10:10:35
@Author :meowpass.com
"""
import json
import logging
import os
from datetime import datetime
from pathlib import Path
import time
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.ssl.v20191205 import ssl_client, models as ssl_models
CertificateList = [] # 证书列表
renewal_days = 10 # 证书到期时间小于指定天数,自动申请新证书
log_path = "/" # 日志路径
# 日志配置
logging.basicConfig(
level=logging.INFO, # 控制台打印的日志级别
filename=Path(log_path) / f"{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.log", # 日志文件
filemode="a", ##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志。a是追加模式,默认如果不写的话,就是追加模式
format="%(asctime)s - %(levelname)s - %(message)s", # 日志格式
)
try:
# 实例化一个认证对象,从环境变量中获取 SecretId 和 SecretKey
cred = credential.Credential(os.environ.get("TENCENTCLOUD_SECRET_ID"), os.environ.get("TENCENTCLOUD_SECRET_KEY"))
# 实例化要请求产品的client对象,clientProfile是可选的
client_for_ssl = ssl_client.SslClient(cred, "")
# 获取证书列表
req = ssl_models.DescribeCertificatesRequest() # 实例化一个请求对象,每个接口都会对应一个request对象
req.from_json_string(json.dumps({}))
resp = client_for_ssl.DescribeCertificates(req) # 返回的resp是一个DescribeCertificatesResponse的实例,与请求对象对应
for cert in resp.Certificates:
if cert.Alias == "博客":
CertificateList.append(cert)
logging.info(cert.CertificateId)
if cert.Alias == "博客评论系统":
CertificateList.append(cert)
logging.info(cert.CertificateId)
# 获取证书信息
req = ssl_models.DescribeCertificateRequest()
for Certificate in CertificateList:
# 查询证书信息
params = {"CertificateId": Certificate.CertificateId}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.DescribeCertificate(req) # 返回的resp是一个DescribeCertificateResponse的实例,与请求对象对应
logging.info("<%s> 的到期时间:%s", resp.Domain, resp.CertEndTime)
# 计算证书到期时间
given_date = datetime.strptime(resp.CertEndTime, "%Y-%m-%d %H:%M:%S") # 将字符串转换为 datetime 对象
current_date = datetime.now() # 当前日期
difference = given_date - current_date # 计算两个日期之间的差异
days = difference.days # 获取天数
logging.info("<%s> 距离证书到期还有: %s 天", resp.Domain, days)
# 如果证书到期时间小于10天,自动申请新证书
if days < renewal_days:
# 申请新证书
logging.info("<%s> 证书到期时间小于%s天,自动申请新证书", Certificate.Domain, renewal_days)
req = ssl_models.ApplyCertificateRequest()
params = {"DvAuthMethod": "DNS_AUTO", "DomainName": Certificate.Domain}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.ApplyCertificate(req)
newCertId = resp.CertificateId # 新证书id
logging.info("<%s> 申请新证书成功,证书id:%s", Certificate.Domain, resp.CertificateId)
while True:
# 休眠60秒
logging.info("<%s> 等待60秒,查询证书状态,直至证书颁发成功", Certificate.Domain)
time.sleep(60)
# 查询证书状态
req = ssl_models.DescribeCertificateRequest()
params = {"CertificateId": newCertId}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.DescribeCertificate(req)
logging.info("<%s> 新证书%s", resp.Domain, resp.StatusName)
if resp.Status == 1:
break
# 修改旧证书备注
req = ssl_models.ModifyCertificateAliasRequest()
params = {"CertificateId": Certificate.CertificateId, "Alias": f"old_{datetime.now().strftime('%Y%m%d')}_{Certificate.Alias}"}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.ModifyCertificateAlias(req)
logging.info("<%s> 修改旧证书备注成功", Certificate.Domain)
# 修改新证书备注
params = {"CertificateId": newCertId, "Alias": Certificate.Alias}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.ModifyCertificateAlias(req)
logging.info("<%s> 修改新证书备注成功", Certificate.Domain)
# 部署新证书到CDN
req = ssl_models.DeployCertificateInstanceRequest()
params = {
"CertificateId": newCertId,
"InstanceIdList": Certificate.CertSANs,
"ResourceType": "cdn",
}
req.from_json_string(json.dumps(params))
resp = client_for_ssl.DeployCertificateInstance(req)
logging.info("<%s> 部署新证书到CDN%s", Certificate.Domain, "成功" if resp.DeployStatus else "失败")
else:
logging.info("<%s> 证书到期时间大于%s天,跳过", Certificate.Domain, renewal_days)
except TencentCloudSDKException as err:
logging.error(err)
except Exception as err:
logging.error(err)
使用
前往腾讯云控制台创建一个新策略:
{
"statement": [
{
"action": [
"ssl:DescribeCertificate",
"ssl:DescribeCertificates",
"ssl:ApplyCertificate",
"ssl:ModifyCertificateAlias",
"ssl:DeployCertificateInstance"
],
"effect": "allow",
"resource": ["*"]
}
],
"version": "2.0"
}
前往腾讯云控制台创建子账号,获取 SecretID、SecretKey。
修改代码中的 log_path
和 renewal_days
两个变量。然后修改 44 ~ 49 行中 if
语句。添加自己想要自动更新的 ssl 证书的备注。
脚本从环境变量中读取 SecretID 和 SecretKey。
所以需要导入这两个变量:
export TENCENTCLOUD_SECRET_ID=<SecretID>
export TENCENTCLOUD_SECRET_KEY=<SecretKey>
然后运行脚本即可。
也可以创建一个定时任务,每天自动运行脚本:
0 0 * * * export TENCENTCLOUD_SECRET_ID=<SecretID> && export TENCENTCLOUD_SECRET_KEY=<SecretKey> && <脚本路径> > /dev/null
Powered by Waline v3.3.2