AWS Lambda Node.js中Axios调用REST API证书验证失败求助
我在AWS Lambda(Node.js运行时)中尝试使用P12/PFX客户端证书连接REST API。该证书在curl命令与Java应用中均可正常使用,但通过Axios调用时,仅当设置rejectUnauthorized: false才能成功;注释该参数则触发如下错误:
Error: AxiosError: unable to verify the first certificate
cause: Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1539:34)
at TLSSocket.emit (node:events:513:28)
at TLSSocket.emit (node:domain:489:12)
at TLSSocket._finishInit (node:_tls_wrap:953:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:734:12) {
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}
已知rejectUnauthorized: false不适用于生产环境,且相同配置下调用SOAP API无此问题,推测httpsAgent配置存在遗漏,求助如何正确配置以解决该问题。使用的Node.js代码如下:
const axios = require("axios"); const https = require('https'); const fs = require('fs'); const url = `https://example.com/test`; let httpsAgent = new https.Agent({ pfx: fs.readFileSync('./src/example.p12'), passphrase: 'Test123', maxVersion: 'TLSv1.2', //rejectUnauthorized: false }) const axiosConfig = { httpsAgent: httpsAgent, }; axios.get(url, axiosConfig) .then((response: any) => { console.log('Response:', response.data); }).catch((error: any) => { console.error('Error:', error); });
这个错误的核心是Node.js的HTTPS模块无法验证服务器证书的完整信任链,与客户端证书本身无关(curl/Java能正常使用即可证明)。以下是几种可行的修复方式:
1. 补充服务器根/中间证书到HTTPS Agent配置
Node.js默认的CA证书存储可能缺少目标API服务器证书链中的根CA或中间CA。需要将服务器的完整证书链(包含根CA和所有中间CA)导出为PEM格式,然后在httpsAgent中指定ca参数:
// 读取服务器证书链的PEM文件 const serverCa = fs.readFileSync('./src/server-ca-chain.pem'); let httpsAgent = new https.Agent({ pfx: fs.readFileSync('./src/example.p12'), passphrase: 'Test123', maxVersion: 'TLSv1.2', ca: serverCa // 添加服务器信任链 })
获取服务器证书链的方法:
- 通过浏览器访问目标API地址,查看证书详情,导出完整的证书链(所有层级的CA证书)为PEM格式
- 使用curl命令导出:
curl -v https://example.com/test 2>&1 | awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' > server-ca-chain.pem
2. 检查P12证书的完整性
部分P12文件可能仅包含客户端证书,缺少对应的中间CA证书。可以用OpenSSL检查P12内容:
openssl pkcs12 -info -in example.p12
如果输出中只有客户端证书(无Issuer对应的中间CA条目),需要重新生成包含完整客户端证书链的P12文件,再替换到代码中。
3. 适配AWS Lambda环境的CA配置
AWS Lambda的Node.js运行时使用系统级CA证书,但私有CA证书可能不在默认列表中。除了代码中指定ca参数,还可以:
- 将服务器CA证书上传到Lambda层,在代码中读取层内的证书文件
- 确保Lambda执行角色拥有证书文件的访问权限(若证书存储在S3,需添加S3读取权限)
内容的提问来源于stack exchange,提问作者raman20

