首页 > 其他分享 >生产事故-错误密钥引发的接口通信问题

生产事故-错误密钥引发的接口通信问题

时间:2022-12-23 12:55:06浏览次数:43  
标签:事故 接口 问题 打包 测试环境 密钥

入职多年,面对生产环境,尽管都是小心翼翼,慎之又慎,还是难免捅出篓子。轻则满头大汗,面红耳赤。重则系统停摆,损失资金。每一个生产事故的背后,都是宝贵的经验和教训,都是项目成员的血泪史。为了更好地防范和遏制今后的各类事故,特开此专题,长期更新和记录大大小小的各类事故。有些是亲身经历,有些是经人耳传口授,但无一例外都是真实案例。

注意:为了避免不必要的麻烦和商密问题,文中提到的特定名称都将是化名、代称。

0x00 大纲

目录

0x01 事故背景

2021年3月19日11时30分,C公司业务人员向外包A公司开发人员反映某业务登记系统从9时许开始无法使用某关键业务接口。该接口依赖于B公司提供的服务,所以刚开始怀疑过是网络波动的问题,经运维人员检查,证明网络连通性没有问题。后来尝试过重启应用服务,也还是不能解决。怀疑是2021年3月18日夜间升级后的系统版本存在缺陷。为了避免进一步影响业务处理,果断先采取系统回滚处理。回滚后,系统业务功能于2021年3月19日12时恢复正常。

0x02 事故分析

为了对问题进行定位和分析,第一时间让运维拷贝和固定了更新前后的系统日志和应用包。奇怪的是,日志上并未见明显异常,调用接口的相关日志没有看到任何 ERROR 级别的日志或者异常堆栈信息。追踪了若干次业务接口调用,均是对端无任何返回,正常情况应该会返回类似{"code":"200","msg":"succeed"}的响应码和响应信息。尝试在测试环境上复现问题并断点跟踪调试,测试环境问题未复现!无奈开始走查代码,但反复查看变更内容,都是与该接口无关的非关键性变更。按道理不可能影响到接口调用。

问题的线索似乎都断了。洗了把脸,重新梳理了目前的几个基本情况:

  • 变更升级后才发生的问题
  • 变更的代码非关键性代码,与接口调用和通信无关
  • 回滚后系统恢复正常
  • 测试环境未能复现
  • 问题不是偶现的

想到这里,一个想法已经呼之欲出,难道是打包的问题?于是拿到了当时部署的war包和与测试环境上的war包进行解包比对,除了配置文件之外其余文件都没有差异,而这正是问题所在。

0x03 事故原因

这是一个通过加密数字信封进行信息交换的接口,数据格式为JSON,加密方式为RSA非对称密钥加密,双方交换公钥,保留自己的私钥,从而实现可信通信。通信过程如下图所示:

通信示意

对方的公钥被打包在应用包中,随着应用一同发布。然而,生产环境和测试环境使用的RSA密钥对是不同的。负责打包的小T,在进行生产应用包打包时,忘记将测试环境的公钥替换成生产环境的公钥了!替换密钥并重新打包部署到生产环境后,业务验证成功。此时已是2021年3月19日13时05分。

0x04 事故复盘

这里面存在一系列的不规范行为,最终导致了问题的发生。但凡有一个环节做好了,可能都可以避免这次事故,或者说更快地定位到问题。

  • 首先是密钥的存储方式。将密钥直接打包到应用包里面是非常不合理的,尤其是它可能发生可预见的变更时。哪怕外置到其他目录,或者存储在数据库中,也不至于发生如此惨案。
  • 其次是打包的问题。生产环境的包,居然是开发人员在自己机器上打包,然后通过跳板上传到生产服务器上进行部署。不但有些配置容易遗漏,也存在重大的风险隐患,哪怕没有现代化的现代CI/CD管道工具,也应该脚本化和自动化打包。
  • 最后是对端在解密和验签失败的情况下,居然没有任何返回。当然,不能要求外部系统能达到自己软件质量标准,这是不科学的,但是作为一个反例,也提醒了各位开发人员在设计接口时注意规范性,尤其是要给别人用的。

0x05 事故影响

造成C公司关键业务停摆三小时,生产系统紧急回滚一次。A公司吃到客户投诉一张,相关负责人连夜编写事故报告一份。

标签:事故,接口,问题,打包,测试环境,密钥
From: https://www.cnblogs.com/mylibs/p/production-accident-0001.html

相关文章

  • ABP 调用swagger里面的 POST接口报错400
    请求报错修改......
  • 41聊聊对自动化和接口的理解
    用代码写自动化测试接口测试我觉得不难对业务逻辑挺重要的比如先构思一下流程过程最好自己整个流程图知道了它想要实现什么了然后开始写代码我对python的使用有一......
  • Go语言基础之接口
    接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。接口本章学习目标了解为什么需要接口以及接口的特点掌握接口的声明和使用掌......
  • 基于.NetCore开发博客项目 StarBlog - (25) 图片接口与文件上传
    前言上传文件的接口设计有两种风格,一种是整个项目只设置一个接口用来上传,然后其他需要用到文件的地方,都只存一个引用ID;另一种是每个需要文件的地方单独管理各自的文件。这......
  • express的使用:接口的编写(三)
    1.接口的跨域问题a.CORS,主流b.JSONP,只支持get请求步骤:a.安装npminstallcorsb.使用 constcors=require('cors')导入中间件c.在......
  • Go 快速入门指南 - 接口和方法
    接口Go接口是隐式实现。 对于一个数据类型,无需声明它实现了哪些接口,只需要实现接口必需的方法即可。当然了,存在一个小问题就是:我们可能无意间实现了某个接口:),所以 ......
  • Go 快速入门指南 - 判断是否实现接口
    判断是否实现接口Go里面没有 implements 关键字来判断一个结构体(对象)是否实现了某个接口, 要实现类似的功能,需要用到 类型断言。类型断言// 判断 v 是否实......
  • 接口优化技巧~~优雅
    前言之前工作中,遇到一个504超时问题。原因是因为接口耗时过长,超过nginx配置的10秒。然后真枪实弹搞了一次接口性能优化,最后接口从11.3s降为170ms。本文将跟小伙伴们分享......
  • js在post后台接口的时候,一行代码完成删除对象中所有值为null、undefined或为空字符串
    vard={a:1,b:null,c:3,d:undefined};Object.keys(d).forEach(k=>d[k]==null&&deleted[k]);//去掉值为null或undefined的对象属性//Object.keys(d).f......
  • redis c++接口
    redis接口redis是c语言写的,有c接口,无c++接口。在一个负载均衡服务器项目中,用过一个redis的c++接口类。简单粗暴上代码吧,需要的自行移植一下。/**redis_interface.cpp*Aut......