在最近的几个月内,软件供应链安全问题不断被提及。从最近的总统行政令到世界上用户最活跃的开发者讨论板块,以及开源软件小组讨论板块等诸多地点,软件供应链安全以及软件物料清单(software Bill Of Materials)问题正在逐渐步入大众的视野。
组成产品本身的所有组件的整体被称为供应链。与实体产品不同,软件开发的供应链定义要相对松散很多,这一点在以下的这些例子中可以看到更直观的对比,还可以从这些例子中分析其相同与不同之处。首先以汽车为例,汽车的组装只允许使用通过精心设计和挑选的部件,以便供应商对汽车质量进行把控,以及管理全部制造流程的结果。
再以一个典型的软件开发过程为例。软件开发过程中的重点一直都在于如何解决技术上的难题,而内部流动的组件却从未被严格控制或管制,开发者随时可以根据项目需求引入非标准的库,完全没有仔细筛选或者安全性的概念。这种组件引入方面松散的定义完全是软件开发中供应链定义松散的结果。再加上实际开发的过程中还有其他各种的工作流程,比如模拟、测试以及部署,都会引入大概率未经测试的新组件到产品的生命周期之中。软件供应链可以说是 DevOps 行业这条过度追求加速与部署速度的超高速公路上无可避免的减速带。
发起软件供应链攻击的方式有很多。一般来说,软件的组件是需要验证才可以在部署的管道上工作,而这些组件应该也是可以访问主机基础设施的各种内部的。比如授予用于测试和断言各种结果的库,对互联网和本地 Web 客户端(通常是无头浏览器的形式)的完全访问权就是一个例子。而随着测试载体的复杂程度不断增加,又将会给予这些库对本地系统(比如文件系统)更多的访问权限。这就造成了一个相当宽广的攻击面。想象一下,如果这些库中被插入了恶意代码,那么当软件在生产环境运行的过程中,这些恶意程序被过度认证,获得了对全部已有资源的访问权,从而可以从内部执行对软件的攻击。
DevOps 中的许多原则都让软件开发不得不站在了安全的对立面。具体来说,DevOps 与软件开发生命周期中供应链的安全问题无法对齐标准。下面让我们来分析 DevOps 中的几个原则:
DevOps 的原则经常建议开发者每日发布 M 次,更快 N 倍。这种快节奏的部署导致团队用于审核新软件 APP 中组件的时间少得可怜,而 DevOps 开发团队重点关注的指标始终是降低更新的失败率,对软件中实际应用的组件来源和安全性验证工作并没有直接的作用。在这种高频率部署的情况下,精力有限的团队很难再有时间保证软件中所有使用到的组件都能有适当的记录和说明。
开发团队通过修正构建流程中的开发、测试、部署和支持生产中的发布,让流程维护更快、更一致。很多的构建工具允许用户通过任意的安装命令执行依赖性注入,并直接对接功能性软件中的内部组件。为构建流程中的复杂性再雪上加霜的,还有各种微服务和多角化应用。而这种结果就是,所有的服务都将生成各自的独立构建和迁移流程,这与构建流程目标的透明和可审计性是背道而驰的。最终,构建流程变成了小黑盒,并进一步向其他部分蔓延,产生了潜在更大的攻击面。
在工作中应用 DevOps 模式与使用 Agile 敏捷开发的情况很是类似。在工作之中,敏捷开发者们经常会发现自己分配给非开发工作的时间几乎没有。在观察敏捷方法论的这些年里,作者从没遇到过有开发者会把组件溯源和安全验证当作任务分配的故事点。敏捷中的所有过程,无论是项目规划、计划预估、进度追踪,组件的验证和听众规划很难在这种不稳定的项目管理中完成。
在大多数的公司之中,部署就像是多米诺骨牌,从某种良性的模式开始一路排开,形成一条从开发者工作站到生产服务器阻力最小的路径。沿着这条路径,我们能找到好几个不同的节点,都易于受到供应链攻击。
需要重点关注的节点有二。其一是当开发者准备将组件集成到开发中的应用程序的时候。这一点用汽车组装来比喻的话就是,使用经认证部件的比例与汽车安全系数的正相关。如果机工们可以使用任何可用的零件,那么汽车的标准化与安全性就不能够得到保证。其二则是构建管道的时候。已有大量的案例为我们敲响警钟,在交付管道中一旦被插入恶意组件,在黑客们成功进入超额配置的环境后,就可以对自己进行断言(assert)。
开发者,尤其是开源代码的贡献者们,通常对组件安全性颇有怨言。他们要做的是解决技术问题,阅读理解代码规范清单的耐心和精力有限。他们渴望的是无拘无束的产品创新,而不是层层叠叠的代码监管,任何的指责埋怨都会让他们干劲衰减。这必然是软件开发中百害无一利的情况,但对这种情况我们能想到什么解决方法呢?
整体来看,缓解软件供应链攻击的解决方案有很多途径可选。这套解决方案简单可行,就像是所有的安全系统一样,最先要做的就是对开发者的培训,让他们明白自己的责任所在,之后才是要找到一个可以在不干扰他们工作流程的前提下将安全纳入考量的代码实践方法。
解决方案的其中一个环节是软件物料清单(SBOMs)。简单来说,SBOMs 是一个正在运行的应用程序中所有组件和依赖关系的综合清单。不同的软件组件可能会在不同的阶段与应用程序进行接触,SBOM 则会作为仓库对这些信息进行存储,有助于开发人员对依赖进行选择性透明化,更利于安全规范和审计。在 Java 的生态系统中,SBOMs 物料清单最早的表现形式是 Maven,一款可选的 Java 构建工具。而现在,人们更常用的则是以 Docker 镜像作为不可变组件进行构建实践。这种方式一般都具有极高不透明度,不允许开发人员得知镜像内部的组成。
更新潮的容器镜像生成方法是使用云原生打包工具(Cloud Native Buildpack)或者用命令行工具(pack CLI)。云原生打包工具(CNB)可从应用程序源码中导出 OCI 兼容的容器镜像,其本身则是一组用于打包的详细规范。生成的构建包首先需要检查源码,启动创建过程,最后才是导出生成的容器镜像。CNB 规范为容器生命周期中的创建和维护部分贡献不菲。在整个堆栈中,无论是基础镜像、依赖,还是应用程序的运行时,都需要周期性进行安全性检查及更新。云原生构建工具会在容器最终镜像的架构中引入独特的层并使用容器注册表,让服务维护起来更加轻松。通过 CNB 规范,我们可以在几秒内大规模更新数千镜像,而通过传统方式构建的容器镜像则要花费更长的时间进行更新。
除此之外,CNB 规范还需要镜像内部构建和导出过程中生成的元数据进行保存,这些元数据可以帮助开发者们确定容器镜像中每一层的构成以及应用程序的组件和依赖项。
//paketo.io/)为例,这是一款CNB规范的开源实现,其为容器镜像通常会遇到的缺乏透明度相关的问题提供了一种直接的解决方案。Paketo打包工具同时还为安全地重复进行的构建过程提供了基础。这两大优势相结合,为前文中我们所提到的软件供应链安全问题解决提供极大助力。 :
pack inspect-image test-xchange
Inspecting image: test-xchange
REMOTE:
present)
LOCAL:
Stack: io.buildpacks.stacks.bionic
Base Image:
Reference: bace2b890e3a242b9ad9c6e4e882e1dc471ee27a7db59ec19745efc7345e2a51
Top Layer: sha256:863853c5b183a0b88e5a8cd6f1b37ca5d3b4c6bf10a4338ff45e01befdf737d6
Run Images:
base-cnb :
base-cnb :
Buildpacks:
ID VERSION
0.1.5
0.2.4
0.0.3
Processes:
TYPE SHELL COMMAND ARGS
web (default) bash node server.js
打包命令的自动化流程让开发者们无需任何额外的操作,pack 可以直接通过 Paketo 打包工具导出容器镜像。至于软件供应链的安全问题,Paketo 采用了一种元数据的结构化格式,对镜像中所使用的组件进行精准描述,让希望实施合规性与安全策略的组织可以做到开箱即用。生成的物料清单将协助工程团队做出更明智的决策,从而有效缓解软件供应链上游的安全漏洞风险。
具体的过程我们可以通过运行 pack inspect-image 命令来一探究竟。
这张截图中展示的是使用 pack 构建命令为 JavaScript Web 应用程序创建的物料清单检查。它存储元数据时会将其与用于创建容器镜像的所有构建包关联在一起。这个链接中的 GitHub 将展示另一种通过容器镜像为 Java 应用程序创建物料清单的示例。除了上文截图中的信息之外,链接中的示例还包含了许可证的元数据、依赖,以及其他组成一个综合的物料清单所需的其他信息。
Paketo 构建包及其软件物料清单,都为提高软件供应链安全提供了起始点。在 DevOps 的应用开发流程中应用构建包有助于缓解许多安全问题带来的紧张局势,再加上构建包可以自动生成包括 SBOMs 在内的诸多有用文件,Paketo 非常适合用于提高生产力。
构建包将对软件工程团队,特别是小型和初创公司,有极大的吸引力。这种构建方式潜移默化,无需开发人员在工作流程额外付出时间和经历。而 Paketo 的社区同时也在致力于标准化所有构建包的 BOM,在未来将为那些希望为软件组件溯源追加审计的 DevOps 开发者们提供更好的帮助。
概括来说,下面是我们在前文中所涉及到的供应链安全问题,以及 Paketo 构建工具所提供解决方案的总结。
首先是现代工程团队在项目中所侧重的指标。最常用的 DevOps 指标是发布频率、容量变化,以及部署时间。这些指标与创建部署或发布的软件中所使用组件的审计追踪几乎毫无关系。将构建过程中软件物料清单的生成过程自动化,是确保软件发布与其所使用组件元数据紧密耦合的好办法,而这一步骤构建工具已经为我们做好了。随着发布频率的提高,SBOMs 的更新频率也会有所提升,这一切都是自动化的功劳。
每次部署时生成的 SBOMs 都可用于任何的审计需求。通常来说,这些审计都是异步,或者在安全事故发生的时候才会进行。通过对比是否有使用物料清单的情况,我们可以发现,根据各个团队对安全性和规范性要求的不同,软件物料清单可能会需要审计。而在没有 BOM 的情况下,任何形式的审计都将变得无比困难且非常耗时。
因为 Paketo 构建包的软件物料清单是可以自动生成的,所以不会影响到敏捷开发团队在迭代周期(sprint)中对任务的预估和追踪。正如工程团队在迭代周期期间或结束时会有成果展示一样,准备发布同样需要与发布版本相对应的 SBOM。软件物料清单与构建过程之间的耦合十分紧密,确保了这类元数据可在不降低生产速度的前提下生成。
原文链接:
https://www.infoq.com/articles/buildpacks-software-supply-chain/
点击底部阅读原文访问 InfoQ 官网,获取更多精彩内容!
汇集全网最深度技术内容,聚齐各领域最优秀创作者
InfoQ 引航计划正式启动,下一个引导技术领域共建发展的 Pioneer 就是你!
扫描下方二维码获取更多活动信息!
点个在看少个 bug 👇