feat: 新增 check_ssl.sh — 檢查 tpesupporter 憑證狀態
部署於 hospital_web:~/check_ssl.sh,檢查目標網域憑證的主機名匹配與 到期天數。GCA G3 verify code 20 已於腳本內視為正常,不當失敗處理。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
93
check_ssl.sh
Executable file
93
check_ssl.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
# check_ssl.sh — 檢查 tpesupporter.tpech.gov.tw SSL 憑證狀態
|
||||
#
|
||||
# 用法:./check_ssl.sh [domain] [port]
|
||||
# 預設 domain=tpesupporter.tpech.gov.tw, port=443
|
||||
#
|
||||
# 備註:憑證由 GCA G3(政府憑證管理中心)簽發,根憑證不在 Linux 預設
|
||||
# 信任庫。openssl verify 會回 code 20,屬**正常現象**,瀏覽器端可正常
|
||||
# 驗證。此腳本不把 verify code 當成失敗條件,只看期限與主機名匹配。
|
||||
#
|
||||
# 結束碼:
|
||||
# 0 — 憑證正常
|
||||
# 1 — 連線失敗或無法取得憑證
|
||||
# 2 — 憑證已過期
|
||||
# 3 — 憑證將於 WARN_DAYS 天內到期
|
||||
# 4 — 憑證主體與目標網域不符
|
||||
|
||||
set -u
|
||||
|
||||
DOMAIN="${1:-tpesupporter.tpech.gov.tw}"
|
||||
PORT="${2:-443}"
|
||||
WARN_DAYS="${WARN_DAYS:-30}"
|
||||
|
||||
echo "== SSL 憑證檢查:${DOMAIN}:${PORT} =="
|
||||
echo
|
||||
|
||||
# --- 1. 取得憑證 ---
|
||||
RAW=$(echo | openssl s_client -connect "${DOMAIN}:${PORT}" -servername "${DOMAIN}" 2>/dev/null </dev/null)
|
||||
if [ -z "$RAW" ] || ! grep -q "BEGIN CERTIFICATE" <<<"$RAW"; then
|
||||
echo "[FAIL] 無法連線或取得憑證"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PEM=$(sed -n "/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p" <<<"$RAW" | awk "/BEGIN/{f=1} f; /END/{exit}")
|
||||
|
||||
# --- 2. 解析憑證欄位 ---
|
||||
SUBJECT=$(openssl x509 -noout -subject <<<"$PEM" 2>/dev/null)
|
||||
ISSUER=$(openssl x509 -noout -issuer <<<"$PEM" 2>/dev/null)
|
||||
DATES=$(openssl x509 -noout -dates <<<"$PEM" 2>/dev/null)
|
||||
SAN=$(openssl x509 -noout -ext subjectAltName <<<"$PEM" 2>/dev/null | sed -n "2p" | sed "s/^[ \t]*//")
|
||||
END_DATE=$(openssl x509 -noout -enddate <<<"$PEM" | sed "s/notAfter=//")
|
||||
|
||||
echo "$SUBJECT"
|
||||
echo "$ISSUER"
|
||||
echo "$DATES"
|
||||
echo "SAN: ${SAN:-(無)}"
|
||||
echo
|
||||
|
||||
# --- 3. 計算到期天數 ---
|
||||
END_EPOCH=$(date -d "$END_DATE" +%s 2>/dev/null || echo 0)
|
||||
NOW_EPOCH=$(date +%s)
|
||||
if [ "$END_EPOCH" -eq 0 ]; then
|
||||
echo "[WARN] 無法解析到期日:$END_DATE"
|
||||
DAYS_LEFT="?"
|
||||
else
|
||||
DAYS_LEFT=$(( (END_EPOCH - NOW_EPOCH) / 86400 ))
|
||||
fi
|
||||
echo "到期日:${END_DATE}"
|
||||
echo "剩餘天數:${DAYS_LEFT}"
|
||||
|
||||
# --- 4. 驗證 Code(僅資訊性) ---
|
||||
VCODE=$(grep -oE "Verify return code: [0-9]+" <<<"$RAW" | tail -1 | awk "{print \$NF}")
|
||||
echo "openssl verify code:${VCODE:-?}(GCA G3 根憑證不在 Linux 預設信任庫,回 20 屬正常)"
|
||||
|
||||
# --- 5. 主機名匹配(CN / SAN) ---
|
||||
if grep -qi "DNS:${DOMAIN}" <<<"$SAN" || grep -qi "CN[[:space:]]*=[[:space:]]*${DOMAIN}" <<<"$SUBJECT"; then
|
||||
HOST_MATCH=1
|
||||
else
|
||||
HOST_MATCH=0
|
||||
fi
|
||||
|
||||
echo
|
||||
# --- 6. 判定 ---
|
||||
if [ "$HOST_MATCH" -eq 0 ]; then
|
||||
echo "[FAIL] 憑證 CN/SAN 不包含 ${DOMAIN}"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
if [ "$DAYS_LEFT" = "?" ]; then
|
||||
echo "[WARN] 憑證期限無法解析"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if [ "$DAYS_LEFT" -lt 0 ]; then
|
||||
echo "[FAIL] 憑證已過期 $((-DAYS_LEFT)) 天"
|
||||
exit 2
|
||||
elif [ "$DAYS_LEFT" -lt "$WARN_DAYS" ]; then
|
||||
echo "[WARN] 憑證將於 ${DAYS_LEFT} 天內到期(閾值 ${WARN_DAYS} 天)"
|
||||
exit 3
|
||||
else
|
||||
echo "[OK] 憑證狀態正常(剩 ${DAYS_LEFT} 天)"
|
||||
exit 0
|
||||
fi
|
||||
Reference in New Issue
Block a user