背景:
当前最新的个人免费版本的https证书由于更新,在云平台上申请之后,有效期只有三个月,由于证书有效期时间比较短,手动更新比较麻烦,这里采用acme.sh 加自定义shell脚本的方式来完成自动更新ssl证书
acms.sh
介绍
acme.sh是一个用于自动化证书申请和部署的开源工具,支持多种验证方式和CA机构。能够简化证书的申请和管理过程,尤其适合那些需要频繁更新证书的用户。它通过完全实现ACME协议,帮助用户从Let's Encrypt、ZeroSSL等多个CA免费获取SSL/TLS证书
安装
由于acme.sh的源码是在git上面 拉取会有无法访问的问题 此时我们使用国内的码云进行下载安装
源码地址:github.com/acmesh-offi…
码云地址:gitee.com/neilpang/ac…
安装参考:github.com/acmesh-offi…
#拉取码云上的代码
git clone https://gitee.com/neilpang/acme.sh.git
#进入到指定目录
cd acme.sh
#安acme my@example.com 修改为自己的邮箱地址
./acme.sh --install -m my@example.com
#重新加载用户的bashrc文件
source ~/.bashrc
#验证是否安装完成 能够打印出版本信息已经帮助信息即可
acme.sh -h
https://github.com/acmesh-official/acme.sh
v3.0.5
Usage: acme.sh <command> ... [parameters ...]
默认CA机构
目前 acme.sh 支持 5 个正式环境 CA,分别是 Let’s Encrypt、Buypass、ZeroSSL、SSL.com 和 Google Public CA,默认使用 ZeroSSL,如果需要更换可以使用如下命令:
#切换Let’s Encrypt
acme.sh --set-default-ca --server letsencrypt
#切换 Buypass
acme.sh --set-default-ca --server buypass
#切换 ZeroSSL
acme.sh --set-default-ca --server zerossl
#切换 SSL.com
acme.sh --set-default-ca --server ssl.com
#切换 Google Public CA
acme.sh --set-default-ca --server google
结合阿里云使用
前提
1 已经拥有阿里云账户
2 该账户下有相应的域名
获取阿里云秘钥
新建AccessKey
新建AccessKey
服务器配置环境并更新证书
#设置环境变量
export Ali_Key="阿里云kry"
export Ali_Secret="阿里云Secret"
#使用acme.sh 申请证书
#--issue 申请证书
#--dns dns_ali 阿里云的自动验证dns的工作流
#testdemo.demo.com 需要申请证书的域名
#--force 强制更新证书
acme.sh --issue --dns dns_ali -d testdemo.demo.com --force
查看证书
配置无误后 会申请到证书并保存到相应的位置
Nginx更新证书
#使用acme获取到证书之后 可以使用--install-cert来安装证书
#该命令会和获取证书的命令绑定 下次再执行获取证书的命令后 会自动执行安装证书的命令
#--install-cert 将证书安装到nginx或者是其他服务器上
#-d 指定域名的证书
#--key-file nginx中key文件中位置 与nginx配置文件中的路径一致
#--fullchain-file nginx中pem文件的位置 与nginx配置文件的李静一致
#-reloadcmd 安装证书后需要执行的命令 一般是重启nginx
acme.sh --install-cert -d testdemo.wisdcloud.com --key-file /etc/nginx/ssl/testdemo.key --fullchain-file /etc/nginx/ssl/testdemo.pem --reloadcmd "systemctl restart nginx"
结合华为云使用
前提
1 拥有华为云账户
2 该账户下有相应的域名
3 使用华为云IAM账户
注意
使用华为云的时候,一定要用IAM子账户,否则在获取证书的步骤会报错
华为云设置
主账户生成IAM子账户
创建用户组
针对用户组授权 确保该用户组拥有添加dns解析记录的权限
将用户授权 使用将用户加入到用户组的方式
将用户授权 使用将用户加入到用户组的方式
登录IAM账户 获取相应的信息
登录IAM账户 获取相应的信息
记录下 IAM用户名 和 账号名
服务器侧设置
#这是华为云登录环境变量
export HUAWEICLOUD_Username="IAM用户名"
export HUAWEICLOUD_Password="IAM用户登录密码"
export HUAWEICLOUD_DomainName="账户名"
#获取证书
acme.sh --issue --dns dns_huaweicloud -d 需要获取证书的域名
#配置无误后 会获取到相应的证书
[2024年 07月 10日 星期三 17:58:11 CST] Your cert is in: /root/.acme.sh/testdemo.sqklrq.com/testdemo.demo.com.cer
[2024年 07月 10日 星期三 17:58:11 CST] Your cert key is in: /root/.acme.sh/testdemo.sqklrq.com/testdemo.demo.com.key
[2024年 07月 10日 星期三 17:58:11 CST] The intermediate CA cert is in: /root/.acme.sh/testdemo.demo.com/ca.cer
[2024年 07月 10日 星期三 17:58:11 CST] And the full chain certs is there: /root/.acme.sh/testdemo.demo/fullchain.cer
Nginx更新证书
#使用acme获取到证书之后 可以使用--install-cert来安装证书
#该命令会和获取证书的命令绑定 下次再执行获取证书的命令后 会自动执行安装证书的命令
#--install-cert 将证书安装到nginx或者是其他服务器上
#-d 指定域名的证书
#--key-file nginx中key文件中位置 与nginx配置文件中的路径一致
#--fullchain-file nginx中pem文件的位置 与nginx配置文件的李静一致
#-reloadcmd 安装证书后需要执行的命令 一般是重启nginx
acme.sh --install-cert -d testdemo.wdemo.com --key-file /etc/nginx/ssl/testdemo.key --fullchain-file /etc/nginx/ssl/testdemo.pem --reloadcmd "systemctl restart nginx"
常见错误
Not enough information provided to dns_huaweicloud 环境变量没设置好 检查设置的环境变量
dns_api(dns_huaweicloud): Error getting token. 用户名密码和domain设置错误
dns_api(dns_huaweicloud): Error getting zone id. 子账号云解析服务没有进行授权
结合其他厂商使用
当需要结合其他厂商使用的时候 需要调用不同的API接口
具体格式参考:github.com/acmesh-offi…
搭配shell脚本使用
思路
- 通过shell脚本结合crontab定时任务 来自动完成更新ssl证书 将以上内容自动化完成
- 通过判断相应的证书文件 来获取到证书的过期时间 并将时间戳转化为标准格式 进行时间对比 如果有效期小于15天 则进行更新证书的操作
- 支持在同一个服务器上面配置多个不同的阿里云或者是华为云的key
- 使用came.sh来更新证书
- 更新完成后 使用邮件来通知(需要提前配置好邮件设置) 也可以更换其他的通知方式
需提前安装邮件服务器,可自行查找安装教程.本文不做介绍
shell脚本
#/bin/bash
# 整体逻辑:使用acme.sh来获取证书 并更新 使用邮件通知更新结果
# 需要更新的域名
Domain_name=demo.demo.cn
# 域名ssl文件所在地址
key_path=/usr/local/nginx/conf/ssl/demo.demo.cn.cn_server.key
pem_path=/usr/local/nginx/conf/ssl/demo.demo.cn.cn_server.crt
# 证书有效期 设置一个空值 后续步骤给此变量赋值
ssl_validity=""
# 邮件通知的邮箱地址
mailbox=demo@163.com
# 需要使用不同的云平台的时候 将相应的注释取消就可以
# 阿里云秘钥
# 修改为对应域名所在阿里云的key和Secret
#export Ali_Key="阿里云Key"
#export Ali_Secret="阿里云Secret"
# 华为云秘钥
export HUAWEICLOUD_Username="test"
export HUAWEICLOUD_Password="demo"
export HUAWEICLOUD_DomainName="demo"
# 检查现有证书的有效期 定义函数获取证书有效期,接受一个参数:证书文件路径
# 根据传入的证书文件 获取证书有效期 并转换为可读的年月日
get_ssl_expiry_date() {
pem_path="$1"
notAfterRaw="$(openssl x509 -in "$pem_path" -noout -enddate)"
notAfterDate="${notAfterRaw#*=}"
notAfterDateFormatted=$(date -ud "${notAfterDate% *}" +"%Y-%m-%d")
echo $notAfterDateFormatted
}
# 定义发送邮件的函数 接收4个参数 1更新的域名 2是否成功 3证书有效期 4备注
send_email() {
domain="$1"
update_result="$2"
certificate_expiry="$3"
remarks="$4"
# 设置邮件内容
subject="域名更新通知"
body="更新域名: $domain
更新结果: $update_result
证书有效期: $certificate_expiry
备注: $remarks"
# 发送邮件
echo "$body" | mail -s "$subject" $mailbox
}
# 获取现有证书到期时间
output_date=$(get_ssl_expiry_date "$pem_path")
# 将现有证书到期时间转换为秒数
output_seconds=$(date -d "$output_date" +%s)
# 获取当前时间的秒数
current_seconds=$(date +%s)
# 计算两个时间之间的差值(以秒为单位)
time_difference=$((output_seconds - current_seconds))
# 将差值转换为天数
days_difference=$((time_difference / 86400))
# 判断两个差值(即距离证书到期)是否小于15天 是则进行证书更新操作
if [ $days_difference -lt 15 ]; then
# 使用acme来获取证书 判断域名所在的云厂商 如果是在阿里云 则使用第一个 华为云使用第二个
#/root/acme.sh/acme.sh --issue --dns dns_ali -d $Domain_name --force #阿里云使用
/root/acme.sh/acme.sh --issue --dns dns_huaweicloud -d $Domain_name --force #华为云使用
# 检查获取证书的命令是否正确完成
if [ $? -eq 0 ]; then
# 正确获取到证书 则更新证书并重启nginx
/root/acme.sh/acme.sh --install-cert -d $Domain_name --key-file $key_path --fullchain-file $pem_path --reloadcmd "systemctl restart nginx"
# 查看更新证书的状态
if [ $? -eq 0 ]; then
# 正确更新证书 则获取证书有效期 并邮件通知
ssl_validity=$(get_ssl_expiry_date "$pem_path")
send_email "$Domain_name" "成功" "$ssl_validity" "无"
else
# 更新证书有误 获取已有证书有效期 并邮件通知
ssl_validity=$(get_ssl_expiry_date "$pem_path")
send_email "$Domain_name" "失败" "$ssl_validity" "已获取证书,但更新失败,请及时检查"
fi
else
# 获取证书步骤有误 则查看现有证书有效期 并邮件通知
ssl_validity=$(get_ssl_expiry_date "$pem_path")
send_email "$Domain_name" "失败" "$ssl_validity" "获取证书失败,请及时检查"
fi
# 证书到期大于15天 则获取证书时间 并邮件通知
else
ssl_validity=$(get_ssl_expiry_date "$pem_path")
send_email "$Domain_name" "未执行" "$ssl_validity" "证书有效期足够,未执行更新操作,下次检查时间:$(date -d "+7 days" +"%Y-%m-%d")"
fi
设置crontab 定时任务
作者设置的是每周日晚上10点进行检查更新操作
0 22 * * 0 sh /root/shell/update.sh