如何解决使用botocore的make_request方法时出现的SSL证书验证错误?

问题背景

在使用botocore库的make_request方法进行AWS服务调用时,许多开发者会遇到类似"SSL: CERTIFICATE_VERIFY_FAILED"的错误。这个问题通常发生在以下场景:

  • 开发环境使用自签名证书
  • 企业网络使用中间人(MITM)代理
  • Python环境缺少根证书包
  • AWS服务端点证书链不完整

错误现象

典型的错误堆栈如下:

botocore.exceptions.SSLError: SSL validation failed for [https://example.com] 
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:997)

根本原因

该错误源于Python的ssl模块对服务器证书的严格验证机制。当出现以下情况时会导致验证失败:

  1. 服务器证书过期或被吊销
  2. 客户端系统时间不正确
  3. 证书链中缺少中间CA证书
  4. 主机名与证书SAN不匹配
  5. 系统根证书存储不完整

解决方案

方案1:临时禁用验证(不推荐生产环境)

通过配置botocore客户端参数禁用SSL验证:

import boto3
from botocore.config import Config

config = Config(
    connect_timeout=10,
    read_timeout=30,
    retries={'max_attempts': 3},
    verify=False  # 禁用SSL验证
)

client = boto3.client('s3', config=config)

方案2:指定自定义CA证书包

将企业CA证书添加到验证链中:

import os
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/custom/ca-bundle.crt'

方案3:更新系统证书存储

对于Python 3.10+,可使用系统证书存储:

import certifi
import os
os.environ['SSL_CERT_FILE'] = certifi.where()

方案4:修复证书链问题

使用OpenSSL检查证书链:

openssl s_client -connect example.com:443 -showcerts

最佳实践

生产环境中建议:

  • 保持SSL验证开启状态
  • 定期更新CA证书包
  • 使用AWS Certificate Manager管理证书
  • 配置适当的重试策略

底层原理

botocore的make_request最终使用urllib3的HTTPS连接池,其验证流程包括:

  1. TCP三次握手建立连接
  2. TLS/SSL握手协商
  3. 证书有效性验证(包括过期检查、签名验证等)
  4. 主机名验证
  5. OCSP状态检查(可选)