“在数字化转型的浪潮中,DevOps作为推动软件开发与运维高效协同的重要实践模式,正逐步成为企业的标配。然而,在追求速度与创新的同时,如何确保系统的安全性与合规性,成为了摆在众多企业面前的一道难题。传统的“DevOps + Sec”模式,往往将安全视为后期添加的组件,不仅影响了开发流程的流畅性,也难以真正实现全面的安全防护。因此,“Sec in DevOps”的理念应运而生,倡导将安全融入DevOps的每一个环节,实现安全与效率的深度融合。 为了帮助企业顺利过渡至DevSecOps模式,本文提炼出了12个关键实施要点,旨在指导企业在软件开发生命周期的各个阶段,都能将安全考量置于核心位置,从而构建起一个既高效又安全的开发运维体系。
引发 DevSecOps 的这个概念背后有很强大的变化,安全一般来说是服务于其他信息技术,如果相应的技术或者解决方案或者流程发生变化,安全也要随之改变,否则无法适应新的技术的安全要求。这里面的最重大的变化有三个:
在 DevOps 的过程中发现,安全的问题需要考虑进来,按照历史的惯性,一开始只是开发运维走到了一起,安全的要素还是事后考虑,大部分的情况下安全人员还是属于事后处置,安全效果没有得到很好的提升,一个很明显的现象是开发人员在部署最新的技术架构,而安全人员还在关注传统的安全问题。
为了解决这个问题,所以在整个流程中加入了安全的人员形成了 DevSecOps 这种协同机制或者特殊岗位,可以让安全人员更早的介入开发和运维的过程,让安全的措施向前移动,主要的目的是让所有的技术人员都对安全负责
Gartner曾预测,到 2021 年,60% 的快速开发团队将采用 DevSecOps 实践,而 2019 年这一比例为 20%。 到 2023 年,超过 70% 的企业 DevSecOps 计划将纳入针对开源组件和商业软件包的自动安全漏洞和配置扫描,这比 2019 年的不到 30% 有显著增长。
从《中国DevOps现状调查报告(2023)》,可以看到DevSecOps 在企业中的影响力继续扩大,实践DevSecOps的企业首次突破七成。
调查显示,已有 72.71% 的企业引入了 DevSecOps 实践,同比增加 14.48%;尚未引入 DevSecOps的企业占比下降至 27.29%。可见,将安全融入到 Devops 的各个阶段,是企业建设 Devops 平台的重要趋势。
如果正确实施,DevOps 可通过采用一种协作理念来打破传统的开发和运营孤岛,从而提高 IT 组织的开发速度。然而,在大多数情况下,安全性和合规性仍然是开发过程本身的后续考虑。
通过与客户的对话以及对成功的 DevSecOps实践分析,我们了解到了哪些方法有效、哪些方法无效以及哪些方法最为成功。在这里,提供了具体的指导来解决安全和风险管理领导者需要正确处理以下12 个领域,以成功实现 DevSecOps。其中许多活动还将增强更传统开发环境中的应用程序安全性。
DevOps 的哲学原则为成功将应用程序安全性集成到 DevOps 流程提供了指导。DevOps 的最著名的原则之一,就是以尽可能快的速度在系统中“移动工作”为目标。因此,领先的组织每隔几秒钟就会部署一次代码,尽可能在早期向开发人员提供反馈。传统的应用程序安全流程侧重于通过耗时的网关在项目后期提供完整反馈,不适合 DevOps 的需求。
不要强迫 DevOps 开发人员遵循信息安全陈旧、重量级、以检查点为中心的流程。相反,应在整个持续集成/持续部署 (CI/CD) 工具链和流程中无缝集成持续安全保障。对于习惯于强迫开发人员遵守其流程的信息安全专业人员来说,这代表着重大转变,因此需要进行几项变革:
“完美是优秀的敌人”。 特别是在数字商业领域,信息安全对完美安全性的追求与企业和开发人员对速度和敏捷性的需求相矛盾。完美的安全性和零风险是不可能的。
我们必须采用持续、自适应的基于风险和信任的评估战略方法,并将应用程序漏洞的优先级纳入 DevSecOps。试图从应用程序中删除所有可能的漏洞的徒劳尝试会减慢开发人员的速度,导致他们浪费时间追逐不真实的问题(误报)或解决真实存在但无法直接或轻易利用的低风险漏洞。
测试速度、误报浪费开发人员时间以及误报风险增加之间存在权衡。对于 DevSecOps,信息安全必须接受零漏洞既不可能也不可取,如果它显著减慢了新服务交付和创新的速度。 此外,您还可以使用运行时控制来补偿已知、低风险漏洞或引入生产的未知漏洞的大部分剩余风险。示例包括基于网络和主机的入侵防御系统 (IPS)、拒绝服务 (DOS) 和分布式 DOS (DDOS) 保护以及 Web 应用程序和 API 保护。
通过将 DevSecOps 中的应用程序安全视为一个涵盖开发和运营的持续改进过程(如下图),您无需消除开发中的所有潜在漏洞。相反,您可以将运行时保护视为 DevSecOps 策略的一个组成部分。
安全性并不止于开发阶段(图 左侧)。整个 DevOps 生命周期都需要得到保护,包括将新服务部署到运行时操作中(图右侧)。与开发一样,安全性也正在成为一个持续交付、学习和改进的过程——Gartner 的持续自适应风险和信任评估捕捉到了这种思维转变。 在开发阶段执行基于风险的扫描,接受一些漏洞会通过,并通过持续的运行时评估和保护来弥补这种风险。最后,如果没有监管缺陷,可接受多少风险不是信息安全的责任。这是一个业务决策,最终由产品/服务所有者和其他利益相关者做出。
现代软件通常是组装的,而不是开发的。开发人员大量使用来自公共资源和存储库(如 GitHub / Docker Hub)的预构建组件、库、容器和框架。自定义代码通常只占现代应用程序代码的一小部分。
这导致安全扫描的重点发生转变,因为大多数风险可以通过在这些库、框架和组件投入生产之前识别其中的已知漏洞和已知配置错误问题来解决。从安全角度来看,识别已知代码中的已知漏洞比识别自定义代码中的未知漏洞要容易得多。这可以通过多种方式完成,最简单的方式是将文件与漏洞库进行匹配。漏洞评估供应商正在调整其扫描功能以满足在 DevSecOps 中自动执行此操作的需求,这种最佳实践的重要性怎么强调都不为过。
开源软件 (OSS) 提出了独特的挑战,因为开发人员可能只是剪切和粘贴源代码,而不是链接到整个库或框架。这不能简单地使用哈希值来识别,而识别需要对源代码本身进行全面扫描。此外,由于许可条款,使用 OSS 可能给组织带来法律风险。因此,建议采用商业软件组成分析 (SCA) 解决方案来为应用程序构建详细清单(物料清单)。此清单还有延长生命周期的好处。如果后来发现正在使用的组件包含严重的安全漏洞,安全团队可以通过查询存储库快速回答“哪些应用程序受到了影响?”(例如,Apache Struts,或 OpenSSL 的 Heartbleed 攻击)。
sbom-1200-×-628-px-new-768x402.png
这凸显了一个应该由安全和开发架构师共同解决的流程问题——是否应该允许开发人员直接访问公共互联网下载代码。对于一些组织来说,这种风险被认为太高,因此禁止开发人员直接从互联网上下载这些代码。对于其他组织来说,这种风险是通过将用户限制在公共互联网上的托管代码存储库(例如 GitHub)来管理的。但是,这些存储库中保存的是较旧的、已知易受攻击的软件版本,开发人员可以下载这些版本。
为了解决这个问题,安全提供商提供了 SCA 工具,向开发人员公开库的安全状况,以便他们能够做出明智的决定,确定使用哪个版本。使用这种方法,组织有时可以明确阻止下载已知严重漏洞的组件和库——例如,根据分配的常见漏洞和暴露 (CVE) 的严重程度。其他方法在开发人员浏览代码时标记有问题的软件包,所有工具都会在测试过程中搜索问题。
不允许开发人员直接从公共互联网下载代码的组织需要考虑安全的代码存储库模型。在这里,开发组织与信息安全团队合作,构建、审查和维护内部托管的组件存储库。这种方法需要开发架构师和信息安全部门之间持续承诺保持最新状态,并需要开发人员请求新框架和库的流程。此外,一些组织将要求使用预先批准的标准库来进行常见的安全关键操作(例如身份验证、授权、密钥管理、加密、点击劫持和输入清理),以进一步降低风险。
开发人员工作单元的全部内容(包括虚拟机 (VM)、容器和机器映像)以及容器应得到全面支持。在评估应用程序是否存在已知漏洞时,SRM领导者应扫描:
“
“扫描”的概念还应扩展到识别恶意软件和敏感数据,而不仅仅是编码漏洞。领导者应确保加密密钥和其他秘密数据不会意外嵌入代码中。因此,扫描还应包括:
“
在上一节中,强调了在已知组件、库和框架中识别已知漏洞的重要性,但应用程序中 10% 到 40% 的自定义代码又该如何应对呢?
在 DevSecOps 中,您应该扫描自定义代码中的未知漏洞。但是,不要指望使用传统的静态/动态应用程序安全测试 (SAST/DAST) 工具和服务而不做任何更改。这些传统的测试解决方案需要重构、重新调整或替换。
请遵循以下步骤:
无论您执行哪种安全扫描,领导者都应按风险对为开发人员发现的漏洞进行优先排序。接受低风险漏洞是可以接受的,并且可以通过运行时缓解保护控制或在软件的未来迭代中解决。
作为传统 SAST 和 DAST 的替代方案,我们建议尽可能采用交互式 AST (IAST) 方法。IAST 结合了 SAST 和 DAST 的属性,在测试期间利用应用程序的检测。这提供了由外而内和由内而外的可见性。这种组合使 IAST 方法能够提供更好的功效平衡——DAST 的误报减少与 SAST 的精确代码行和代码覆盖率可见性。但是,这种方法在平台支持方面仍然有限,并且要求在运行状态下组装应用程序。
DevOps 产品团队中的每个人都应该接受安全培训,并且根据角色的不同,培训内容会有所不同。开发人员接受的培训最多,测试人员接受的培训差不多,产品负责人接受的培训较少。不能也不应该试图让这些团队成员成为安全专家。但是,可以培训所有开发人员了解安全编码的基础知识以及应用程序可能受到攻击的方式。
例如,大多数应用程序层漏洞可以通过允许列出输入并过滤掉无关字符来解决。SQL 注入和跨站点脚本的根本原因是缺乏输入清理。同样的原则也适用于数据和配置文件以及网络流量的输入。
“OWASP Top 10 项目和类似的公开指南是一个很好的开始。培训应包括:
理想情况下,第一次培训课程是面对面进行的,每年定期更新培训内容,并通过基于计算机的培训模块进行强化。此外,如果在开发过程中发现安全问题,则可据此确定开发人员或团队是否需要进一步的特定培训。例如,如果在开发人员的代码中发现严重漏洞,则可以让他们接受有关该问题及其避免方法的进一步培训。
在 “DevOps 安全冠军帮助组织在无需培训所有人的情况下获得优势”中, 我们建议采用安全冠军模式,将有限的信息安全团队资源投入到开发组织中。「安全冠军」为组织提供可以充当现场顾问和专家的个人,他们可以在开发过程的早期预测潜在的设计或实施问题。
安全倡导者可以通过在团队代码中提供即时的真实示例并专注于立即补救而不是更抽象、不太相关的问题来降低安全编码的感知复杂性。例如,对于业务风险低到中等的新应用程序,安全倡导者可以成为有关安全要求收集和威胁建模问题的第一联系人。我们建议使用简单的安全要求收集和威胁建模工具,以尽可能方便开发人员使用。目标应该是尽可能实现自助服务。对于风险最高的应用程序,我们建议通过联络人直接与信息安全团队接触,以进行全面的威胁建模和安全要求收集。
image.png
施基础设施即代码要求源代码控制也适用于基础设施代码工件。这包括对所有软件定义项目(如配置脚本和可执行文件)的版本控制。这些控制可确保使用正确版本的脚本,平台控制和配置脚本不应包含机密(如凭证、密钥或其他漏洞)。可能需要使用专门设计用于扫描此类机密的工具
将自动化代码、脚本和其他此类基础设施和平台工件视为具有特定额外风险的宝贵源代码。因此,使用源代码类型的控制,包括审计、保护、数字签名、变更控制和版本控制来保护所有此类基础设施和平台工件。
容器和容器管理系统必须保留其变更控制记录,并使用其日志记录功能来提供可审计的保证,确保已知漏洞已被排除。简而言之,不应有无记录的变更。此外,DevOps 经常使用的受云启发的编程基础架构来部署应用程序和服务也应该不断评估其配置是否正确且合规。
在整个生命周期内使用良好的源代码版本控制。这应该得到适当工具的支持,例如分布式版本控制系统 (DVCS) 和应用程序生命周期管理 (ALM) 工具。
在高速环境中,捕获变更的每个细节非常重要。这应包括代码的来源、变更的内容、变更的时间和变更者,以及可能已授予的任何授权(例如,由产品可能受变更影响的其他产品经理授予的授权)。在大多数情况下,这不是一个明确的权限模型,但适用“信任但要核实”的理念,因为有办法确定谁调用了此 API 或谁使用了此代码。能够区分使用了哪些代码(与实际在生产中使用哪些代码)至关重要。通过删除未使用的组件,它成为一种在未来迭代中强化应用程序的方法,或者降低这些组件(如果后来发现这些组件存在漏洞但实际上并未使用)的风险。
image.png
当代码从预生产阶段转移到生产阶段时,检测代码数字签名并确保最终版本是上次扫描的版本。不要在运行时实例化代码,除非确认自批准从预生产阶段/存储库中退出以来它没有被篡改过。平台运营团队将使用传统的变更控制技术(包括 ITIL 方法)来为产品团队提供底层基础设施和平台。
机密信息(通常是敏感凭证或加密密钥)在 DevSecOps 环境中变得越来越危险,尽管这一挑战并不是什么新鲜事。开发人员总是在脚本和程序中对密码和其他类型的凭证进行硬编码。更开明的组织可能会将凭证移至配置文件或元数据服务中——这在一定程度上有所帮助,但通常仍将凭证以明文形式放在恶意用户容易访问的位置。至少在那些情况下,暴露通常仅限于数据中心环境,因此主要攻击媒介是内部恶意人员。 DevOps 和公共存储库已将此问题提升到关键级别。例如,将敏感凭据意外提交到公共存储库(例如安全 Shell (SSH) 和允许访问单个服务器和整个云服务帐户的 API 密钥)的情况很普遍。根据 已发表的研究,数十万个此类密钥存储在 GitHub 等系统的存储库中,并且每天还会增加数千个。
image.png
机密管理提供了一种管理这些风险的方法。一般来说,凭证存储并加密在包含保险库的机密服务器中。资源(应用程序、CI/CD 组件等)从服务器请求所需的凭证,在经过某种形式的身份验证或验证后,在运行时将其提供给请求者。各种开源和商业工具都支持该过程。实施细节差异很大,取决于组织的需求和优先级。
采用机密管理系统会产生额外的成本和摩擦,因此请先从最关键的应用程序开始。与讨论的其他安全控制一样,实施应尽可能无缝且对开发人员透明,方法是直接集成到 CI/CD 管道中并自动执行重复任务(例如凭证和密钥轮换)。
“不可变基础设施思维(Immutable Infrastructure)是一个由Chad Fowler在2013年提出的构想。这种思维强调基础设施中的每一层(从虚拟机、云主机到集群、节点管理和单个节点的安装软件配置)的每个组件都可以自动安装和部署,并且在完成后将保持不变。每个组件一旦部署完成,就不会再进行修改;如果需要更改,则会丢弃旧的组件并部署一个新的组件。这种思想与不可变对象的概念类似,即部署后的组件或环境处于只读状态,不允许直接修改。
对于经常更新的现代微服务应用程序,有一种操作上更安全的方式来维护这些应用程序。在可能的情况下,不应允许任何人直接在生产系统上进行更改。基础设施被认为是“不可变的”。当需要更新时(包括安全补丁和配置更改),应在开发中进行更新(图 左侧),并通过自动化工具进行部署。
生成生产映像的库、组件和操作系统映像保存在安全的存储库中。如果需要修补文件,请在那里进行修补,而不是在生产系统上进行修补。然后,可以使用现有的 DevOps 流程部署新修补的应用程序。这具有多种安全和运营优势。大多数安全和运营事件的根本原因是某种类型的配置错误、管理不善或缺少补丁。
image.png
从运营和安全角度来看,许多现代容器和工作负载编排系统都包括自动健康监测和偏离预期状态的警报。如果工作负载表现异常或偏差太大,则可以将其从活动资源池中移除,并用从已知良好状态启动的工作负载替换。有了适当的应用程序架构,组成服务的各个工作负载都是短暂的,可以来来去去,而服务交付对最终用户来说是一致且不间断的。
此外,从安全角度来看,这种思维方式可以得到进一步发展,它可以通过主动“终止”工作负载并将其替换为已知良好状态的版本(即使它们看起来“健康”)来从根本上提高安全性。假设一个聪明的黑客可能会以某种方式在无法通过正常机制检测到的系统上站稳脚跟。通过定期随机终止工作负载,攻击者的立足点就会丢失,无法持续存在。
让 DevSecOps 产品所有者负责所有服务监控。DevSecOps 团队应为其服务/产品执行一线监控,涵盖运营和安全监控。
本着 DevOps 的精神,“you code it, you own it
”,编写服务的产品团队应该拥有服务的运行时操作。有了 DevSecOps,这一理念应该扩展到安全监控和事件响应。如果对业务有影响,无论根本原因是什么,都应反映在产品/服务仪表板(以及业务影响指标)中。
授权 DevSecOps 团队制定响应策略。如果 DevSecOps 团队负责事件监控,那么他们应该负责制定响应策略,以使组织能够在业务中断(例如,更改服务、补丁、WAF 规则或阻止规则)后在可接受的时间内恢复到可接受的性能水平。产品所有者应有权进行安全执行和政策变更,这些变更应遵守信息安全设定的指导方针和产品所有者的风险承受能力。企业安全运营中心 (SOC) 仍然有作用,但作用可能会减弱。
要让 DevSecOps 产品所有者成为第一线,需要融合安全和运营监控工具。在应用层,无需使用两个单独的工具(一个用于安全,一个用于运营)对服务进行详细监控。至少,数据将在团队之间共享,但理想情况下,应用程序性能监控和安全监控将合并为支持单个 DevSecOps 团队的应用程序和性能。
image.png
尽管大多数 DevOps 基础设施工具至少提供了基本的基于角色的访问控制 (RBAC)(应将其作为最低限度的基线控制),但快速变化的 DevOps 环境和功能边界的模糊可能会对静态访问控制造成挑战。因此,请考虑使用动态访问配置,例如针对开发人员的零信任网络访问 (ZTNA) 控制。
ZTNA 也称为软件定义边界 (SDP),它在应用程序或应用程序集周围创建基于身份和上下文的逻辑访问边界。这些应用程序隐藏起来,无法被发现,并且通过信任代理将访问限制为一组命名实体。代理在允许访问之前验证指定参与者的身份、上下文和策略遵守情况。这将应用程序资产从公共可见性中移除,并大大减少了攻击面。
image.png
这种方法为开发环境提供了自适应访问控制,开发人员可以根据所扮演的角色、工作量以及开发过程中需要访问的点获得不同程度的访问权限。这种方法也可以应用于部署到生产中的开发工作负载。 结果是环境更具弹性,灵活性更高,监控效果更好。通过提供更精细的资源访问控制,该方法可以减少应用程序的攻击面。
综上所述,负责确保应用程序和数据安全的安全和风险管理应该:
you code it, you own it
”理念扩展到安全漏洞。