From 14899055a439303993452b901febd090b9099a40 Mon Sep 17 00:00:00 2001 From: sans Date: Mon, 20 Jul 2026 11:43:46 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC=E6=97=A5=E5=BF=97=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/templates_cert/deploy-cert.ps1.j2 | 41 +++++++++++++++++++---- backend/templates_cert/deploy-cert.sh.j2 | 37 ++++++++++++++++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/backend/templates_cert/deploy-cert.ps1.j2 b/backend/templates_cert/deploy-cert.ps1.j2 index e51ad63..cabb34c 100644 --- a/backend/templates_cert/deploy-cert.ps1.j2 +++ b/backend/templates_cert/deploy-cert.ps1.j2 @@ -1,5 +1,7 @@ $ErrorActionPreference = "Stop" +function Log($msg) { Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $msg" } + # === 由 CertCenter 生成 === $Domain = "{{ domain }}" $BaseUrl = "{{ base_url }}" @@ -21,35 +23,60 @@ $headers = @{ Authorization = "Bearer $Token" } # 跳过 TLS 证书验证(CertCenter 初期可能使用自签证书) [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } +Log "开始同步证书: $Domain" +Log "配置目录: $CertDir, 配置ID: $(if ($ConfigId) { $ConfigId } else { '无' })" + # 1. 检查版本 -$remote = (Invoke-WebRequest -Uri "$BaseUrl/api/version?domain=$EncodedDomain$ConfigParam" -Headers $headers -UseBasicParsing -SkipCertificateCheck).Content.Trim() -$local = if (Test-Path $VersionFile) { (Get-Content $VersionFile).Trim() } else { "0" } -if ($remote -eq $local) { exit 0 } +Log "检查远程版本..." +try { + $remote = (Invoke-WebRequest -Uri "$BaseUrl/api/version?domain=$EncodedDomain$ConfigParam" -Headers $headers -UseBasicParsing -SkipCertificateCheck).Content.Trim() +} catch { + Log "错误: 无法获取远程版本 - $_" + exit 1 +} +$local = if (Test-Path $VersionFile) { (Get-Content $VersionFile).Trim() } else { "0" } +Log "远程版本: $remote, 本地版本: $local" +if ($remote -eq $local) { + Log "版本一致,跳过更新" + exit 0 +} # 2. 下载证书 -Invoke-WebRequest -Uri "$BaseUrl/api/cert/fullchain?domain=$EncodedDomain$ConfigParam" -Headers $headers -OutFile "$TmpDir\fullchain.pem" -UseBasicParsing -SkipCertificateCheck -Invoke-WebRequest -Uri "$BaseUrl/api/cert/private?domain=$EncodedDomain$ConfigParam" -Headers $headers -OutFile "$TmpDir\private.key" -UseBasicParsing -SkipCertificateCheck +Log "版本不一致,开始下载证书..." +try { + Invoke-WebRequest -Uri "$BaseUrl/api/cert/fullchain?domain=$EncodedDomain$ConfigParam" -Headers $headers -OutFile "$TmpDir\fullchain.pem" -UseBasicParsing -SkipCertificateCheck + Invoke-WebRequest -Uri "$BaseUrl/api/cert/private?domain=$EncodedDomain$ConfigParam" -Headers $headers -OutFile "$TmpDir\private.key" -UseBasicParsing -SkipCertificateCheck +} catch { + Log "错误: 下载证书失败 - $_" + exit 1 +} +Log "证书下载完成" # 3. 备份旧证书 Copy-Item "$CertDir\fullchain.pem" "$CertDir\fullchain.pem.bak" -ErrorAction SilentlyContinue Copy-Item "$CertDir\private.key" "$CertDir\private.key.bak" -ErrorAction SilentlyContinue +Log "旧证书已备份" # 4. 原子替换 Move-Item "$TmpDir\fullchain.pem" "$CertDir\fullchain.pem" -Force Move-Item "$TmpDir\private.key" "$CertDir\private.key" -Force +Log "证书文件已替换" # 5. 校验 & 重载 & 上报 $HostName = $env:COMPUTERNAME try { + Log "执行校验命令: $CheckCmd" Invoke-Expression $CheckCmd + Log "校验通过,执行重载: $ReloadCmd" $remote | Out-File -NoNewline -Encoding ascii $VersionFile Invoke-Expression $ReloadCmd - Write-Host "[$(Get-Date -Format o)] updated: $Domain -> $remote" + Log "更新成功: $Domain -> v$remote" try { Invoke-WebRequest -Uri "$BaseUrl/api/report?domain=$EncodedDomain&status=success&hostname=$HostName&message=deployed+v$remote$ConfigParam" -Headers $headers -Method POST -UseBasicParsing -SkipCertificateCheck | Out-Null } catch {} } catch { + Log "错误: 校验失败,回滚证书 - $_" Move-Item "$CertDir\fullchain.pem.bak" "$CertDir\fullchain.pem" -Force -ErrorAction SilentlyContinue Move-Item "$CertDir\private.key.bak" "$CertDir\private.key" -Force -ErrorAction SilentlyContinue - Write-Error "[$(Get-Date -Format o)] FAILED: $Domain, rolled back" + Log "已回滚到旧证书" try { Invoke-WebRequest -Uri "$BaseUrl/api/report?domain=$EncodedDomain&status=failed&hostname=$HostName&message=check+failed+rolled+back$ConfigParam" -Headers $headers -Method POST -UseBasicParsing -SkipCertificateCheck | Out-Null } catch {} exit 1 } diff --git a/backend/templates_cert/deploy-cert.sh.j2 b/backend/templates_cert/deploy-cert.sh.j2 index d1cee49..1504d7b 100644 --- a/backend/templates_cert/deploy-cert.sh.j2 +++ b/backend/templates_cert/deploy-cert.sh.j2 @@ -20,42 +20,67 @@ PRIVATE_URL="${BASE_URL}/api/cert/private?domain=${DOMAIN}${CONFIG_PARAM}" TMP_DIR="/tmp/cert-sync-${DOMAIN//\*/_}" VERSION_FILE="${CERT_DIR}/.version" +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; } + mkdir -p "${CERT_DIR}" "${TMP_DIR}" auth=(-H "Authorization: Bearer ${TOKEN}") # -k 跳过 TLS 证书验证(CertCenter 初期可能使用自签证书) -curl_opts=(-fsSL -k --connect-timeout 5 --max-time 30) +# -S 显示错误信息(配合 -s 不显示进度条) +curl_opts=(-SfsSL -k --connect-timeout 5 --max-time 30) + +log "开始同步证书: ${DOMAIN}" +log "配置目录: ${CERT_DIR}, 配置ID: ${CONFIG_ID:-无}" # 1. 检查版本 -REMOTE=$(curl "${curl_opts[@]}" --max-time 15 "${auth[@]}" "${VERSION_URL}") +log "检查远程版本..." +REMOTE=$(curl "${curl_opts[@]}" --max-time 15 "${auth[@]}" "${VERSION_URL}") || { + log "错误: 无法获取远程版本 (${VERSION_URL})" + exit 1 +} LOCAL=$(cat "${VERSION_FILE}" 2>/dev/null || echo "0") +log "远程版本: ${REMOTE}, 本地版本: ${LOCAL}" if [[ "${REMOTE}" == "${LOCAL}" ]]; then + log "版本一致,跳过更新" exit 0 fi # 2. 下载证书 -curl "${curl_opts[@]}" "${auth[@]}" "${FULLCHAIN_URL}" -o "${TMP_DIR}/fullchain.pem" -curl "${curl_opts[@]}" "${auth[@]}" "${PRIVATE_URL}" -o "${TMP_DIR}/private.key" +log "版本不一致,开始下载证书..." +curl "${curl_opts[@]}" "${auth[@]}" "${FULLCHAIN_URL}" -o "${TMP_DIR}/fullchain.pem" || { + log "错误: 下载 fullchain.pem 失败" + exit 1 +} +curl "${curl_opts[@]}" "${auth[@]}" "${PRIVATE_URL}" -o "${TMP_DIR}/private.key" || { + log "错误: 下载 private.key 失败" + exit 1 +} chmod 600 "${TMP_DIR}/private.key" +log "证书下载完成" # 3. 备份旧证书 cp -f "${CERT_DIR}/fullchain.pem" "${CERT_DIR}/fullchain.pem.bak" 2>/dev/null || true cp -f "${CERT_DIR}/private.key" "${CERT_DIR}/private.key.bak" 2>/dev/null || true +log "旧证书已备份" # 4. 原子替换 mv -f "${TMP_DIR}/fullchain.pem" "${CERT_DIR}/fullchain.pem" mv -f "${TMP_DIR}/private.key" "${CERT_DIR}/private.key" +log "证书文件已替换" # 5. 校验 & 重载 & 上报 HOSTNAME=$(hostname) +log "执行校验命令: ${CHECK_CMD}" if ${CHECK_CMD}; then + log "校验通过,执行重载: ${RELOAD_CMD}" echo "${REMOTE}" > "${VERSION_FILE}" ${RELOAD_CMD} - echo "[$(date -Is)] updated: ${DOMAIN} -> ${REMOTE}" + log "更新成功: ${DOMAIN} -> v${REMOTE}" curl "${curl_opts[@]}" "${auth[@]}" -X POST "${BASE_URL}/api/report?domain=${DOMAIN}&status=success&hostname=${HOSTNAME}&message=deployed+v${REMOTE}${CONFIG_PARAM}" 2>/dev/null || true else + log "错误: 校验失败,回滚证书" mv -f "${CERT_DIR}/fullchain.pem.bak" "${CERT_DIR}/fullchain.pem" 2>/dev/null || true mv -f "${CERT_DIR}/private.key.bak" "${CERT_DIR}/private.key" 2>/dev/null || true - echo "[$(date -Is)] FAILED: ${DOMAIN}, rolled back" >&2 + log "已回滚到旧证书" curl "${curl_opts[@]}" "${auth[@]}" -X POST "${BASE_URL}/api/report?domain=${DOMAIN}&status=failed&hostname=${HOSTNAME}&message=check+failed+rolled+back${CONFIG_PARAM}" 2>/dev/null || true exit 1 fi