部署於 hospital_web:~/check_ssl.sh,檢查目標網域憑證的主機名匹配與 到期天數。GCA G3 verify code 20 已於腳本內視為正常,不當失敗處理。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.9 KiB
Bash
Executable File
94 lines
2.9 KiB
Bash
Executable File
#!/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
|