【AWS生态】Java连接AWS IOT-CORE组件报证书受限问题

380 阅读3分钟

问题记录:【AWS】Java连接AWS IOT-CORE组件报证书受限问题


Java连接IOT报证书不受信任问题

1. 问题描述

​ 背景:某与设备端交互的需求,涉及步骤,连接iot-core操作mqtt推送消息。

​ 关键代码:

private IotDataPlaneClient iotDataPlaneClient = IotDataPlaneClient.builder().region(Region.of(SystemEnvironment.REGION)).build();
PublishRequest build = PublishRequest.builder().topic(topic).qos(1).
    payload(SdkBytes.fromString(payload, Charset.forName("UTF-8"))).build();
// 下方代码报错
iotDataPlaneClient.publish(build);

​ 关键报错信息:

software.amazon.awssdk.core.exception.SdkClientException:
Unable to execute HTTP request: sun.security.validator.ValidatorException: TLS Server certificate issued after 2019-04-16 and anchored by a distrusted legacy Symantec root CA: CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US

2. 过程分析

  • 铺垫及前期相关信息: 本地开发调试过程中,出现过该问题。根据报错信息,可以分析出是HTTPS建立连接过程,证书校验环节出现问题。 查阅资料,发现JDK中JRE自带了证书,为 Symantec Certificate。 求助周边大佬,得知类似功能本地调试没问题,目光锁定在JDK版本影响上。 但JAVA JDK重新安装是个比较重的操作,就没有采取更换JDK的方式,遂上网找解决方案。

    得到方案普遍为以下几类:

    1. 升级JDK(*黑盒*做法,可能有的JDK版本自带的证书不同,刚好能绕过证书校验的步骤)
    2. 更换证书(治本做法之一,但是要找到合适的证书,也是一个问题)
    3. 忽略证书校验(治本做法之一,比较简单,对于整个https连接过程中,会跳过证书校验的步骤)
    

    综合下来,本地开发的时候选择了第3种做法,即将JDK自带JRE的校验证书配置注释了,于是开发环境问题解决。

    注释文件:
    .../jdk1.8.0_321/jre/lib/security/java.security
    
    注释关键行:
    jdk.security.caDistrustPolicies=SYMANTEC_TLS
    

  • 服务器重现:

    2022.12.13将该程序部署到feature 和 test机器,发现该问题再次出现,报错信息如【问题描述】。

  • 结合铺垫分析:

    类似功能为Iot程序,出现问题为IPC程序,两个功能代码点基本一致,于是排除代码问题;
    基于本地解决思路,合理怀疑:
    1. 容器使用的JRE自带证书有问题
    排查Iot程序和IPC程序,两个都是基于dockerFile拉取容器镜像,使用的jdk版本一致。
    如果是JRE自带证书问题导致,那么两个程序应该都会报错(实际上,确实是证书问题,但是这里分析分析不出来)
    排除JRE问题
    2. 将目光转向两个程序其他变量,试图找出导致出问题的不同点,但无果
    
  • 关键点:

    周边大佬一起帮忙查资料,得知可能是证书不被iot-core信任,最终找到文档,确定aws sdk在不同区域下对证书的要求不同。
    即,Iot程序没问题,因为在发布地区信任jdk自带证书;
    而,IPC程序有问题,也是因为地区限制jdk自带证书。
    
    官方链接(问题核心):
    https://aws.amazon.com/cn/blogs/iot/aws-iot-core-ats-endpoints/?teamwork_src=1&gcmt=ut_hSJL5HWhLrVDChauKjZBnQXmfXcjj2oLzqi&accessToken=ut_hSJL5HWhLrVDChauKjZBnQXmfXcjj2oLzqi&lang=zh_CN
    

3. 改进措施

​ 基于官方链接说明,最终采用Java程序连接Iot-core的时候,统一去除https过程中的证书校验,代码如下:

@SpringBootApplication
public class ManagerApplication {

    public static void main(String[] args) {
        // 忽略https证书校验
        java.security.Security.setProperty("jdk.security.caDistrustPolicies", "");
		....
    }
}

4. 事后总结

  1. 对于java程序,后续使用aws iot-core相关组件,建议都忽略掉证书校验(aws官方也是这么建议)

  2. 排查原因比较漫长,因为存在比较多变量。

    同时反馈出对https的不熟悉,故附上https讲解比较清晰的外链,供大家学习参考。

    segmentfault.com/a/119000002…