banner
Vinking

Vinking

你写下的每一个BUG 都是人类反抗被人工智能统治的一颗子弹

将 SSL 证书同步到多吉云 CDN

前两个月由于腾讯云 CDN 不支持欠费立刻暂停服务换到了多吉云 CDN。

但是!

目前 宝塔 / 1Panel 的免费 SSL 证书都只有 90 天的有效期,虽然可以自动续签,但是续签后还是需要频繁手动更新 CDN 的证书,非常麻烦。

好在多吉云提供了对应的 API,使得我们可以通过脚本的方式自动实现同步 SSL 证书到多吉云 CDN。

image

功能#

  • 🔑 动态生成多吉云 API 访问令牌
  • 📤 一键式证书上传与管理
  • 🌐 多域名智能证书绑定
  • 🗑️ 旧证书清理功能(可选)
  • ⏰ 无缝衔接 Let's Encrypt 自动续期
  • ✅ 双平台支持(宝塔 / 1Panel)

快速开始#

  1. 获取多吉云 API 密钥:
    • 登录多吉云控制台
    • 进入「用户中心」→「密钥管理」
    • 创建新密钥对
  2. 确认证书路径:
    • 宝塔面板:/www/server/panel/vhost/ssl/域名目录/
    • 1Panel 可跳过

配置指南#

编辑脚本中的以下参数:

# 多吉云 AccessKey 和 SecretK
ACCESS_KEY="your_access_key_here"   # 替换为你的AccessKey
SECRET_KEY="your_secret_key_here"  # 替换为你的SecretKey

# 证书路径配置
FULLCHAIN_PATH="/path/to/fullchain.pem"  # 全链证书路径
PRIVKEY_PATH="/path/to/privkey.pem"      # 私钥路径

# 域名配置
DOMAINS=("example.com" "cdn.example.com" "www.example.com")  # 需要绑定的域名列表

# 旧证书处理策略
DELETE_OLD_CERT=false  # true=自动删除旧证书 | false=保留历史证书

部署指南#

1Panel#

  1. 进入证书管理界面
  2. 创建 / 编辑证书:
    • 启用「自动续签」
    • 启用「推送证书到本地目录」
    • 选择目录
    • 启用「申请后执行脚本」
    • 粘贴本脚本内容
    • 修改证书路径为:
# 证书路径
FULLCHAIN_PATH="./fullchain.pem"
PRIVKEY_PATH="./privkey.pem"

1Panel 证书设置

宝塔#

  1. 创建定时任务:
    • 任务类型:Shell 脚本
    • 任务名称:随意
    • 执行周期:每月 1 号 01:30 执行一次
    • 执行用户:root
    • 脚本内容:粘贴本脚本内容

宝塔定时任务

  1. 配合自动续签 Let’s Encrypt 证书定时任务 /www/server/panel/pyenv/bin/python /www/server/panel/class/acme_v2.py –renew=1 理论上可以实现放养多吉云 CDN 的证书。

保存后执行一次任务,如果显示下面信息即已经完成证书的同步:

证书上传成功!
证书ID:12345
证书已成功绑定到 www.vinking.top
证书已成功绑定到 vinking.top
证书ID 12344 删除成功。
----------------------------------------------------------------------------
★[2024-12-26 16:01:29] Successful
----------------------------------------------------------------------------

代码思路#

获取密钥 & 生成 AccessToken#

多吉云的 API 具有验证机制,使用前需要在控制台的 密钥管理 获取 AccessKey 以及 SecretKey,然后根据 AccessKeySecretKey生成 AccessToken

AccessToken 的生成过程是将请求地址和请求内容拼接后,使用 SecretKey 进行 HMAC-SHA1 加密,然后将得到的加密值与 AccessKey 用冒号连接起来。具体的生成算法可以参考文档 验证机制

# 多吉云 AccessKey 和 SecretKey
ACCESS_KEY="xxxx"
SECRET_KEY="xxxxxx"

