最近我在阅读一本安全方案的书《零信任网络:在不可信网络中构建安全系统》,它让我对应用的安全有了一次新的升级。当然了,这又是一本昂贵的,字数不多的 O'Reilly 的书。
在看这本书的期间,我突然有了一个新的安全实施方案: 依赖孪生——针对于中小型 IT 组织的依赖方案。(PS:其实这只是吹吹而已,并没有那么夸张)。所以,我就顺手写了一篇文章,记录一下相关的实践和模式。
在构建软件系统时,软件的一部分依赖于另外一部分,就产生了依赖关系。(『持续交付:发布可靠软件的系统方法』)除了,组织内部的软件依赖之外,一个为了快速满足于业务系统的软件系统,便会充斥大量的三方依赖——受益于开源软件的发展。
对于大型组织来说,依赖的管理及期风险控制变成一个极其重要的话题,它涉及到法律风险及安全漏洞两方面的问题。这里的法律风险指的是依赖相关的软件协议、出口限制等带来的问题。在我们引入软件包的时候,开源协议带来的风险问题可以人为地降低。而依赖的安全问题,则不是一件容易的事情。尽管已经有商业的软件,可以做这样的工作,但是对于大部分的企业而言,维护一个 IT 团队已经不是一件容易的事。
依赖管理之所以成为新的关注点是因为依赖地狱、安全风险。
谈到多重依赖的时候,不得不谈及依赖地狱。
依赖地狱,是指在操作系统中由于软件之间的依赖性不能被满足而引发的问题。[wiki]
依赖地狱有多种类型[wiki]:
依赖过多。一个软件包可能依赖于众多的库,因此安装一个软件包的同时要安装几个甚至几十个库包
多重依赖。指从所需软件包到最底层软件包之间的层级数过多。这会导致依赖性解析过于复杂,并且容易产生依赖冲突和环形依赖。
依赖冲突。即两个软件包无法共存的情况。除两个软件包包含内容直接冲突外,也可能因为其依赖的低层软件包互相冲突。因此,两个看似毫无关联的软件包也可能因为依赖性冲突而无法安装。
依赖循环。即依赖性关系形成一个闭合环路,最终导致:在安装A软件包之前,必须要安装A、B、C、D软件包,然而这是不可能的。
[wiki]: https://zh.wikipedia.org/wiki/相依性地狱
依赖冲突和依赖循环是我们在引入软件包的问题,这个问题对于那些运行时依赖的语言来说比较常见,诸如于 Java、Ruby、Python 等。而对于编译时依赖的语言,如 JavaScript,这个问题并不会那么痛点。为此比较常见的痛点便是依赖过多和多重依赖。
而多重依赖往往是经常出现安全漏洞的地方,如之前的 left-pad 事件。我们的项目依赖于 A,而 A 依赖于 B 库,而 B 库又可能依赖于 C 库。它会导致依赖的层层引用,导致我们无法人为地追踪每个库——这个问题在 JavaScript 社区特别严重(主要是 Node.js 相关)。
如下是 Angular CLI 生成的一个新的项目的依赖示例:
从表面上来看,我们只依赖于 Angular 相比的几个组件,但是实际上它生成的依赖树是这样的:
Angular 新项目依赖树
注
:上图由 npm2dot
及 Graphviz
生成。
对于只是使用类库,如 Java 的 *.jar
往往不会有这个问题。而对于诸如 Node.js 服务端项目中的 NPM 来说,它存在一个 preinstall
和 postinstall
的过程,在这个过程中会运行依赖开发人员的预设脚本。诸如于 Standard JS
的广告问题,又或者是 core-js
的寻找工作:
话说我真应该再写一篇文章:开源软件作者正在遭遇的收入困境。毕竟 core-js
的项目被 3,407,074 个项目依赖,而作者并没有因此带来太多的收入。还好,我已经放弃了用开源软件赚钱的方式。
在有了 NVM 的情况下,你并不会用 sudo
去执行 npm install
或者 yarn install
,否则开发人员可以在脚本中添加一个 rm -rf /
。不过,对于大部分前端项目来说,只是在客户端执行 npm install
。哪怕是采用 Node.js 的系统来说,也只会在容器里运行 npm install
。
应对这些开源软件,便有了一系列的解决方案。诸如于 Black Duck 或者是 SonarQube:
Black Duck,是当前在这一方面最全面的开源组件、漏洞和许可信息数据库,Black Duck 软件组成分析解决方案和开源审计为您提供必要的洞见,用于跟踪代码中的开源、降低安全性和许可合规性风险,并使用您现有的 DevOps 工具和流程自动实施开源策略。
当然了,对于还有 SonarQube 也是一个不错的方案,只是 SonarQube 更关注于代码质量。对于大型组织来说,这都是小问题。而中小型组织来说,要去维护这些基础设施并不是一件容易的事。
为此,我们就有了依赖孪生这样扯淡而又有意思的解决方案。
依赖孪生(dependency twins,依赖映射 depencecy mapping)是将项目依赖状态信息(包括元数据,配置和条件)用模拟真实的项目(类似于内部环境的双胞胎)的形式,存储在第三方的信息化平台上来,以用于进行依赖的安全检测。稍有不同的是,它是免费的,并且你还不需要开源你的代码。
即,我们构建一个虚拟的项目,在这个项目中只存储依赖信息,如软件包的名称和版本,随后将运行在提供这样功能的平台上,比如 GitHub。它既可以帮助我们检查依赖,又可以保存代码的安全性。
所以说,这是一个适用于小型组织的方案。
上传项目的依赖到 GitHub 的私有、私有、私有项目中
查看项目的 Security Alerts
Done
你还有什么更好的 idea 吗?