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

通过以下脚本,定义 RANCHER_URL 和 RANCHER_API_TOKEN,可以查询 rancher 下所有集群中所有 TLS 证书密文的过期时间。

#!/bin/bash
set -euo pipefail

# ============ 配置区域 ============
RANCHER_URL="https://demo.xxx.cn"
API_TOKEN="token-q5v42:xxxxxx"
# ==================================

# 工具检查
check_deps() {
if ! command -v jq &> /dev/null; then
echo "错误:请先安装 jq"
exit 1
fi
if ! command -v openssl &> /dev/null; then
echo "错误:未找到 openssl"
exit 1
fi
}

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

# API
rancher_api() {
curl -s -k -H "Authorization: Bearer $API_TOKEN" "$1"
}

# 解析证书
parse_cert() {
local crt_b64="$1"
echo "$crt_b64" | base64 -d | openssl x509 -noout -enddate -subject 2>/dev/null
}

main() {
check_deps
echo -e "${GREEN}=== 开始扫描 Rancher 所有集群 TLS 证书 ===${NC}"

clusters=$(rancher_api "${RANCHER_URL}/v3/clusters")
cluster_ids=($(echo "$clusters" | jq -r '.data[].id'))

for cluster in "${cluster_ids[@]}"; do
echo -e "\n============================================================"
echo -e "${BLUE}📦 集群: $cluster${NC}"
echo -e "============================================================"

cert_temp=$(mktemp)
trap 'rm -f "$cert_temp"' EXIT

# 获取命名空间
ns_url="${RANCHER_URL}/k8s/clusters/${cluster}/api/v1/namespaces"
namespaces=$(rancher_api "$ns_url" | jq -r '.items[].metadata.name')

for ns in $namespaces; do
secret_url="${RANCHER_URL}/k8s/clusters/${cluster}/api/v1/namespaces/${ns}/secrets?fieldSelector=type=kubernetes.io/tls"
secrets=$(rancher_api "$secret_url")

echo "$secrets" | jq -c '.items[]' | while read -r secret; do
name=$(echo "$secret" | jq -r '.metadata.name')
crt_b64=$(echo "$secret" | jq -r '.data."tls.crt"')
cert_info=$(parse_cert "$crt_b64")
[ -z "$cert_info" ] && continue

end_date=$(echo "$cert_info" | grep -E '^notAfter=' | cut -d= -f2)
subject=$(echo "$cert_info" | grep -E '^subject=' | cut -d= -f2-)

if [[ "$(uname)" == "Darwin" ]]; then
exp_sec=$(date -j -f "%b %e %H:%M:%S %Y GMT" "$end_date" +%s 2>/dev/null)
else
exp_sec=$(date -d "$end_date" +%s 2>/dev/null)
fi
now_sec=$(date +%s)
left_days=$(( (exp_sec - now_sec) / 86400 ))

if [ $left_days -lt 0 ]; then
status="RED|❌ 已过期"
elif [ $left_days -lt 30 ]; then
status="YELLOW|⚠️ 即将过期"
else
status="GREEN|✅ 正常"
fi

echo "$left_days|$ns|$name|$subject|$end_date|$status" >> "$cert_temp"
done
done

# ========== 修复序号:统一排序 + 编号输出 ==========
cert_count=$(wc -l < "$cert_temp")
if [ "$cert_count" -eq 0 ]; then
echo -e "${CYAN}ℹ️ 该集群无 TLS 证书${NC}"
rm -f "$cert_temp"
continue
fi

echo -e "${CYAN}✅ 本集群证书按剩余天数排序${NC}"
echo "----------------------------------------------------------------------"

# 核心修复:用 awk 生成序号,绝对递增
sort -n -t'|' -k1 "$cert_temp" | awk -F'|' '
BEGIN { num=1 }
{
print num "|" $0;
num++;
}' | while IFS='|' read -r num left_days ns name subject end_date color_code status_text; do
case $color_code in
RED) color=$RED;;
YELLOW) color=$YELLOW;;
GREEN) color=$GREEN;;
*) color=$NC;;
esac
echo -e "${num}. ${color}${status_text} | 剩余 ${left_days} 天 | ${ns}/${name} | ${subject} | ${end_date}${NC}"
done

rm -f "$cert_temp"
done

echo -e "\n${GREEN}=== 全部扫描完成 ===${NC}"
}

main