本文永久链接: https://www.xtplayer.cn/rancher/query-the-expiration-time-of-all-tls-certificate-ciphertexts/

通过以下脚本,查询单个集群中所有 TLS 证书密文的过期时间

#!/bin/bash
# 列出所有 TLS Secret 过期时间,支持导出 CSV

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 是否导出 CSV(设置为 1 启用)
EXPORT_CSV=${EXPORT_CSV:-0}
CSV_FILE="tls-secrets-expiry-$(date +%Y%m%d_%H%M%S).csv"

# 临时文件存储数据
temp_file=$(mktemp)

echo "正在扫描所有命名空间的 TLS Secret..."
echo

# 获取所有命名空间
namespaces=$(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}')

# 统计变量
total=0
expired=0
expiring_soon=0
valid=0
error=0

# 表头
printf "${BLUE}%-35s %-25s %-25s %-10s${NC}\n" "SECRET" "NAMESPACE" "EXPIRY DATE" "DAYS LEFT"
printf "${BLUE}%-35s %-25s %-25s %-10s${NC}\n" "$(printf '%0.s-' {1..35})" "$(printf '%0.s-' {1..25})" "$(printf '%0.s-' {1..25})" "$(printf '%0.s-' {1..10})"

for ns in $namespaces; do
# 获取 TLS Secret
secrets=$(kubectl get secrets -n $ns --field-selector type=kubernetes.io/tls -o jsonpath='{.items[*].metadata.name}' 2>/dev/null)

if [ -n "$secrets" ]; then
for secret in $secrets; do
total=$((total + 1))

# 获取证书数据
cert_data=$(kubectl get secret $secret -n $ns -o jsonpath='{.data.tls\.crt}' 2>/dev/null)

if [ -n "$cert_data" ]; then
# 解析证书信息
cert_info=$(echo "$cert_data" | base64 -d 2>/dev/null)
if [ $? -eq 0 ]; then
expiry=$(echo "$cert_info" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
issuer=$(echo "$cert_info" | openssl x509 -noout -issuer 2>/dev/null | sed 's/issuer=//')
subject=$(echo "$cert_info" | openssl x509 -noout -subject 2>/dev/null | sed 's/subject=//')

if [ -n "$expiry" ]; then
# 计算剩余天数
if date --version >/dev/null 2>&1; then
expiry_epoch=$(date -d "$expiry" +%s 2>/dev/null)
else
expiry_epoch=$(date -j -f "%b %d %H:%M:%S %Y %Z" "$expiry" +%s 2>/dev/null)
fi

if [ -n "$expiry_epoch" ]; then
now_epoch=$(date +%s)
days_left=$(( ($expiry_epoch - $now_epoch) / 86400 ))

# 根据剩余天数设置颜色
if [ $days_left -lt 0 ]; then
color=$RED
status="EXPIRED"
expired=$((expired + 1))
elif [ $days_left -lt 7 ]; then
color=$YELLOW
status="EXPIRING_SOON"
expiring_soon=$((expiring_soon + 1))
else
color=$GREEN
status="VALID"
valid=$((valid + 1))
fi

# 打印到终端
printf "${color}%-35s %-25s %-25s %-10d${NC}\n" \
"$secret" "$ns" "$expiry" "$days_left"

# 写入临时文件(用于 CSV 导出)
echo "\"$secret\",\"$ns\",\"$expiry\",$days_left,\"$status\",\"$issuer\",\"$subject\"" >> $temp_file
else
printf "${YELLOW}%-35s %-25s %-25s %-10s${NC}\n" \
"$secret" "$ns" "Parse error" "ERROR"
error=$((error + 1))
fi
else
printf "${RED}%-35s %-25s %-25s %-10s${NC}\n" \
"$secret" "$ns" "Invalid certificate" "ERROR"
error=$((error + 1))
fi
else
printf "${RED}%-35s %-25s %-25s %-10s${NC}\n" \
"$secret" "$ns" "Base64 decode error" "ERROR"
error=$((error + 1))
fi
else
printf "${RED}%-35s %-25s %-25s %-10s${NC}\n" \
"$secret" "$ns" "No tls.crt data" "ERROR"
error=$((error + 1))
fi
done
fi
done

# 打印统计信息
echo
echo "========================================="
echo "统计信息"
echo "========================================="
echo "总计 TLS Secret: $total"
echo -e "${GREEN}有效证书: $valid${NC}"
echo -e "${YELLOW}即将过期(<7天): $expiring_soon${NC}"
echo -e "${RED}已过期: $expired${NC}"
echo "解析错误: $error"
echo "========================================="

# 导出 CSV
if [ $EXPORT_CSV -eq 1 ] && [ -s $temp_file ]; then
# 添加 CSV 表头
echo "\"SECRET_NAME\",\"NAMESPACE\",\"EXPIRY_DATE\",\"DAYS_LEFT\",\"STATUS\",\"ISSUER\",\"SUBJECT\"" > $CSV_FILE
cat $temp_file >> $CSV_FILE
echo "已导出到文件: $CSV_FILE"
fi

# 清理临时文件
rm -f $temp_file

# 如果有过期证书,返回非零退出码
if [ $expired -gt 0 ]; then
exit 1
fi