近期在工作中遇到一个加解密的集成需求,过程算得上是一波三折,在此记录以供思路分享,并便于日后翻阅。
1.需求背景:
客户引入数据时上传的excel是加密文件,由于系统无法直接解析加密文件导致引入失败。故需要在文件引入前增加扩展处理,调用客户提供的加解密程序。
2. 服务器配置:
根据客户提供的文档《intekey9接口使用说明(linux篇).pdf》,联系客户技术人员对服务器进行加解密资质初始化,生成intekey相关唯一标志文件。
3. 加解密测试:
进入已预处理的服务器
a) cd /intekey/intekey
b) vi MainTestKey.java
修改:System.setProperty("user.dir","/intekey/intekey");
c) 编译java文件:javac -Djava.ext.dirs=./lib MainTestKey.java
,产生MainTestKey.class
d) 测试:./run
测试说明:
- 准备一个未加密文件,放到/tmp目录下,此时文件大小为12510;
-
测试脚本1:加密文件
输入KeyID=40,KeyLevel=100;
文件开始加密……
文件加密成功。
此时文件大小变为16606。将文件复制到桌面,双击后会提示无法打开,需要特定的电脑才可以打开。 -
测试脚本2:检查文件是否加密
返回文件已加密。 -
测试脚本3:更新文件加密等级
返回文件加密等级更新成功。 -
测试脚本4:解密文件
解密成功,文件大小恢复为12510。 -
整体测试成功。
-
后在k8s的pod中执行,执行成功。
如测试不成功会返回各种错误,包括且不限于
- 无法加载.so文件
检查user.dir配置路径是否正确。 - 初始化class失败
检查run目录下是否有lib。 - 初始化认证服务器mac地址失败
联系客户工程师检查是否资质文件配置成功。 - 解密失败
联系客户工程师检查是否资质文件配置成功。总结:测试类可以在本地执行、可以在Linux服务器执行,可以在k8s的pod中执行。
4. 问题:
问题出现在开发环境中。
在功能上传至开发环境进行初步测试后,系统经常会发生重启操作。在多次测试定位后发现正是该功能扩展导致。代码执行到调用加解密程序【InteKey.Ia(FilePath)】时,会直接强制重启erp系统的容器,目前尚未找到根本原因,且并未产生任何日志。初步分析是天喻软件的加解密程序在异常退出时,会触发erp系统容器的exit,导致服务重启;
5. 进度暂停,整理思路:
问题出现在调用加解密程序时
之前在本地、服务器、k8s容器执行命令调用加解密文件均未出现问题,问题只出现在了正式开发环境中。
执行到加解密程序导致容器重启后,未产生任何日志,难以进一步追踪……
那么,是不是可以……
6. 峰回路转
那么,问题在难以进一步解决时,我们是否可以跳过这一步,借用其他赛道接轨?
也就是通过提供一个中间件程序,将加解密的这段程序剥离出来独立运行,并通过接口进行调用。
于是我在确定以下两点后,开始着手 “调用加解密程序代码” 的抽离
- 加解密程序如何实现
编写一个Spring Boot小程序,提供restful接口。
Spring Boot 框架内置完整的一套服务,可以便于我们将精力主要投放在系统间的接口调用上。 - 接口的传输内容
传输文件流 or 传输文件路径?
考虑到接口性能,这里不建议传输文件流,所以我们传递的是文件路径;基于此,我们需要完成一个前置条件:
erp系统的待处理文件,可以被加解密程序直接访问到【重要!】
7. Spring Boot加解密程序(以下简称Spring Boot小程序)
程序说明:
- 程序默认配置均未修改,占用8080端口
- 提供4个接口
i. 加密文件:http://ip:8080/intekey/encryptFile/{filePath}
ii. 解密文件:http://ip:8080/intekey/decryptFile/{filePath}
iii. 判断文件是否加密:http://ip:8080/intekey/checkEncryptFile/{filePath}
iv. Transfer文件:http://ip:8080/intekey/transferFile/{filePath} - 考虑到文件路径可能包含特殊字符,filePath需要进行编码处理:先进行Base64编码,然后UrlEncode编码,实现方式:
URLEncoder.encode(Base64.getEncoder().encodeToString(filePath.getBytes()), "utf-8");
- 接口返回参数:
i. 成功:Success
ii. 失败:Failed/异常 - 测试:
- 可以Postman测试,
- 或者直接浏览器输入地址测试
- 测试时可以去服务器查看文件是否加解密成功
- 打包方式:mvn clean package
8. erp扩展点代码处理
- 既然加解密程序提供的是Restful接口,那么我们可以直接在原加解密代码中调用该接口
- 具体实现思路和之前本质上相同,只是加解密的代码通过中间件实现
9. 环境配置说明(非文章分享主体,可跳过)
DEV环境
- 检查服务器:erp系统的pod是运行在172.16.xxx.xxx这个节点的,考虑到文件夹映射,我们把Spring Boot程序也部署在这台服务器;
- 为服务器配置JDK,上传编译后的jar
a) JDK配置,配置环境变量等
b) 运行小程序java -jar intekey-ext-1.0.0.RELEASE.jar
- 访问接口,可以正常得到返回结果,以及看到相关日志
- 配置自定义hosts
a) 172.16.xxx.xxx intekeyserver
- 配置文件夹映射(使erp系统和Spring Boot小程序可以访问同一个文件):
a) 主机路径:/intekey 容器内挂载路径:/intekey
- 检查服务器和容器内是否完成挂载
- 检查自定义hosts是否成功(ping)
- 启动测试,引入文件选择加密后的文件,引入成功
- 查看日志,可以看到解密后的文件,解密后大小是12510
SIT环境
SIT和DEV配置原理相同,这里只给出注意点
- SIT和DEV使用的都是172.16.xxx.xxx服务器,所以可以共用加解密程序
- SIT配置HOSTS、文件夹映射
UAT环境
- UAT环境比较特殊,用的是堡垒机和云。不过虽然环境特殊,但是本质上诉求并没有变化
a) 自定义hosts
b) 文件夹映射
i. 无法直接做文件夹映射:因为uat环境不是宿主机的关系,且k8s是独立的云上产品 - UAT配置的加解密机器是:10.190.xx.xx,所以诉求翻译如下:
a) uat的k8s的pod,添加一个hosts: 10.190.xx.xx intekeyserver
b) uat的k8s的pod,需要能够和 10.190.xx.xx的/tmp/erpfile/目录实现文件共享: - 基于以上诉求,确认以下方案:
i. 方案1:将10.190.xx.xx的/tmp/erpfile目录做成nfs共享给k8s
ii. 方案2:申请一块nfs,挂载到k8s的pod和10.190.xx.xx中 - 考虑到快速实现,目前是采用方案1
- 配置10.190.xx.xx的NFS
a) yum install nfs-utils
b) vi /etc/exports
/common/intekey/erpfile 10.190.x.x/24 (rw,sync,no_root_squash)
c) systemctl enable nfs-server
d) systemctl start nfs-server
- 检查NFS:showmount -e 10.190.xx.xx
- 配置自定义hosts
- 检查自定义hosts
- 配置nfs挂载
a) 直接在命令行挂载,提示没权限
b) 这里修改deployments的yaml,或者界面调整
c) kubectl edit deployments -n cloud-uat uat-mservice
volumeMounts:
- mountPath: /tmp/erpfile
name: intekey-nfs
volumes:
- name: intekey-nfs
nfs:
path: /kingdee/common/intekey/erpfile
server: 10.190.xx.xx
10. 界面修改
11. 验证成功
12. 测试成功
10. 总结(附架构图)
在将整个功能基本完成并交付测试的那一刻,我也难免松了口气,却也意识到自己完成了一项新的挑战。
其实不论是排查每项问题出现的原因,还是提供/调用接口,都是日常工作中的一环,之所以会感到挑战并决定记录下来,还是在 “跳过问题” 的那一环——借用中间件思想,执行加解密程序。
在确保不论是服务器环境,还是容器环境,以及本地都执行成功,只在erp系统的mservice这个pod执行java程序会触发报错时,除了满头雾水,脑子里剩下的只有接下来该怎么解决?
反复自排查了多次,也请教了系统平台的专家前辈进行跟踪,可摆在面前的,却只有血淋淋的现实:确实只有在那一特殊情况会出错,且加解密程序未报出任何执行日志。
那几天就连在卫生间通畅时都在思考,接下来要怎么做?
皇天不负有心人,吃好喝好,脑袋好好。
在社区随意翻阅资料时突然看到了“中间件”的相关文档,忙静下心去总结排查,找寻问题的关机点:
既然问题难以进一步解决,那么是否可以跳过这一步,借用其他赛道接轨?
在两天后,我终于拿出了一份答卷,赶在了功能交付时间之前,随即吃了三大碗卤面(不是)。
为便于理解,贴出一份加解密的架构图,以供参考:
名词说明:
cosmic:erp系统容器
加解密小程序:Spring Boot加解密程序
天喻:加解密程序厂商名