开发人员经常想在安全性方面做“正确”的事情,但是他们并不总是知道那是什么。为了帮助开发人员继续快速发展,同时获得更好的安全性,大多数组织都正在转向DevSecOps。
DevSecOps 是一种思维转变,通过在整个开发过程中不断集成安全性,使应用程序开发生命周期中的各方都对应用程序的安全性负责。实际上,这意味着将安全审查和测试从部署时的审计或强制执行转移到开发侧,也可以在构建或开发时更早地检查安全控件。
对于开发人员编写的代码,这意味着在开发过程中需要提供有关问题的反馈,这样开发人员就不会失去他们的工作流程。这意味着您的代码会作为软件供应链的一部分,成为其他软件的依赖项。对于如何做到这一步,首先你定义一个依赖项。
依赖关系是软件运行所需的另一个二进制文件,指定为应用程序的一部分。使用依赖项可让您利用开源的力量,并为不是应用程序核心部分或您可能不是专家的功能引入代码。但是据 GitHub 2019 年发布报告显示,平均而言,每个存储库都具有200多个依赖项。这些依赖关系中任何一个的上游漏洞,就意味着您也可能会受到影响。
于是,对于软件供应链的现实是,您依赖于未编写的代码,但是这些依赖关系仍需要您的工作才能持续进行。那么您应该从哪里开始实施安全控制呢?
创建统一的 CI / CD 管道以向开发侧移动安全控制
DevSecOps 的目标之一是在开发环境中不仅提供反馈,而且还提供一致性和可重复性。这并非您的供应链所独有,它适用于任何安全控制。
越早统一 CI / CD 管道,就能越早实现控件,从而使安全控件向开发端侧移动。您不想在不同的系统中多次应用相同的控件——它无法扩展,无法分散您(已经精简的)安全资源,甚至更薄,允许通过漂移或系统不兼容而引入不一致的情况,这可能是最糟糕的情况,表示您可能会错过一些东西。
事实上,向开发侧靠近和应用 DevSecOps 的前提根本不是安全控制,而是要改进开发人员的工具,即使没有统一所有其他步骤,也可以开始将安全控制应用于代码。以开发人员为中心的方法意味着您的开发人员可以在编写代码时保持上下文状态并响应问题,而不是在部署后几天或在渗透测试报告后数月。
在统一的 CI / CD 流水线的基础上,这里有一些技巧,说明您的开发团队如何应用 DevSecOps 来保护软件供应链。
声明代码中的依赖项,以便您在开发时发现它们
首先,为了维护您的依赖关系(例如,应用安全补丁),您需要知道您的依赖关系是什么。
有多种方法可以在开发过程的不同部分检测依赖关系:通过分析代码中声明的依赖关系,例如,由开发人员在清单文件或锁定文件中指定的依赖关系;通过跟踪在构建过程中引入的依赖关系;或检查完成的构建工件,例如,一旦它们进入您的注册表中。不幸的是,没有完美的解决方案,因为所有方法都面临挑战,但是您应该选择与现有开发流程最紧密集成的解决方案,或者使用多种解决方案来深入了解开发过程中每个步骤的依赖性。
检测代码中的依赖关系是有好处,将依赖关系管理步骤向开发端侧移动,这使得开发人员可以立即维护依赖关系-执行更新,应用安全补丁或删除不必要的依赖关系,无需等待构建或部署步骤的反馈。而且,如果您没有集中的或一致的构建管道,并且以后无法应用检查,则检测代码中的依赖项意味着您仍然可以推断出此信息。检测代码中的依赖项的主要缺点是,您可能会错过以后引入的任何工件,例如,Gradle 允许将依赖项作为构建的一部分进行解析,这意味着构建时检测将包含更完整的信息。
为了准确地检测代码中的依赖关系,并更轻松地控制使用的依赖关系,您需要将其明确指定为应用程序清单文件或锁定文件的一部分,而不是将它们供应到存储库中(将依赖项的副本作为项目的一部分进行分叉,也称为复制粘贴)。如果您有充分的理由来分叉代码,例如修改或限制组织的功能,或者将其用作查看依赖关系的步骤(您知道,实际上是跟踪软件供应商的输入),则可以使用软件供应商。
但是,如果您打算使用上游版本,则软件供应商会使更新依赖项变得更加困难。通过显式指定依赖项,开发团队可以更轻松地进行更新:在清单中更改一行代码,而不是重新派生和复制整个存储库。在某些生态系统中,您可以使用锁定文件来确保一致性。
为您的开发团队提供铺有“黄金”包装的道路
您可能已经熟悉“黄金”映像的概念,该映像由组织维护和批准,包括最新的安全补丁。这是容器的常见概念,可为开发人员提供基础映像,使他们可以在其上构建容器,而不必担心基础操作系统。这里的想法是仅维护一组由中央团队管理的操作系统,您知道这些操作系统已经过安全性审查并已在您的环境中进行了验证。所以,那为什么不对其他任何工件也这样做呢?
为了补充统一的 CI / CD 管道,您可以提供一组维护的工件和库的参考集。这只是一种先发制人的安全控制——无需在构建软件包后就验证软件包是否为最新版本,而是为开发人员提供所需的内容,以作为其构建的输入。
例如,如果多个团队正在使用 OpenSSL,则不需要每个团队都对其进行更新。如果一个团队对其进行了更新(并且已经进行了足够的测试!),那么您应该能够更改所有团队的默认设置。这可以通过以下方式实现——对您已知的优良工件进行集中的内部软件包注册表,该注册表已经通过了任何安全要求,并且由明确的所有者负责更新。
通过提供一组软件包,可以确保所有团队都参考这些软件包。请记住,最新的操作可以在构建系统中进行,但这也可以在代码中更早地完成,尤其是在使用 monorepo 的情况下。
共享常见工件和库的另一个好处是,可以更轻松地判断您是否受到新发现的漏洞的“影响”。如果相应的工件尚未更新,那么您就是!然后,这只是解决问题的一种更改,并且所有更新都可以向下流向所有团队。
自动化下游构建和部署
为了确保开发人员的辛勤工作得到回报,他们的更改实际上需要付诸生产!在创建统一的 CI / CD 管道时,您清除了对开发环境中的代码所做的更改以向下游传播到测试和生产环境的路径。下一步是通过自动化简化此过程。在理想的环境中,您的开发团队只对开发环境进行更改,对该环境的任何更改都会自动推送到测试,验证和自动推出(并在需要时进行回退)。
您无需通过要求开发团队学习操作工具来应用 DevOps 和 DevSecOps,而是可以简化这些工具并反馈这些团队需要了解的知识,以便在代码中最熟悉的地方进行更改。这听起来应该很熟悉的,诸如代码基础架构或 GitOps 之类的趋势所发生的背景——在代码中定义内容,并让您的工作流工具处理实际更改。
如果您可以自动化代码的下游构建,测试和部署,那么开发人员只需要专注于修复代码。遵循 DevSecOps 原理,他们无需学习工具即可进行验证测试,分阶段部署或环境中可能需要的任何操作。至关重要的是,为了安全起见,您的开发团队无需学习如何推出修补程序即可应用修补程序。修复并提交代码中的安全性问题足以确保它最终在生产中得到修复。相反,您可以专注于快速查找和修复代码中的错误。
创建统一的 CI / CD 管道可让您向左移动安全控制,包括供应链安全。然后,为了最好地应用 DevSecOps 原理来提高依赖项的安全性,您应该要求开发人员在代码中声明依赖项,然后为他们提供维护的“黄金”工件和自动化的下游操作,以便他们可以专注于代码。由于这不仅需要更改安全控制,还需要更改开发人员的经验,因此仅使用安全工具不足以实现 DevSecOps。除了启用平台本机依赖性管理功能外,您还需要仔细查看 CI / CD 管道和工件管理。
总之,应用 DevSecOps 意味着您可以更好地了解软件供应链中的内容。通过使用 DevSecOps,应该更容易管理依赖项,只需更改清单或锁定文件即可轻松更新多个团队中正在使用的单个工件,并自动执行 CI / CD 管道,以确保开发人员可以迅速将变更最终投入生产。
原文链接:https://github.blog/2020-12-03-applying-devsecops-to-your-software-supply-chain/
评论