function generateAccessToken() {
   local apiPath="$1"
   local body="$2"
   local signStr=$(echo -e "${apiPath}\n${body}")
   local sign=$(echo -n "$signStr" | openssl dgst -sha1 -hmac "$SECRET_KEY" | awk '{print $NF}')
   local accessToken="$ACCESS_KEY:$sign"

   echo "$accessToken"
}

生成了 AccessToken 后,只需要在请求头中加上 Authorization: TOKEN <AccessToken> 即可通过验证。

找到宝塔的域名证书 & 上传证书#

/www/server/panel/vhost/ssl/ 目录下,可以找到宝塔所有以域名命名的文件夹,文件夹内包含这个域名对应的完整证书链 fullchain.pem 以及私钥 privkey.pem

这里推荐给域名及其所有子域名使用同一个泛域名证书,可以实现一次性将域名及其所有子域名完成证书同步。

以域名 vinking.top 为例,完整证书链文件和私钥文件的目录如下:

FULLCHAIN_PATH="/www/server/panel/vhost/ssl/vinking.top/fullchain.pem"
PRIVKEY_PATH="/www/server/panel/vhost/ssl/vinking.top/privkey.pem"

获取到域名证书后,需要通过 POST 的方式向 https://api.dogecloud.com/cdn/cert/upload.json 提交证书内容。上传成功后需要获取证书 ID,以便将刚才上传的证书绑定到域名。

参考文档 上传证书绑定证书

# 宝塔面板 Let's Encrypt 证书路径
FULLCHAIN_PATH="/www/server/panel/vhost/ssl/vinking.top/fullchain.pem"
PRIVKEY_PATH="/www/server/panel/vhost/ssl/vinking.top/privkey.pem"

# 证书备注名
CURRENT_DATE=$(date +"%y/%m/%d")
NOTE="Certificate $CURRENT_DATE"

# 需要绑定的域名列表
DOMAINS=("xxxxx.com" "cdn.xxxxx.com" "www.xxxxx.com")

# 上传证书到多吉云
function uploadCert() {
    local note="$1"
    local certFile="$2"
    local privateKeyFile="$3"
    local certContent=$(<"$certFile")
    local privateKeyContent=$(<"$privateKeyFile")
    local encodedCert=$(echo "$certContent" | jq -sRr @uri)
    local encodedPrivateKey=$(echo "$privateKeyContent" | jq -sRr @uri)
    local body="note=$note&cert=$encodedCert&private=$encodedPrivateKey"
    local accessToken=$(generateAccessToken "/cdn/cert/upload.json" "$body")
    local response=$(curl -s -X POST "https://api.dogecloud.com/cdn/cert/upload.json"  \
         -H "Authorization: TOKEN $accessToken" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         --data "$body")

    local code=$(echo "$response" | jq -r '.code')

    if [ "$code" -eq 200 ]; then
        echo "证书上传成功!"
        local certId=$(echo "$response" | jq -r '.data.id')
        echo "证书 ID:$certId"
        bindCert "$certId"
    else
        local errMsg=$(echo "$response" | jq -r '.msg')
        echo "证书上传失败,错误代码:$code,错误信息:$errMsg"
    fi
}

# 绑定证书
function bindCert() {
    local certId="$1"
    local responses=()

    for domain in "${DOMAINS[@]}"; do
        (
            local body="id=$certId&domain=$domain"
            local accessToken=$(generateAccessToken "/cdn/cert/bind.json" "$body")
            local response=$(curl -s -X POST "https://api.dogecloud.com/cdn/cert/bind.json"  \
                 -H "Authorization: TOKEN $accessToken" \
                 -H "Content-Type: application/x-www-form-urlencoded" \
                 --data "$body")
            local code=$(echo "$response" | jq -r '.code')

            if [ "$code" -eq 200 ]; then
                echo "证书已成功绑定到 $domain"
            else
                local errMsg=$(echo "$response" | jq -r '.msg')
                echo "绑定证书到 $domain 失败,错误代码:$code,错误信息:$errMsg"
            fi
        ) &
    done

    wait
}

此文由 Mix Space 同步更新至 xLog
原始链接为 https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。