使用acme生成泛域名证书并定时上传更新阿里云OSS
- acme.sh工 具可以自动化申请Let's Encrypt 证书,并可通过api自动化创建dns解析完成验证,acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成.
现在新规则免费证书都只有三个月,很麻烦,提供一种思路以自动更新
自动创建证书
我的静态站点和域名DNS都是阿里云的
配置acme使用阿里云API自动申请证书
#安装
curl https://get.acme.sh | sh
#配置证书机构为letsencrypt,默认的需要登陆
acme.sh --set-default-ca --server letsencrypt
#设置阿里云api key,需要在阿里云控制台用户管理创建并授权
export Ali_Key="<key>"
export Ali_Secret="<secret>"
./acme.sh --issue --dns dns_ali -d example.com -d *.example.com
证书就会自动生成了. root用户执行默认在/root/.acme.sh路径
这里给出的 api id 和 api key 会被自动记录下来, crontab里面已经有任务会每天检测证书过期时间自动更新:
# crontab -l
17 13 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
上传证书到OSS
使用SDk调用对象存储api,这里我用的python,定时任务每月上传一次,实际三个月才过期,可以按需调整
#crontab -l
0 10 23 */2 * python /root/oss_ssl/oss_ssl.py
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-shenzhen.aliyuncs.com"
# 填写Endpoint对应的Region信息,例如cn-hangzhou。注意,v4签名下,必须填写该参数
region = "cn-shenzhen"
# examplebucket填写存储空间名称。
bucket = oss2.Bucket(auth, endpoint, "bucket-name", region=region)
# 填写自定义域名
domain = 'www.example.com'
# 填写旧版证书ID,首次执行不用管,第二次执行起把证书ID放进来可以覆盖写入,避免每次都创建新的证书
previous_cert_id = '1xxxxx7-cn-hangzhou'
with open("/root/.acme.sh/example.com_ecc/example.com.cer") as f:
certificate = f.read()
# 设置证书私钥。
with open("/root/.acme.sh/example.com_ecc/example.com.key") as f:
private_key = f.read()
cert = oss2.models.CertInfo(cert_id=previous_cert_id, certificate=certificate, private_key=private_key, force=True)
# 首次执行不传cert_id
# 通过force=True设置强制覆盖旧版证书。
# 通过delete_certificate选择是否删除证书。设置为delete_certificate=True表示删除证书,设置为delete_certificate=False表示不删除证书。
# cert = oss2.models.CertInfo(certificate=certificate, private_key=private_key, force=True, delete_certificate=False)
input = oss2.models.PutBucketCnameRequest(domain, cert)
bucket.put_bucket_cname(input)