4. 证书有效期监控:设置预警阈值(30天、15天、7天)

证书过期,是生产环境中最常见、也最不该发生的故障。我见过太多团队因为一张证书过期,导致整个支付链路中断两小时。说白了,这不是技术问题,是管理问题。

有效期监控的核心就一句话:在证书死掉之前,给你留足反应时间。那留多少天合适?我个人习惯设三层:30天、15天、7天。为什么是这三个数字?往下看。

4.1 三层预警模型:为什么是30/15/7?

你想想看,证书续签这件事,涉及的人不止你一个。你得找CA申请、等审批、拿新证、部署、重启服务。每一步都可能卡住。所以预警不能只设一个点,得分层。

预警层级 阈值 预警级别 响应要求
第一层 30天 提醒(Info) 确认证书归属,启动续签流程
第二层 15天 警告(Warning) 必须提交续签申请,进入审批
第三层 7天 紧急(Critical) 立即执行,跳过非必要审批

30天那层,说白了是给你「看一眼」的机会。我建议这时候发邮件或钉钉消息,别太吵。15天是真正的行动线。7天是红线——我曾经遇到过某家银行,7天预警发出去没人理,结果第6天CA系统宕机,差点没续上。从那以后,7天预警我直接打电话。

核心原则:预警不是通知,是驱动行动。每一层预警都必须对应一个明确的动作,否则就是噪音。

4.2 预警阈值配置实战

不管你是用Prometheus、Zabbix还是自研平台,阈值配置的逻辑都一样。我拿Prometheus举个例,因为它的表达式最直观。

4.2.1 Prometheus 告警规则示例

groups:
  - name: certificate_expiry
    rules:
      - alert: CertExpiryIn30Days
        expr: |
          (x509_cert_not_after - time()) / 86400 <= 30
          and
          (x509_cert_not_after - time()) / 86400 > 15
        for: 1h
        labels:
          severity: info
        annotations:
          summary: "证书 {{ $labels.common_name }} 将在30天内过期"
          description: "剩余 {{ $value | humanizeDuration }}"

      - alert: CertExpiryIn15Days
        expr: |
          (x509_cert_not_after - time()) / 86400 <= 15
          and
          (x509_cert_not_after - time()) / 86400 > 7
        for: 30m
        labels:
          severity: warning
        annotations:
          summary: "证书 {{ $labels.common_name }} 将在15天内过期"
          description: "剩余 {{ $value | humanizeDuration }},请尽快续签"

      - alert: CertExpiryIn7Days
        expr: |
          (x509_cert_not_after - time()) / 86400 <= 7
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "证书 {{ $labels.common_name }} 将在7天内过期"
          description: "剩余 {{ $value | humanizeDuration }},立即处理!"

小技巧:注意每个规则的 for 字段。30天预警我设1小时,避免短时波动误报。7天预警只等10分钟,因为这时候每一分钟都宝贵。

4.2.2 用脚本做兜底检查

有些环境跑不了Prometheus,比如离线内网。我习惯写一个简单的Shell脚本,配合crontab做兜底。嗯,这里要注意:脚本里一定要处理时区问题,我踩过坑。

#!/bin/bash
# 证书有效期检查脚本
# 用法: ./check_cert_expiry.sh /path/to/cert.pem

CERT_PATH=$1
WARN_DAYS=30
CRIT_DAYS=7

# 获取证书过期时间(秒)
EXPIRY_EPOCH=$(openssl x509 -in "$CERT_PATH" -noout -enddate | cut -d= -f2 | date -f - +%s)
NOW_EPOCH=$(date +%s)
REMAIN_DAYS=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))

if [ $REMAIN_DAYS -le $CRIT_DAYS ]; then
    echo "CRITICAL: 证书 $CERT_PATH 剩余 $REMAIN_DAYS 天"
    exit 2
elif [ $REMAIN_DAYS -le $WARN_DAYS ]; then
    echo "WARNING: 证书 $CERT_PATH 剩余 $REMAIN_DAYS 天"
    exit 1
else
    echo "OK: 证书 $CERT_PATH 剩余 $REMAIN_DAYS 天"
    exit 0
fi

避坑指南:我曾经在macOS上写这个脚本,date -f 参数不兼容。后来统一用 date -d 加GNU date才解决。跨平台时一定要测试date命令的行为。

4.3 预警阈值动态调整策略

30/15/7是通用模板,但实际场景需要微调。我总结了几种常见情况:

  • 根CA证书:有效期通常10年以上,预警可以放宽到90天。但千万别不管,根证丢了比叶子证过期更麻烦。
  • 内部CA签发证书:流程快,15天预警就够了。我建议把7天预警改成3天,给自己留点缓冲。
  • 外部CA证书(如Let's Encrypt):90天有效期,30天预警其实已经有点晚了。我习惯设成45天、20天、10天。
  • 设备证书(IoT场景):设备可能离线,预警要提前到60天。因为你要留出设备回连、OTA升级的时间。
证书类型 典型有效期 建议预警阈值 备注
根CA证书 10-20年 90/60/30天 手动续签,流程长
内部CA签发证书 1-3年 30/15/3天 自动化程度高
Let's Encrypt 90天 45/20/10天 自动续签为主
IoT设备证书 1-5年 60/30/15天 考虑设备离线窗口

4.4 预警阈值背后的知识体系

说了这么多,其实就一张图能讲清楚。我画了个流程图,帮你理解三层预警怎么联动。

证书有效期三层预警联动流程 第一层:30天预警 级别:提醒 第二层:15天预警 级别:警告 第三层:7天预警 级别:紧急 动作:确认归属 启动续签流程 通知证书负责人 动作:提交申请 进入审批流程 准备新证书 动作:立即执行 跳过非必要审批 直接部署新证书 是否在截止日前完成续签? 每层预警触发时检查 续签完成 关闭预警,记录日志 续签失败 升级处理,人工介入 关键点 每层预警触发时,必须检查 上一层的动作是否已完成

这张图的核心逻辑是:每一层预警触发时,都要检查上一层的动作是否已完成。如果30天预警发了没人动,15天预警就不能只发通知,得升级处理。我见过最惨的案例,就是每层预警都发邮件,结果没人看,最后证书过期了才发现。

4.5 预警阈值的最佳实践总结

最后,我把自己踩过的坑和总结的经验列一下:

  • 不要只设一个阈值。单点预警等于没有预警。万一那天你休假呢?
  • 预警渠道要分层。30天发邮件,15天发邮件+钉钉,7天直接打电话。我建议7天预警的接收人里加上你的领导。
  • 节假日要自动顺延。如果证书在春节前7天过期,预警要提前到15天。我写过一个脚本,对接节假日API自动调整阈值。
  • 测试预警流程。每季度做一次模拟演练,真的让证书走到7天预警,看团队能不能在24小时内续上。我第一次演练就发现,有人不知道私钥在哪。
  • 记录预警响应时间。每次预警从触发到关闭,记录耗时。如果连续三次都在7天预警才处理,说明30天和15天的流程有问题。

我的习惯:在监控系统里加一个「证书健康度」仪表盘,显示所有证书的剩余天数,按颜色排序。绿色>30天,黄色15-30天,红色<15天。每天早上看一眼,心里有数。

阈值设好了,监控就跑起来了。但别忘了,监控只是手段,续签才是目的。下一层我们要聊的,就是证书发现和资产盘点——你得先知道你有多少张证书,才能管好它们。