Azure-DevSecOps-全-

Azure DevSecOps(全)

原文:annas-archive.org/md5/ea7f6186a0b7eef4c68212a992d5ed68

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

安全性是企业的一个重要问题。 60%的组织报告称,由于开发过程的速度、自动化和去中心化增加,他们的 DevOps 计划面临安全挑战。 我们写这本书的目标是帮助你(读者)清晰理解如何在采纳 Azure 云及其服务和 DevOps 工具链的组织中,将持续安全融入 DevOps 工作流的每个阶段。

本书通过动手实验,带你从基础知识深入了解如何在 DevOps 工作流中尽早集成安全。 通过本书的学习,您将全面掌握如何加固整个 DevOps 工作流,从软件规划到编码,再到源代码控制、持续集成,直到运行 Azure 云工作负载。

本书适合谁阅读

本书专为过渡到公共云环境或迈向 DevSecOps 范式的开发人员和安全专业人员量身定制。 它同样适合 DevOps 工程师,或任何希望以实际方式掌握 DevSecOps 实施的读者。 此外,寻求了解如何将安全检查、测试和其他控制措施整合到 Azure 云持续交付管道中的读者,将会发现本书非常有价值。 对 DevOps 原则和实践的先前知识以及对安全基础知识的理解 将有助于阅读本书。

本书内容概览

第一章, 敏捷、DevOps 与 Azure 概述, 将介绍我们将在本书中使用的 DevOps 工作定义。 我们将讨论 DevOps 工作流中的各个阶段和五项核心 DevOps 实施实践。 我们还将解释敏捷、DevOps 和云之间的关系;实施 DevOps 的安全挑战;以及组织如何开始应对 这些挑战。

第二章, DevOps 工作流的安全挑战, 将探讨实施 DevOps 实践所带来的独特安全风险和威胁。 我们将研究组织如何有效地开始解决这些 挑战。

第三章在 DevOps 计划阶段实施安全性 *,讨论了 DevOps 的 PLAN 阶段如何专注于从关键利益相关者和客户收集需求和反馈,制定一个不断演变的产品路线图,优先考虑关键需求,并设计灵活的软件架构。 在此阶段实施 DevSecOps 时,应重点关注在开发人员开始编写代码之前可以解决的安全挑战! 此阶段的活动应包括实施敏捷威胁建模流程,以便更早地识别设计层级的安全问题;并为团队实施安全培训。 在本章中,我们将讨论在实施持续威胁建模过程中有效的方法。 我们还将讨论安全的代码到云的不同成熟度水平 培训项目。

第四章实施提交前安全控制,将专注于可以在开发人员将代码更改提交到版本控制系统之前实施的安全措施和检查。 这包括实施安全控制措施以降低开发环境风险,并建立安全保障措施,以便在代码提交到本地 代码库之前识别并修复漏洞和常见错误。

第五章实施源代码控制安全性,探讨了 DevOps 中的源代码控制是如何通过使用 源代码控制管理(SCM) 系统(如 Git 或 团队基础版本控制(TFVC))来组织和跟踪项目代码的。 在源代码控制中实施 DevSecOps 时,考虑代码库的管理和安全性至关重要。 如果代码库的访问权限被破坏或保护措施容易被绕过,那么很难信任存储在其中的代码。 为了确保代码库的安全,我们应该实施代码签名过程,以验证代码更改的真实性。 我们还应保护敏感分支并实施 安全控制措施。

第六章在 DevOps 的 构建 阶段实现安全性,将重点理解 DevOps 的持续构建阶段,确保 CI 环境和过程的安全,加固构建过程以增强安全性,并将 SAST、SCA 和密钥扫描集成到 构建过程中。

第七章在 DevOps 的 测试 发布 阶段实现安全性,将重点确保发布的构件来自受保护的分支,实施代码审查过程,选择安全的构件源,并验证构件的完整性。 此外,我们还将讨论在发布阶段如何安全地管理密钥,实现基础设施即代码(Infrastructure-as-Code)的安全扫描,并通过发布门控验证和强制执行运行时安全性。

第八章在 Azure 上的持续安全监控,将重点理解 DevOps 中的持续监控,实施 Azure 中的运行时护栏,以及在运行时防止、检测和修复应用程序风险。 在运行时。

为了充分利用本书内容

对 Azure 云的基本理解是充分理解本书内容的前提。要跟随实际操作练习,您需要 以下内容:

  • 一台有互联网连接的 PC

  • 一个有效的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

下载示例代码文件

您可以从 GitHub 下载本书的示例代码文件,网址为 https://github.com/PacktPublishing/DevSecOps-for-Azure。如果代码有更新,将会在 GitHub 仓库中进行更新。

我们还提供了来自丰富书籍和视频目录的其他代码包,您可以在以下网址查看: https://github.com/PacktPublishing/。快去看看吧!

使用的约定

本书中使用了多种文本约定。

文本中的代码:表示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟网址、用户输入和 Twitter 用户名。 这是一个例子: DevSecOps-Book-RG | 确定

代码块设置如下: 如下所示:

 apiVersion: v1
kind: Pod
metadata:
  name: non-root-pod
spec:
  containers:
  - name: mycontainer
    image: myimage
    securityContext:
      runAsUser: 1000
      runAsGroup: 3000

任何命令行输入或输出如下所示: 如下:

 pip install pre-commit

粗体:表示新术语、重要单词或屏幕上显示的词汇。 例如,菜单或对话框中的文字以 粗体显示。这里是一个例子:“点击 登录。””

提示或重要说明

显示如下。

联系我们

我们欢迎读者的反馈 。

一般反馈:如果你对本书的任何部分有疑问,请通过电子邮件联系我们 customercare@packtpub.com 并在邮件主题中提及书名。 你的信息。

勘误:虽然我们已经尽力确保内容的准确性,但错误确实会发生。 如果你在本书中发现了错误,我们非常感激你报告给我们。 请访问 www.packtpub.com/support/errata 并填写 表单。

盗版:如果你在互联网上发现任何我们作品的非法副本,我们将非常感激你提供该副本的网址或网站名称。 请通过 copyright@packt.com 与我们联系并提供 该材料的链接。

如果你有兴趣成为作者:如果你在某个话题上有专长并且有兴趣撰写或贡献一本书,请 访问 authors.packtpub.com

分享你的想法

阅读完 Azure 的 DevSecOps后,我们非常希望听到你的想法! 请 点击这里直接访问亚马逊书籍评价页面 并分享 你的反馈。

您的评价对我们以及技术社区至关重要,将帮助我们确保提供卓越的 优质内容。

下载此书的免费 PDF 副本

感谢购买 本书!

您是否喜欢随时随地阅读,但无法携带您的纸质书籍到处走动?

您的电子书购买是否无法与您选择的设备兼容?

别担心,现在购买每本 Packt 书籍时,您将免费获得该书的无 DRM PDF 版本 ,无需额外费用。

随时随地,在任何设备上阅读。 直接从您最喜欢的技术书籍中搜索、复制并粘贴代码到 您的应用程序。

福利不止于此,您还可以获得独家折扣、新闻简报,以及每天通过电子邮件发送的精彩免费内容。

按照以下简单步骤即可享受 这些福利:

  1. 扫描二维码或访问以下 链接

https://packt.link/free-ebook/9781837631117

  1. 提交您的购买凭证 以证明购买

  2. 就是这样! 我们将直接将您的免费 PDF 和其他福利发送到您的 电子邮件

第一部分:了解 DevOps 和 DevSecOps

在这一部分,我们将讨论 DevOps 工作流的各个阶段、实施 DevOps 的安全挑战,以及组织如何开始解决 这些挑战。

本部分包含以下章节: 以下章节:

  • 第一章, 敏捷、DevOps 和 Azure 概述

  • 第二章, DevOps 工作流的安全挑战

第一章:敏捷、DevOps 与 Azure 概览

DevOps 是一种现代的应用程序开发和交付方法,帮助组织将高质量的软件更快速地发布到生产环境中,并减少缺陷! 然而,采用 DevOps 方法的好处并非单独实现。 它们最好与其他概念结合使用,如敏捷规划和 云计算。

本书的大部分内容集中在 DevSecOps,但在本章中,我们将为那些不熟悉这一概念的读者介绍 DevOps。 我们将介绍 DevOps 的工作定义,并将在本书的其余部分中使用该定义。 我们将讨论 DevOps 工作流中的阶段和五个核心的 DevOps 实施实践。 我们还将解释敏捷、DevOps 和云计算之间的关系,实施 DevOps 的安全挑战,以及组织如何开始解决这些挑战。

在本章结束时,你将对以下内容有清晰的理解: 以下内容:

  • 什么是 DevOps

  • DevOps 的五个核心实践 核心实践

  • DevOps 工作流中的阶段 DevOps 工作流

  • DevOps 中协作文化的重要性 在 DevOps 中的协作文化

  • 需要注意的 DevOps 反模式 反模式

  • DevOps 工具链(Azure DevOps, GitHub Actions, 和 GitLab)

  • DevOps 的缘由 DevOps 的必要性

  • 敏捷、DevOps 和 云计算之间的关系

这些主题将为你提供理解和 contextualize 本书其余部分讨论的必要基础知识。 现在,让我们开始吧,开启我们的旅程!

技术要求

要跟随本章的指引,你需要 以下内容:

  • 一台具备 互联网连接的 PC

  • 有效的 电子邮件地址

定义 DevOps——理解其概念和实践

如果你问 10 个人 DevOps 是什么,你可能会得到 10 个不同的答案,这取决于这些人的背景以及他们阅读的书籍。 因此,我们必须为本书接下来的内容建立一个工作定义,以此定义 DevOps。 微软对 DevOps 的官方定义由 Donavan Brown 于 2018 年在一个会议上提出。 你仍然可以在 YouTube 上找到该视频: https://www.youtube.com/watch?v=cbFzojQOjyA。以下是 该定义:

DevOps 是人员、过程和产品的结合,以实现持续向最终用户交付价值。

从这个定义中,我们想强调几个关键点。 首先,必须理解 DevOps 不是 一个工具 、一个产品,或者一个职位名称。 相反,它是一种协作式的软件开发方法。 它是一种工作/思维方式,最重要的是,它是文化的变革(稍后我们会详细讨论)。 另一个关键点是,DevOps 的主要目标是确保功能性软件能够快速且频繁地交付给最终用户。 如果实施的结果没有达到这一目标,那么它很可能就不是 DevOps,或者它并没有得到恰当的实施(我们将在本章的 远离 DevOps 反模式 部分详细讨论这一点)。 最后,我们想强调的是,DevOps 有三个方面。 它有一个 人员 方面,一个 过程 方面,和一个 产品 方面。 在接下来的部分中,我们将首先讨论过程方面,但在此之前,让我们讨论一下为什么组织正在快速转向 DevOps 方法来进行软件开发 和交付。

DevOps 的“为什么”——创新、速度和效率

虽然我们已经 花费了 大量时间讨论 DevOps 的 过程、人员和产品方面,但同样重要的是要理解推动公司采用 DevOps 的因素,以及近年来它日益重要的原因。 DevOps 为公司提供了其他软件交付方法无法比拟的独特优势。 以下是一些与 采用 DevOps 相关的好处:

  • 加速市场推出时间:这指的是将新产品更快推向市场的能力。 根据 Puppet 进行的研究,采纳 DevOps 文化和实践的公司在代码部署频率上比未采用的公司高出 46 倍。

  • 适应市场和竞争:这意味着能够适应市场和竞争的变化。 例如,Etsy 是一个在线手工艺品和复古商品市场,采用 DevOps 实践,每天部署 50 次代码变更。 这使公司能够迅速测试和发布新功能,回应用户反馈,并保持领先于 竞争对手。

  • 维护系统的稳定性和可靠性:DevOps 实践可以通过改善开发和运维团队之间的沟通与合作,帮助组织保持系统的稳定性和可靠性。 例如,Netflix 采用 DevOps 方法,确保其流媒体服务始终保持可用和响应迅速。 该公司通过自动化基础设施部署并使用“混沌猴子”工具故意在系统中引入故障,从而在问题发生之前识别并解决系统中的弱点。 这有助于防止问题的出现。

  • 提高平均恢复时间:通过采纳 DevOps 实践,组织可以提高从事件和故障中恢复的效率。 例如,美国领先零售公司 Target 在实施 DevOps 实践后,将其 整体 平均恢复时间(MTTR) 缩短了 90%。 这使得公司能够将停机的影响降到最低,并保持高水平的 客户满意度。

在基础知识 得到覆盖后,接下来我们深入探讨 DevOps 中用于创建 工作流的过程。

理解 DevOps 过程方面

每当讨论 DevOps 时, 人们往往会把技术或工具作为焦点。 然而,如果没有明确定义的流程,采用 DevOps 所带来的任何好处或结果最多也只是有限的,甚至可能带来额外的挑战 和复杂性!

在 DevOps 方法论中,过程方面指的是创建一个高效、简化的软件开发、测试和部署工作流程。 目标是优化开发过程,确保软件能够快速且可靠地交付给最终用户,同时保持较高的质量水平。 的质量。

这涉及到敏捷开发方法学的使用,以及 持续集成和持续交付(CI/CD) 实践。 这些实践涉及自动化软件开发生命周期的各个方面,如代码测试、构建和部署。 通常,当一个组织采用 DevOps 方法时,必须实施五个基本实践: 敏捷规划版本控制持续集成 (CI), 持续交付 (CD),和 持续监控 (见 图 1**.1):

图 1.1 – DevOps 的五个基本实践

图 1.1 – DevOps 的五个基本实践

值得注意的是,这些并不是 DevOps 中唯一的实践,但它们被认为是至关重要的实践。 在接下来的章节中,我们将更详细地描述这五个核心实践。 更多 细节。

重要说明

对于那些希望探索 与 DevOps 相关的其他定义和模型的人,DevOps 能力模型 由 DevOps 敏捷技能协会 (DASA) (DASA) 是一个有价值的资源。 你可以在这里找到更多相关信息: https://www.dasa.org/products/guidance-products/team-competence-model/

理解 DevOps 的五个核心实践

在本节中,我们将首先从 敏捷规划开始,探讨 DevOps 的五个基本实践。 敏捷规划。

敏捷规划 是广泛 指用于计划和跟踪我们在 DevOps 中软件项目的技术。 它是一种项目管理方法,涉及将一个项目分解为小的、可管理的部分,并以迭代方式进行工作。 敏捷方法论于 2001 年通过《敏捷宣言》正式发布,涵盖了敏捷项目管理的主要原则。 要获取更多关于《敏捷宣言》的信息,您可以访问 以下链接 https://agilemanifesto.org/

目标是逐步和持续地交付一个可用的产品,同时获取 利益相关者的反馈。

一个简单的敏捷规划示例可以在移动应用开发中看到。 假设某公司希望开发一个可以从本地餐馆订餐的移动应用。 开发团队首先会确定应用应该具备的关键功能,例如菜单、订餐系统、支付系统和用户资料。 掌握这些需求后,他们会设计应用的架构。 接下来,团队会将这些功能分解为更小、更可管理的任务,例如设计用户界面、创建存储订单的数据库和集成支付系统。 然后,团队会根据任务所带来的业务价值和完成这些任务所需的努力程度,优先处理这些任务。 任务优先级确定后,团队会估算完成每个任务所需的时间,并制定冲刺计划。 冲刺是一个短期的、有时间限制的工作周期(通常为 1-2 周),在此期间团队会集中处理一组 任务。

在每个冲刺期间,团队会按优先级顺序处理任务,完成任务,并从利益相关者那里获得反馈。 然后,反馈将用于调整 产品和下一次冲刺的计划。 这种将任务分解、优先排序、时间估算并在反馈中迭代工作的过程是 敏捷规划的核心。

重要提示

要了解敏捷开发的指导价值观,我们建议查看以下链接中突出的敏捷开发的十二条原则: https://www.agilealliance.org/agile101/12-principles-behind-the-agile-manifesto/

第二个实践, 版本控制,允许开发人员高效地管理代码更改,进行有效的协作,并跟踪对代码所做的所有更改。 图 1**.2 展示了版本控制在 DevOps 中如何工作的一个简单示例。 假设一组开发人员正在开发一个软件应用程序。 他们使用 一个 版本控制系统 (VCS),例如 Git,创建了一个仓库(存储代码的中央位置)。 每个开发人员可以将仓库克隆到他们的本地计算机,或者他们也可以直接在一个受控的开发环境中工作,从而避免将代码复制到本地 PC。 值得注意的是,一些公司对这种工作流程有严格的政策,不允许代码 在本地克隆。

图 1.2 – 版本控制和分支示例

图 1.2 – 版本控制和分支示例

假设开发人员 A 被分配来处理功能 A;他们在仓库中创建了一个新的分支,名为 功能 A 并开始对代码进行更改。 与此同时,开发人员 B 正在开发应用程序中的另一个功能。 他们创建了一个名为 功能 B 的新分支,并开始对代码进行更改。 两个开发人员可以独立工作,彼此的工作不会互相影响。 一旦他们完成了各自的更改,他们可以将分支合并回主分支(也叫做 主干 分支)中, 并提交到仓库。

如果两个开发人员所做的更改之间存在任何冲突, 版本控制系统将突出显示这些冲突,开发人员可以在合并分支之前解决它们。 版本控制系统还会记录对代码所做的所有更改,包括谁做的更改、何时做的更改以及为什么做的更改。 如果新代码出现问题,团队可以使用版本控制系统快速回滚到代码的先前版本。 这种回滚功能在引入 bug 或新更改导致 意外问题时非常有用。

第三 种实践, 持续集成 (CI),指的是开发人员每次提交或修改代码时,持续验证代码质量的过程。 假设一个开发团队正在进行一个软件项目;每当开发人员完成代码更改并将其提交到共享代码库时,CI 服务器(如 Jenkins 或 Travis CI)会触发一个自动过程,构建软件、运行单元测试,并使用各种工具检查代码质量问题。 如果构建和测试都成功通过,CI 服务器将通知团队,表示这些更改已准备好进行审查和集成。 如果发现任何错误或问题,CI 服务器将提醒团队,团队可以共同解决问题,然后再将代码合并到共享代码库中。 这使得团队能够在开发早期发现并修复问题,从而减少最终产品中出现 bug 和错误的风险:

图 1.3 – 示例 CI 流程

图 1.3 – 示例 CI 流程

第四 种实践, 持续交付 (CD),指的是通过自动化过程持续进行已验证软件的测试和部署。 它允许团队快速发布新特性和修复 bug,采用连续的流程进行。 CD 的目标是使开发团队能够快速且有信心地将软件更改交付到生产环境,同时保持高水平的质量 和可靠性。

假设一个开发团队正在开发一个 web 应用程序;当团队为一个新特性编写代码时,代码会被提交到版本控制系统,并通过一系列自动化测试进行测试,包括单元测试、集成测试和验收测试。 一旦代码通过所有测试,它会被自动部署到预发布环境,在那里进行额外的测试和产品负责人审核。 如果一切正常,代码将被自动部署到生产环境,并提供给 所有用户。

第五项实践 是 持续监控 包括收集 来自用户的反馈和实时运行应用程序的遥测数据。 目标是确保软件系统满足用户需求并为组织提供价值。 这需要持续收集软件系统的性能和行为的洞察,并利用这些信息做出基于数据的决策,从而提升整体质量和用户体验。 为了更好地理解这一实践,我们将其分解为 两个组成部分:

  • 收集用户反馈:用户反馈是持续监控的一个重要组成部分,因为它有助于从用户的角度识别软件系统中的问题和改进的空间。 反馈可以通过各种渠道收集,例如调查、用户评论和支持票据。 通过分析这些反馈,开发团队可以识别出反映改进领域的模式和趋势,并根据这些改进对 用户体验的影响优先考虑这些改进。

  • 收集来自运行中的应用程序的遥测数据:遥测数据是指在软件系统实时运行过程中从各种来源收集的广泛信息。 这些来源可以包括应用日志、服务器指标、网络流量、用户互动、错误报告等。 从这些数据中可以得出响应时间、错误率、服务器负载等指标,以及用户行为的洞察。 通过收集和分析遥测数据,开发团队可以全面了解软件的性能和用户互动。 这些数据对在问题升级为 关键问题之前检测异常和潜在问题至关重要。

通过结合用户反馈和遥测数据,开发团队可以全面了解软件系统的表现以及用户如何使用它。 然后,这些信息可以用来做出基于数据的决策,改进系统 并优先考虑未来的开发工作。 总体而言,持续监控的第五项实践是 DevOps 中至关重要的一部分,帮助确保软件系统满足用户需求,并为 组织提供价值。

理解 DevOps 工作流中的各个阶段

理解 DevOps 的五项基本实践至关重要,但组织如何将它们付诸实践呢? DevOps 实践的实施涉及一系列阶段,这些阶段有助于软件的持续开发、测试和部署。 这些阶段可能会根据组织和开发的软件类型有所不同,但它们通常遵循如 图 1**.4所示的模式:

图 1.4 – DevOps 工作流中的典型阶段

图 1.4 – DevOps 工作流中的典型阶段

第一阶段是 计划,在此阶段,敏捷规划实践开始付诸实施。 在这个阶段,团队根据业务或客户需求计划并优先排序需要完成的任务。 这涉及到创建项目计划或路线图,进行调研以了解所需的架构变更,定义工作范围(如功能开发或修复 bug),将计划分解为更小且可分配的任务,估算每个任务所需的时间,并为需要 优先完成的任务设定优先级。

第二阶段是 编码,这涉及到使用 选定的编程语言、框架和工具进行实际编码和软件开发。 在这一阶段,会实施版本控制实践。 团队协作开发代码并提交更改到版本 控制系统。

第三阶段是 构建测试,在这一阶段,会实施持续集成实践。 在这一阶段,代码被转换为可执行的软件并经过测试,以确保其按预期工作并满足项目要求。 结合使用自动化和手动测试来发现并解决任何错误、bug 或缺陷。

第四阶段是 发布部署,在此阶段,软件被打包并发布到生产环境中。 在这一阶段,会实施持续交付实践。 这一阶段包括设置运行软件所需的基础设施并进行配置,使其能够正常工作,将软件部署到预生产环境中以进行额外的验证,并将经过验证的软件 部署到生产环境。

第五个阶段是 操作监控,在这个阶段,软件会被主动监控和维护。 团队会在部署后监控任何问题或事件,检查应用程序的性能,收集并分析日志,并确保软件符合 已定义的 服务水平协议 (SLA)。 在这一阶段,使用持续监控工具和实践来跟踪应用程序的性能,收集使用遥测和性能指标,并在问题影响用户之前检测潜在问题。 收集到的信息随后用于识别优化的领域或要添加的附加功能。 一种 自愈 方法 在这一阶段越来越受到欢迎。 这种方法涉及利用自动化来修正任何故障或错误,无需人工干预,例如终止一个有问题的应用实例并部署替代实例,或在发生意外事件时触发故障转移到备用实例。 实施这种方法显著提高了系统的可用性和可靠性,并能更快速、更高效地从故障中恢复。 故障恢复。

这些阶段形成了一个持续的循环,使团队能够持续向最终用户交付价值,同时提升软件开发流程。 请记住,速度 对成功的 DevOps 工作流至关重要! 每个阶段都必须快速高效地执行(我们将在谈到 安全集成时重新讨论这一点)。

理解 DevOps 中的人文因素

单纯在持续工作流中实施 DevOps 实践不足以充分释放其潜力;还需要一个文化方面的因素。 在促进沟通、协作和开发与运维团队成员之间共享责任的文化中,实施 DevOps 方法可以取得更好的结果。 然而,对于许多组织(尤其是大型组织),这是拥抱 DevOps 时最困难的方面,因为它涉及到心态和公司文化的变化,这可能会挑战已经取得良好效果的既定政策和流程。 到目前为止。

协作文化的重要性

要实现 DevOps 的全部 潜力,组织必须拥抱协作文化! 我们所说的文化是打破团队孤岛,使开发人员、运维工程师和其他利益相关者能够共同合作,达成持续向客户交付高质量软件的共同目标。 这可以通过创建跨职能团队或 垂直团队来实现。

传统上,大型组织会根据特定的技能集或职能领域,如开发、测试或运维,采用横向结构来组织团队(如 图 1**.5所示)。 每个团队专注于自己的专业领域,仅处理该领域内的任务。 这些团队被一个边界隔开(如 图 1**.6 所示),并使用不同的绩效指标来评估,这通常会导致冲突。

图 1.5 – 软件开发中的团队边界

图 1.5 – 软件开发中的团队边界

另一方面,DevOps 提倡并在围绕特定产品或服务垂直组织的团队中蓬勃发展,这也被称为跨职能团队。 这种结构将来自不同职能领域的人员聚集在一起,共同合作,目标是交付特定的产品或服务。 每个团队成员具备广泛的技能,并负责为交付该产品或服务作出贡献。 这些团队还通过一套共享的绩效指标进行评估,这鼓励团队成员利用彼此的技能和专业知识来实现共同目标。 例如,一个垂直团队可能由开发人员、测试人员和运维工程师组成,共同合作,交付特定的应用程序或服务,如下图所示:

图 1.6 – 垂直团队边界

图 1.6 – 垂直团队边界

需要特别注意的是,尽管团队的组成至关重要,但一个引导人物的存在,通常是一个仆人式领导者,同样重要。 团队需要清晰的方向和领导力,才能高效运作。 这位领导者确保团队始终与目标保持一致,促进协作,并提供解决挑战所需的支持。 应对挑战。

DevOps 还有其他文化组成部分,例如培养持续 学习和实验、责任心和问责制的文化。 然而,我们建议阅读 《凤凰项目》 由基恩·金(Gene Kim)所著,以便更详细地了解 这些组成部分。

避免 DevOps 反类型

在实施 DevOps 文化时,重要的是要意识到潜在的反模式和反类型。 这些是低效的,有时甚至适得其反的方法,可能会阻碍 DevOps 的成功实施。 的实施。

例如,在实施 DevOps 时,一位经理或高管可能会创建一个单独的 DevOps 团队,这可能进一步分割开发和运维团队(图 1**.7)。 这种分离只有在团队是临时性的,且有明确的任务将团队 紧密结合起来时,才有意义:

图 1.7 – 反模式 1

图 1.7 – 反模式 1

另一个常见的反类型是当开发人员或开发经理认为他们可以不依赖操作技能和活动时(图 1**.8)。 这种误解通常源于对云计算的错误理解,认为云计算的自助服务特性使得操作技能变得过时。 然而,这种观点极大 低估了操作技能的复杂性和重要性,导致可避免的 操作失误:

图 1.8 – 反模式 2

图 1.8 – 反模式 2

另一个反模式是组织仅仅将他们的运维团队重新命名为 DevOps 或 站点可靠性工程 (SRE) 团队,而没有对他们的 流程或孤岛做出任何实际改变(参见 图 1**.9)。 这种方法没有理解或认识到将不同领域的人员汇聚在一起,协同工作以实现 共同目标的重要性:

图 1.9 – 反模式 3

图 1.9 – 反模式 3

SRE 是一种将软件工程的理念融入基础设施和运维问题的学科。 SRE 团队的主要目标是创建可扩展且高度可靠的软件系统。 虽然 SRE 与 DevOps 理念高度契合,但仅仅将运维团队更名为 SRE 而没有采纳其原则或实践,可以视为一种反模式。 这不仅仅是一个名称问题,而是要拥抱 DevOps 和 SRE 都提倡的 方法论、实践和文化。

重要提示

有关 DevOps 反模式的更详细分析,请参阅 Matthew Skelton 和 Manuel Pais 的著作 《团队拓扑学》

了解 DevOps 的产品层面——工具链

尽管 DevOps 本身不是 一个工具或产品,但它需要使用工具来有效实施其流程和实践。 可以使用开源和商业工具来支持本章前面讨论的 DevOps 工作流每个阶段所需的流程(计划、编码、构建与测试、发布与部署、以及运维 和监控)。

常用的工具 包括 计划阶段 常用的工具有 TrelloJIRANotionAsana。根据最新的 Stack Overflow 开发者调查,专业开发者更倾向于使用 JIRA(49%),而 Trello 则主要被学习编程的人使用(43%):

图 1.10 – 计划阶段常用工具

图 1.10 – 计划阶段常用工具

代码与开发阶段 , 开发人员使用 集成开发环境 (IDE),例如 Visual Studio CodeVisual StudioIntelliJNotepad++Eclipse,用于 编写代码 和 版本控制工具,例如 Git (自托管或云托管), Apache Subversion (SVN), PerforceMercurial。需要注意的是 ,虽然这个列表突出显示了 一些常见工具,但它并非详尽无遗。 市场上还有无数其他工具,每个工具都有其独特的功能和能力。 根据 2022 年 Stack Overflow 开发者调查,专业开发者压倒性地偏爱 Git 作为他们的版本控制 工具(96%)和 Visual Studio Code 作为他们的 IDE(74%):

图 1.11 – 常见的代码和开发工具

图 1.11 – 常见的代码和开发工具

重要提示

Stack Overflow 开发者调查是由 Stack Overflow 进行的一项年度调查,Stack Overflow 是一个受欢迎的在线开发者社区。 该调查旨在收集开发者社区的偏好、意见和人口统计信息。 2022 年的调查结果可以在 这里找到: https://survey.stackoverflow.co/2022

构建与测试阶段,如 Jenkins (一个开源自动化服务器), Travis CICircle CI 广泛用于持续集成以及构建和测试自动化。 根据 Digital.ai 的最新调查,Jenkins 被 56%的 DevOps 团队使用,显示出它在行业中的受欢迎程度。 此外,测试工具如 SeleniumJunit (一个 Java 单元测试工具), Nunit (一个.NET 单元测试工具), PHPUnit (一个 PHP 单元测试工具),以及 Jmeter (一个性能测试负载测试工具)可以与构建自动化服务器集成,以便于测试过程。 容器构建工具如 Docker Build (一个从 Dockerfile 构建容器镜像的工具), Podman Build (一个使用 Containerfiles 和 Dockerfiles 构建和管理容器的工具), Buildah (一个开源工具,用于创建和修改容器镜像),以及 Kaniko (一个为 Kubernetes 集群设计的安全容器构建工具)也可以集成进来,以简化容器 镜像构建。

图 1.12 – 构建与测试阶段常用的工具

图 1.12 – 构建与测试阶段常用的工具

发布与部署阶段,开发者使用各种工具 来自动化部署。 下表展示了一些在发布和 部署阶段使用的工具:

部署
GoCD
Octopus Deploy
TeamCity
Spinnaker
ArgoCD
基础设施 即代码
Terraform
Azure ARM 模板
Azure BICEP 模板
AWS Cloud Formation 模板
容器部署
Helm charts
Kubernetes 清单文件
配置 管理工具
Ansible
Chef
Puppet
PowerShell Desired State Configuration (DSC)

表 1.1 – 发布和部署阶段使用的工具

运营和监控阶段,可以使用多个工具。 其中一些在 下表中突出显示:

OpenTelemetry 一个开源的可观测性框架,用于生成和收集来自应用 和基础设施的遥测数据
Jaeger 一个开源的分布式追踪系统,用于监控和排查 基于微服务的应用
Zipkin 一个开源的分布式追踪系统,用于收集、分析和可视化跨 微服务架构的请求追踪
Prometheus 一个开源监控系统和时间序列数据库,用于收集和查询应用程序 及基础设施的指标

表 1.2 – 在操作和监控阶段使用的工具

类似 Prometheus 的工具可以用于对应用程序代码进行仪表化,并生成诸如指标、日志和追踪等遥测数据。 Prometheus、 GrafanaELK 堆栈 (Elasticsearch、Logstash 或 Kibana)可以用于监控应用程序和基础设施的性能 和 可用性,提供潜在问题的洞察并实现 主动修复。

协作和通信工具 如 SlackMicrosoft TeamsAzure BoardsAtlassian Confluence 可用于促进 团队间的沟通 和协作,帮助简化工作流程并 提高生产力。

开发人员可以访问各种工具,涵盖每个阶段,超出了我们已提及的工具范围。 为了理解可用的丰富工具选项,我们建议参考由 Cloud Native Computing Foundation (CNCF) 提供的云原生生态图,网址为 https://landscape.cncf.io/。该图(图 1**.13)旨在帮助人们浏览云原生领域中的各种工具、技术和平台。 该图展示了多个类别的工具,包括应用开发、持续集成和交付、自动化、 以及配置管理。

图 1.13 – CNCF 生态图的截图

图 1.13 – CNCF 生态图的截图

随着团队采纳 DevOps 实践,通常会根据偏好选择多个工具,而非考虑与组织 DevOps 战略的整体兼容性(不幸的是,许多组织并没有明确的 DevOps 战略)。 因此,碎片化的工具链可能是常见的现象,不同的团队和产品单元使用不同的工具,这些工具可能无法很好地集成或协同工作,从而阻碍了软件交付的扩展能力,并带来了治理挑战。 使用多个工具时,很难建立并强制执行与访问控制和数据隐私相关的治理和合规政策。 为了解决这些挑战,平台化工具方法可能是更受欢迎的选择。

平台化 DevOps 工具方法

与其为 DevOps 工作流的每个阶段使用多个不同的工具,一些组织选择了平台战略,提供一个集成平台,配备各个阶段所需的工具。 这种方法可以简化 DevOps 工具的使用场景,使得管理变得更加容易,并减少了不同工具之间手动集成的需求。

根据行业报告和调查,以下是五个最常用且评价很高的商业 DevOps 平台:

  • GitLab: 一体化 DevOps 平台,提供一个用于源代码管理、持续集成、测试 与部署的应用程序。

  • Azure DevOps: 一款微软基于云的平台,提供一整套 DevOps 服务,帮助开发者规划、开发、测试并 部署应用程序。

  • GitHub: 另一款微软基于云的平台,提供一整套 DevOps 服务,帮助开发者规划、开发、测试并 部署应用程序。

  • Atlassian: Atlassian 提供一系列 DevOps 工具,包括用于问题跟踪的 Jira、用于源代码管理的 Bitbucket 和用于持续集成 与部署的 Bamboo。

  • Amazon Web Services (AWSs) DevOps: AWS 提供了一整套用于 DevOps 的工具和服务,包括 AWS CodePipeline、AWS CodeCommit 和 AWS CodeDeploy。

其中两个平台是微软的 产品,将实现 DevOps 流程所需的工具汇聚在一个地方:Azure DevOps 和 GitHub。

Azure DevOps 平台概览

Azure DevOps 是微软的 云平台 ,提供帮助团队实施 DevOps 流程的服务。 要使用它,我们需要创建一个 Azure DevOps 组织(图 1**.14)。 在该组织内,我们可以为不同的软件项目创建独立的项目,如 图 1**.14 所示。在每个项目中,我们可以访问用于实施 DevOps 流程的服务,并且可以组织团队来处理项目的不同部分:

图 1.14 – Azure DevOps 组织结构

图 1.14 – Azure DevOps 组织结构

Azure DevOps 平台有五个核心服务。 这些服务与开发过程中的关键实践相连接,如 计划、控制代码变更和测试。 这五项核心服务是 Azure DevOps 的核心:

  • Azure Boards 用于计划

  • Azure Repos 用于控制 代码变更

  • Azure Pipelines 用于持续集成 和交付

  • Azure Artifacts 用于 包管理

  • Azure Test Plans 用于探索性 测试计划

图 1.15 – Azure DevOps 核心服务

图 1.15 – Azure DevOps 核心服务

让我们简要了解这五项服务,从 Azure Boards 开始:

  • Azure Boards:一个帮助我们规划、跟踪和可视化工作的工具,类似于 JIRA。 它可以与 Scrum 或 Kanban 方法一起使用,并提供四种不同的模板供选择。 它还具有交互式看板和报告工具,帮助我们跟踪 我们的工作。

  • Azure Repos:用于管理代码变更的源代码管理服务。 它支持两种代码管理方式:Git 和 团队基础版本控制TFVC)。 它还与 Azure DevOps 中的其他服务集成 以支持可追溯性。

  • Azure Pipelines:一个帮助我们自动构建、测试和部署代码的工具。 它可用于实现持续集成和持续交付的过程。 它支持多种不同类型的编程语言和平台,包括 Python、Java、PHP、Ruby、C#和 Go。 我们还可以用它将代码部署到各种目标,包括本地服务器或 云服务。

  • Azure Artifacts:一个帮助我们存储、管理和组织软件包的工具。 我们可以选择并控制与谁共享包。 它允许我们从上游源下载包。 它支持多种类型的包,如 NuGet、NPM、Maven、Universal、 和 Python。

  • Azure Test Plans:一个云托管的测试管理解决方案,我们可以用它来计划和跟踪不同类型的测试结果。 我们可以用它来规划和跟踪手动 测试、用户 验收测试、探索性测试,甚至是自动化测试。 我们可以通过任何支持的浏览器访问工具,并通过易于使用的网页门户执行手动测试。 它支持端到端的可追溯性,用于跟踪我们需求和构建的进展与质量,并为我们提供数据和报告,以改进我们的 测试过程。

关于 Azure DevOps 平台的一件好事是,我们不被强迫使用它的所有服务。 我们可以选择要用于软件项目的服务,并关闭那些我们 不需要的服务(图 1**.16)。

图 1.16 – 启用/禁用 Azure DevOps 服务

图 1.16 – 启用/禁用 Azure DevOps 服务

GitHub 平台概述

GitHub 平台 提供多种产品选项,适应不同规模的团队和组织。 这些选项包括 以下内容:

  • GitHub Free:这是一个免费的基础版,适合小型个人项目或开源 项目。

  • GitHub Pro:这是一个付费版本,具有额外功能,如高级保护功能、受保护的分支和代码所有者。 它适合需要更多 高级工具的开发人员。

  • GitHub Team:此版本包含 GitHub Pro 的所有功能,并具有团队管理工具。 适合需要在项目中进行协作的团队。 如果您的组织有 11 名或更少开发者,请考虑使用 GitHub Team。

  • GitHub Enterprise:此版本适用于需要更多高级功能(如 SAML 单点登录 (SSO)、数据驻留合规性和高级安全功能)的大型组织。 它适合需要遵循特定安全和监管要求的大型组织。 通常,拥有 12 名或更多开发者的组织最能从 GitHub Enterprise 中获益。 企业版还提供两种选项:企业服务器,托管在客户管理的基础设施上,以及企业云,托管在云端。

图 1.17 – GitHub 平台产品选项

图 1.17 – GitHub 平台产品选项

在本书的其余部分,我们的重点 将放在 GitHub Enterprise Cloud 产品上。 为了使用 GitHub Enterprise Cloud,我们需要创建一个 GitHub 组织(图 1**.18)。 组织是一个共享的 私有 GitHub 账户,企业成员可以在多个项目中进行协作。 在组织内,我们可以创建 仓库,这些仓库类似于 Azure DevOps 中的项目。 为每个组织正在进行的项目创建单独的仓库是一个好主意。

图 1.18 – GitHub 组织层级结构

图 1.18 – GitHub 组织层级结构

一家公司可以拥有多个 GitHub 组织。 为了简化可见性、管理和计费,建议创建一个企业账户来管理属于贵公司的所有组织(图 1**.19)。 创建企业账户是可选的,但它是免费的,并且不会为 GitHub Enterprise Cloud 客户增加任何额外费用。 即使一家公司只有一个组织,创建企业账户仍然是有益的。 通过企业账户,我们可以管理并强制执行 我们公司所有组织的政策。 我们甚至可以选择希望在企业级别强制执行的政策,同时允许组织所有者在 组织级别配置其他政策。

图 1.19 – GitHub 企业账户

图 1.19 – GitHub 企业账户

GitHub Enterprise Cloud 平台提供了一系列服务,我们可以在代码到云的不同阶段使用这些服务。 这些服务包括 以下内容:

  • Projects 用于规划、组织、协作和跟踪软件 开发项目。

  • Codespaces 用于在基于云的 开发环境中编写代码。

  • Copilot 用于机器学习辅助的 代码编写。

  • Repos 用于管理私有和公共 代码库。

  • Actions 用于自动化构建、测试和部署 代码。

  • Packages 用于共享和发现可重用的 代码包。

  • Security 用于扫描和检测代码库中的安全问题。

下图 展示了 GitHub 服务的布局:

图 1.20 – GitHub 服务

图 1.20 – GitHub 服务

让我们简要了解一下这五项服务,从 GitHub 项目开始:

  • GitHub 项目:我们可以用来规划、组织和跟踪软件项目的工具。 我们可以用它分配任务、与他人协作,并添加额外信息以跟踪进度。 它还具有报告已完成和 未完成工作的能力。

  • Codespaces:提供一个方便的云开发环境,开发者可以在其中运行、测试、调试和推送代码,无需进行本地机器设置。 创建 Codespace 后,开发者将自动获得一个已经配置好的系统,其中包括多个语言的 SDK 和运行时,如 Python、Node、Docker、Java、Rust、Go 和 C++。 默认镜像可以根据个人或团队的需求进行完全定制,从而加快每个仓库的设置时间。

  • GitHub Copilot:由 OpenAI Codex 提供支持的人工智能配对编程工具,Codex 是 OpenAI 开发的机器学习模型(OpenAI 是一家知名的人工智能研究和部署公司)。 Copilot 在开发者编写代码时提供代码建议,适用于他们的 IDE。 它还可以解释自然语言注释,并将其转化为代码。 它支持多种编程语言,因为它在所有公开仓库中出现的语言上进行了训练。 Copilot 可以作为扩展插件在支持的 IDE 中使用,例如 Visual Studio Code、Visual Studio、Neovim 和 JetBrains 系列 IDE。

  • GitHub 仓库:一个源代码管理服务,用于管理代码的变更。 与 Azure DevOps 不同,它 支持 Git,这是一种分布式源代码管理工具。 它还与 GitHub 中的其他服务集成 以实现可追溯性。

  • GitHub Actions:一个帮助我们自动构建、测试和部署代码的工具。 它可以用于实现持续集成和持续交付的过程。 它支持许多不同类型的编程语言和平台,包括 Python、Java、PHP、Ruby、C# 和 Go。 它还可以用于将代码部署到多种目标,包括本地服务器或 云服务。

  • GitHub Packages:一个帮助我们存储、管理和组织软件包的工具。 我们可以选择并控制希望与谁共享这些软件包。 它允许我们从上游源下载软件包。 它支持多种类型的软件包,如 NuGet、NPM、Maven、Universal、 和 Python。

  • GitHub 高级安全:它提供了一系列工具来保护我们仓库中的代码。 它扫描易受攻击的依赖项,并允许我们自动发起拉取请求以修复这些问题。 它还会检测新代码或修改过的代码中的安全漏洞和编码错误。 它还可以识别任何意外提交到仓库中的令牌或凭据。 我们将在本书后续章节中详细讨论这一服务。

让我们快速了解一下 另一个 DevOps 平台:GitLab。

GitLab 平台概述

GitLab 是一个基于 Web 的 Git 仓库管理 工具,提供端到端的 DevOps 解决方案。 与其他 DevOps 平台类似,GitLab 也拥有支持 DevOps 工作流各个阶段的核心服务。 这些服务包括 以下内容:

  • GitLab 问题:它是一个敏捷项目管理工具,帮助团队使用 Scrum 或 Kanban 方法规划和组织工作。 通过 GitLab 看板,团队可以轻松地跟踪进度、可视化工作,并与 团队成员协作。

  • GitLab 代码库:GitLab 主要以其版本控制系统而闻名。 它为团队提供了一个集中平台,帮助他们使用 Git 存储、管理和协作开发代码库。 团队可以使用 GitLab 代码库,选择 Git 或 Mercurial,且可以轻松地从 其他代码库导入代码。

  • GitLab CI/CD:GitLab 的 CI/CD 工具允许团队自动化软件交付过程。 GitLab CI/CD 使团队能够以安全高效的方式在各种环境中构建、测试和部署应用程序。

  • GitLab 容器注册表:GitLab 容器注册表是一个内置的容器注册表,允许团队存储、管理和部署 Docker 镜像。 团队可以使用 GitLab 容器注册表创建和管理镜像,并将其部署到 首选平台。

  • GitLab 监控:GitLab 监控是一个监控工具,提供应用程序和基础设施性能的实时可视化。 团队可以使用 GitLab 监控工具监控其应用程序和基础设施的健康状况,发现问题并迅速 解决问题。

GitLab 也具有高度的可配置性和可定制性。 团队可以轻松定制平台以满足他们的需求和偏好。 GitLab 支持多种集成,并拥有一个庞大的第三方扩展 和插件生态系统 ,团队可以使用这些扩展来扩展 其功能。

Azure 服务在 DevOps 工作流中的应用

Microsoft Azure 提供了一系列广泛的工具和服务,能够很好地集成到 DevOps 工作流中。 涵盖了秘密管理、配置管理、负载测试、混沌工程和应用托管/部署的广泛工具和服务,并具备全面的监控和 可观察性功能。

图 1.21 – Azure 云原生服务用于 DevOps

图 1.21 – Azure 云原生服务用于 DevOps

图 1**.21 展示了可以在 DevOps 工作流的不同阶段使用的一些工具。 我们来回顾一下这些服务以及它们 如何适应:

我们有多种服务来托管 我们的应用程序:

  1. 构建阶段:

    • Azure 密钥保管库:提供安全的秘密管理,允许开发人员存储和检索敏感信息,如 API 密钥、密码 和证书。

    • Azure 应用配置:此服务支持集中配置管理,提供在多个环境中存储和检索应用设置的方法。

  2. 测试阶段:

    • Azure 负载测试:通过模拟用户流量并分析系统在负载下的行为,这使得应用程序的压力测试和性能测试成为可能。

    • Azure 混沌工作室:通过引入 受控 干扰和故障来测试 系统的弹性。

  3. 发布阶段:Azure 提供了多种应用托管 和部署的计算选项:

    • 虚拟机(VM)和虚拟机规模集:这些提供了部署和管理虚拟机以托管应用程序的灵活性。

    • 应用服务:提供一个平台来托管 Web 和 API 应用程序,无需担心 基础设施管理。

    • 函数应用:这使得可以开发无服务器函数以按需执行代码 。

    • 容器服务:这支持容器化应用程序的部署,提供如 Azure 容器实例(适用于轻量级工作负载)或 Azure Kubernetes 服务(用于编排和扩展 容器化应用程序)等选项。

  4. 操作和 监控阶段

    • Azure Monitor:这为应用程序和基础设施提供全面的监控和诊断,允许团队深入了解系统性能 和健康状况。

    • 应用程序洞察:这提供了实时应用程序性能监控和日志记录,帮助开发人员快速检测和诊断 问题。

    • 用于可观察性的托管 Grafana:这将流行的开源可观察性平台 Grafana 与 Azure 服务集成,能够提供先进的数据可视化和分析,用于监控 和故障排除。

请记住,这里提到的示例只是其中的一部分,我们在后续过程中会遇到更多的服务。 在本书中,我们将探讨支持 DevOps 实践并增强软件开发过程的各种 Azure 服务,特别是那些与安全相关的 用例。

目前请注意,DevOps 和云计算是相辅相成的,因为两者都旨在加速软件开发和部署。 云提供了可扩展且灵活的基础设施,可以支持现代软件开发的需求,并提供增强该过程的服务,而 DevOps 则提供了一个框架,用于高效地在 云中管理和部署软件。

现在我们已经 探讨了 敏捷、DevOps 和云计算的基本概念,让我们来看看这三者是如何结合在一起,以支持现代软件 开发实践的。

敏捷、DevOps 和云 – 完美的三重奏

采用 DevOps 方法 并非孤立地产生效益,而是与其他概念相结合,如敏捷规划和云计算。 敏捷是一种项目管理方式,注重灵活性和对变化的响应。 云计算指的是使用基于网络的计算服务,而不是物理服务器和软件。 敏捷、DevOps 和云三者结合,可以帮助组织更高效地工作 并提高效率。

一些组织可能只使用其中一个或两个概念,但最佳的结果来自于三者的结合。 我们可以在不实践 DevOps 的情况下采用敏捷方法进行软件开发;也可以实施 DevOps 实践,但不涉及云计算,遗憾的是,许多组织在没有实施 DevOps 实践的情况下采用云计算也很常见。 对于云原生应用和新软件,三者的协同—敏捷、DevOps 和云—通常能带来最佳结果,正如下面的 图示所示:

图 1.22 – 敏捷、DevOps 和云

图 1.22 – 敏捷、DevOps 和云

我们这样说:敏捷是 我们应该做的事情,DevOps 是 我们应该如何做,云计算是 我们应该在哪里做 的方式。

然而, 需要 认识到,这个通用规则有例外。 将 敏捷、DevOps 和云计算结合应用于某些场景时,可能会面临不同的挑战和动态。 虽然这三者的整合对许多应用非常有益,但它并非在每个场景中都能保证成功。 正如俗话所说,金玉其外,败絮其中,并不是所有 DevOps 与云的结合都会带来 成功的结果。

让我们暂时结束讨论。 在接下来的章节中,我们将设置所需的云账户,以便跟随本书余下部分的动手练习。 本书的内容将涵盖这些练习。

动手练习 1 – 创建一个 Azure 订阅

让我们从 创建 订阅开始:

  1. 打开一个网页浏览器并访问 到 https://signup.azure.com

  2. 点击 登录

  3. 输入你的个人资料信息,验证你的身份,并同意条款和条件。

  4. 点击下一步并提供你的信用卡信息(注意,只有在你将订阅从免费试用切换到付费订阅时,信用卡才会被收费)。

  5. 点击注册

实践练习 2 – 创建一个 Azure DevOps 组织(与您的 Azure AD 租户相关联)

接下来,我们将创建一个新的组织:

  1. 打开一个网页浏览器,访问portal.azure.com(Azure 门户)。

  2. 在 Azure 门户中,在顶部的搜索区域,搜索并选择Azure DevOps

  3. 点击我的 Azure DevOps 组织链接。

  4. 在弹出的窗口中,配置以下内容:

    • 名称:输入你新建的 Azure DevOps 组织的名称。

    • 项目位置:选择一个靠近你的位置

接下来,我们来配置我们的新组织的账单:

  1. 在 Azure DevOps 控制台中,点击左下角的组织设置

  2. 点击账单,然后点击设置账单

  3. 选择你的 Azure 订阅,然后点击保存

实践练习 3 – 创建 GitHub 企业云试用账户

首先,我们来创建一个GitHub 企业云组织:

  1. 要创建一个 GitHub 组织,请访问github.com/pricing,点击开始免费试用,然后选择企业云

图 1.23 – 创建企业云组织

图 1.23 – 创建企业云组织

  1. 登录 GitHub 或创建一个账户。

  2. 登录后,你将被引导至 设置你的企业试用 页面。 填写所需的详细信息并点击 创建你的 企业 按钮。

干得好! 你现在已经 完成了为接下来的实践练习所需的云账户设置。 接下来的章节将继续进行。

总结

本章概述了 DevOps——一种现代应用程序开发和交付方法,帮助组织更快速地将高质量软件交付到生产环境,并减少缺陷! 我们讨论了 DevOps 的五个核心实践、DevOps 工作流中的不同阶段,以及协作文化在 DevOps 成功中的重要性。 我们还强调了需要避免的 DevOps 反模式和反例,并介绍了流行的 DevOps 平台,如 Azure DevOps、GitHub Actions 和 GitLab。 本章所获得的知识为你提供了扎实的基础知识,帮助你理解本书其余部分的讨论。

在下一章,我们将深入探讨 DevOps 的安全挑战,探索潜在的风险以及组织如何开始应对这些挑战。 敬请期待!

进一步阅读

要了解本章讨论的更多内容,请查看以下资源:

  • 《加速:精益软件与 DevOps 的科学:构建和扩展高性能技术组织》 作者:Nicole Forsgren, Jez Humble, 和 Gene Kim。

  • 《凤凰计划:一本关于 IT、DevOps 以及帮助你的企业成功的小说》 作者:Gene Kim, Kevin Behr, 和 George Spafford。

第二章:DevOps 工作流的安全挑战

随着组织采用 DevOps 实践,他们面临着新的安全挑战,这些挑战将要求他们将 DevOps 转变为 DevSecOps。 这些挑战源于开发和部署速度的提高、过程的自动化以及开发和运维团队之间的协作。 过去服务良好的传统安全方法可能不足以应对这些新兴问题。 因此,组织必须调整其安全实践,并培养以安全为重点的文化,以保护其应用程序、系统 和数据。

在本章中,我们将探讨实施 DevOps 实践所带来的独特安全风险和威胁。 我们将研究组织如何有效地应对这些挑战。 在本章结束时,您将对以下 关键领域有一个扎实的理解:

  • DevOps 的安全挑战 (Security challenges of DevOps)

  • 支持 DevSecOps 和 持续安全

  • 持续安全的挑战 (continuous security)

  • DevSecOps 和供应 链安全

这些主题将为您提供宝贵的见解,帮助您理解为什么仅依靠 DevOps 不足以应对挑战,以及为何必须采用 DevSecOps。 此外,我们还将强调组织在 DevSecOps 过程中应当注意的陷阱。 准备好导航 DevSecOps 的领域,在这里,安全占据核心地位,现代开发环境的挑战将 迎刃而解。

技术要求

要跟随本章的说明,您需要 以下内容:

  • 一台带有 互联网连接的 PC

  • 一个有效的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

DevOps 的安全挑战

随着许多组织的发展 它们的软件交付实践(如前一章所讨论),它们仍然固守传统的安全流程,这些流程难以跟上 DevOps 世界快速发展的步伐。 根据 Dynatrace 2021 年 首席信息安全官CISO)的报告,63%的 CISO 认同转向现代交付模型,如 DevOps,已经严重影响了他们检测和管理软件漏洞的能力! 这并不令人惊讶,因为 DevOps 的核心是速度、灵活性和持续改进。 如果不进化我们的安全流程和进行适当的安全集成,就像开着没有刹车的 F1 赛车——迟早会发生碰撞和灾难。 或者早,或者晚。

注意

Dynatrace 2021 年 CISO 报告可以通过以下 链接访问: https://assets.dynatrace.com/en/docs/report/2021-global-ciso-report.pdf

在本书的接下来的章节中,我们将探讨组织如何调整其安全实践,拥抱自动化,并培养安全意识文化。 然而,在我们开始这段旅程之前,让我们先花点时间看看为什么传统的安全在快速发展的 DevOps 领域中会遇到困难并且受到限制。 。

了解传统安全在快速发展的 DevOps 世界中的局限性

在 DevOps 的世界里,速度 至关重要。 然而,随着速度的提升,也带来了潜在的弊端:漏洞的增加,这些漏洞可能会悄悄溜过。 当组织试图跟上更快发布和更快迭代的需求时,意外引入漏洞的风险也在同步增加。 。

随着软件开发和部署速度的提高,随之而来的漏洞也在不断增加,并且可能会通过漏洞滑过。

传统的安全流程难以跟上这种速度,因为它通常采用人工方式。 人工安全检查和评审既耗时,又容易出错,在 DevOps 环境中不可扩展。 例如,考虑像微信这样的一家公司,每天向生产环境部署约 1,000 次;很少有组织能够有足够的人工资源来每天手动评估 1,000 次发布! 此外,执行合规性检查的僵化任务通常由安全团队负责,这有时会让他们在人际关系上显得不太受欢迎 。

注意

已实施云原生技术的公司已成功实现了显著的 速度、敏捷性和可扩展性,如下所述: https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/definition

此外,传统的安全方法在支持采用 DevOps 软件交付模型的组织常用的现代技术时面临着局限性。 在 DevOps 的世界里,越来越多的开发团队承担起了运营职责。 他们不仅负责编写代码,还负责部署和管理应用程序。 为了促进这一转变,他们采用了云原生技术,如微服务架构,来开发和部署独立的服务,使用容器化技术实现便捷的部署和扩展性,并通过代码管理基础设施。 然而,传统的安全方法并没有能力应对这些现代技术所带来的独特挑战。 保护这些技术需要 在安全方法上的转变,并采用 更新的工具集。

微服务和容器化

微服务架构:一种软件开发方法 将应用程序构建为一组小型、独立的服务。 每个服务可以与其他服务协同工作,使得单独管理和更新更加简单。 一个微服务的例子是反馈服务,用于管理用户反馈,可以被其他应用程序重复使用。 其他应用程序 也可以使用该服务。

容器化:一种软件分发和部署 方法,将应用程序及其必要的设置和依赖项打包成一个 容器,确保在各种 计算环境中一致地运行。

在 DevOps 世界中,传统安全流程的另一个问题是,安全相关的活动通常被 relegated 到开发生命周期的最后阶段(图 2**.1)。 它像一个守门人,站在最后,评估软件在发布前或发布后是否存在安全漏洞。 这种方法将安全视为一个独立的阶段,而不是开发过程的一个不可或缺的部分,如功能性 或性能。

图 2.1 – 软件开发工作流程中的传统安全集成

图 2.1 – 软件开发工作流程中的传统安全集成

这种“关卡”思维的后果是,当软件进入生产环境时,安全突然成为一个障碍。 有位高级开发人员曾与我分享过他们的经历,说:“我们做的每一件事都进展得很快且顺利,直到我们尝试部署到生产环境时,安全就成了问题!” 这句话完美地 概括了当传统安全在 DevOps 流程中引入摩擦时,可能会引发的挫败感。

了解 DevOps 如何增加攻击面

采用 DevOps 实践 引入了组织内部的新工具(我们在本书的第一章中讨论了其中的一些工具)。 如果使用得当,这些工具可以大大提高开发人员的生产力。 然而,它们也带来了自身的一些挑战。 如果管理不当,它们可能导致攻击面扩展,并为潜在攻击者创造机会。 这其中涉及到的风险包括访问控制不足、不安全的工具配置、工具本身的漏洞 、凭证管理以及监控和日志记录的不足。

例如, 一个典型的 持续集成/持续交付 (CI/CD) 系统:

  • 它可以访问组织的源代码,这是其中最 重要的资产之一

  • 它可以生成部署到 多个系统的构建产物

  • 它对 生产环境拥有特权访问权限

  • 它在 构建过程中 拥有对服务凭证的访问权限。

如果没有适当的安全措施,这种广泛的访问权限可能带来严重风险。 如果攻击者能够利用一个弱点,他们可能会进入软件供应链,注入恶意软件,从而影响更多的受害者,并访问 敏感数据。

这类针对 DevOps 工具的攻击频率正在增加,我们预计未来几年这一趋势将进一步加剧。 Forrester 在 2021 年的一项研究发现,57%的组织曾遭遇与 DevOps 工具链曝光相关的安全事件。 这表明,随着这些工具在大多数组织的关键开发过程中占据核心地位,它们已成为攻击的主要目标。 。

Forrester 报告

Forrester 是一家著名的市场研究公司,提供有关技术现有及潜在影响的建议。 有关前述报告的更多详细信息,请参考 https://www.prnewswire.com/news-releases/thycoticcentrify-report-57-of-organizations-suffered-security-incidents-related-to-exposed-secrets-in-devops-301425193.html

除此之外,这些工具本身也可能包含可被利用的漏洞。 在流行的 DevOps 工具链中,曾出现过显著的漏洞,例如 CVE-2016-0792,一个 远程代码执行 (RCE)缺陷,影响了广泛使用的 CI/CD 服务器 Jenkins。 在公共漏洞数据库中搜索任何 DevOps 工具,都能发现多个可被利用的漏洞,且这些漏洞已经存在很长一段时间了! 然而,这个问题不仅限于主要工具或平台。 这些工具还支持大量的插件和扩展生态系统,这使得安全团队很难确定 合适的安全框架 来应对它们。

注意

尽管 DevOps 工具集引入了新的风险,但它们也为我们提供了一系列工具来缓解开发过程中的风险,这是过去很难做到的。 安全评估可以在版本控制中的代码、同行评审时以及通过自动化测试来进行。 这些工具的正确使用可以进一步增强我们开发实践中的安全性。 我们将在接下来的章节中介绍如何实现这一点。

DevSecOps 的论点

如前所述,将安全作为软件开发生命周期中的一个独立阶段来隔离 并不利于 DevOps 的原则,因为 DevOps 强调速度 和敏捷性。

要在 DevOps 环境中有效地实施安全,必须将其无缝集成到工作流的每个环节中。

要在 DevOps 环境中有效地实施安全,必须将其无缝集成到工作流的每个环节中。 否则,安全将变得难以管理,且 妨碍扩展性。

将安全嵌入到每个工作流中意味着从一开始就将安全实践和考虑因素纳入,而不是将其视为一项单独的任务。 这种方法称为 DevSecOps。DevSecOps 的主要目标是让构建和交付软件的团队能够尽早识别并解决开发周期中的关键安全问题。 为了实现这一目标,DevSecOps 在软件开发和交付过程中增加了一项新的核心实践——持续安全,它被嵌入到每个其他 实践中(图 2**.2)。

图 2.2 – DevSecOps 核心实践

图 2.2 – DevSecOps 核心实践

但要真正理解 如何有效地实施 DevSecOps,达到预期结果,我们需要了解其关键组成部分——文化流程工具。让我们深入探讨这三个方面。

理解 DevSecOps 的文化层面

遗憾的是,大多数关于 DevSecOps 的讨论 主要集中在工具的集成,或许还有一些流程。 我们认为,这可能是一些组织未能从其 DevSecOps 计划中获得更好成果的原因。

DevSecOps 的核心代表了一种文化转变。在大多数组织中,开发、运营和安全团队之间有明显的分工。 开发团队负责编写代码和构建应用程序,运营团队负责应用程序的部署和配置,安全团队则负责保护生产环境中的应用程序。 生产中的应用。

DevSecOps 的文化旨在消除这些传统上独立角色之间的孤岛。 目标是让人们更好地协作,使整个软件开发过程更加安全。 在这一模式中,所有团队都共同负责帮助企业实现其持续为最终用户提供安全且功能完备的软件的目标。 每个团队都贡献其独特的专业知识,通过协作共同努力实现这一目标,远离一种以持续归咎 和回避为特征的文化。

文化转变

这是组织在一段时间内在态度、行为、价值观或规范上的重大变化。 它通常涉及领导风格、操作实践或 公司价值观的变革。

消除孤岛并创建 集体焦点通常需要时间和大量的组织工作,因为它涉及改变根深蒂固的习惯、常规和态度。 这常常会导致团队成员的抵触,尤其是当变革未能有效沟通或被理解时。 要成功实施,必须具备几个关键要素,包括高层领导支持、团队培训和团队结构的调整。 让我们来看一下这些要素:

  • 高层赞助:在组织内部将 DevSecOps 付诸实践不是一次性的事件。 这是一个必须从某个地方开始的旅程。 如果我们要提出建议,我们会说从获得高层领导的支持开始。 这是确保与业务目标对齐、获得所需利益相关者的支持、为该举措提供政治保护,并定义和批准所需预算的关键。 大多数成功的安全倡议,能够在整个组织范围内产生影响的,通常都是那些获得 高层支持的倡议。

Synopsys BSIMM 报告

Synopsys 安全构建成熟度模型 (BSIMM)系列报告为软件安全倡议提供了一个基准,强调了高层赞助和领导力的重要性。 最新的 报告可以在这里找到: https://www.synopsys.com/software-integrity/engage/bsimm/bsimm13

  • 审视团队结构与度量指标:DevSecOps 文化挑战了传统安全团队如何与开发和运维团队整合,以满足更广泛的业务需求。 我们不再维持一个有着冲突度量标准的孤立团队结构,这种结构会导致一种 文化的状况,而是拥抱了新的团队结构和协作模式,重点强调安全作为推动力,而非 阻碍。

    安全团队与开发和运维团队紧密合作, 以确保开发和发布能够按照业务需求的快速节奏进行,同时保持安全。 这种方法要求安全团队的思维方式发生转变,优先考虑按照业务需求快速交付软件,同时将安全作为促进这一目标的工具。 这通常导致安全团队转向一种新模式,专注于赋能开发者和运维团队,以安全的方式执行他们的任务,最大程度地减少进入生产环境的重大风险。 这种方法与 向左移动 哲学一致,在这种哲学中,责任(如安全问题)会在开发或任务生命周期的早期阶段得到解决。 DevOps 中的向左移动意味着从开发的最早阶段就确保应用程序的安全,这是 DevSecOps 的一个关键原则,旨在促进开发、安全和运维团队之间的合作。 这一方法的成功必须以共情为核心——愿意了解每个团队的工作方式,以共同确定整合 安全实践的最佳方式。

  • 培训与沟通:正如我们之前所提到的,培养 DevSecOps 文化需要每个人都树立安全优先的思维方式,每个人都要对交付安全软件的各自责任负责。 实现这一目标只能通过培训和沟通来完成。 我们将在第三章中介绍如何实施有效的安全培训计划, 在 DevOps 的 规划 阶段中实施安全,因此我们将在那时再详细讨论。

在现有组织中接受 DevSecOps 文化 可能会面临挑战,但这是实现安全软件开发的重要步骤。 然而,这种文化转变只是方程式的一部分。 为了帮助个人过渡到这一新文化,必须有结构化的流程来指导团队成员,并提供一个清晰的操作框架 供操作使用。

理解 DevSecOps 的过程方面

DevSecOps 是 DevOps 的演变 因此,基本流程是相同的。 DevSecOps 扩展了我们在本书第一章中介绍的相同的 DevOps 流程,增加了持续安全培训、持续安全验证和持续安全衡量的层次。 这些流程帮助过渡到一个状态,在这个状态下,安全被所有人视为创建和交付软件的一个核心元素,与功能性和稳定性处于同等地位。 让我们讨论一下 这些流程:

  • 持续的安全培训:这一过程为提高 角色特定的 安全知识和技能提供了正式和非正式的渠道。 这包括让团队保持对最新的和 相关的 安全最佳实践、漏洞和缓解策略的了解。 这可能包括关于安全编码实践、安全基础设施配置的正式和非正式教育,或者提高对相关威胁行为者的意识。 目标是建立一种安全优先的心态,贯穿整个组织,并使安全成为每个角色的核心组成部分。 成功的关键是优先考虑参与度;否则,它可能只是另一个走过场的活动。 这就是为什么需要大量的思考和合作,以确保培训能够持续保持其相关性。 我们将在本书的下一章中进一步探讨这一点。

  • 持续安全验证:这是定义您组织中不同项目类别的安全软件构建和发布应如何进行的过程。 它涉及安全团队与主要利益相关者(如工程和运维)之间的持续合作。 目标是 共同 建立一套建议的定期安全评估和必须遵守的关键安全护栏。 这使得安全团队的角色从验证每个独立的发布转变为定期检查发布管道的完整性。 成功的关键在于协作——确保验证过程是 共同达成的 ,并且所有参与者都理解其重要性。 在定义此过程在您环境中的具体形式时,请勿过分关注工具或测试。 相反,专注于您希望实现的改进成果。 像所有其他 DevOps 流程一样,这是一项持续的活动,需要随着标准的演变和新见解的获取不断调整。 我们将在本书的 第四章第七章 深入探讨这一主题。

  • 持续安全测量:最后,持续安全测量侧重于与利益相关者达成一致,确定用于评估进展和成果的度量标准。 该过程的目标是提供对安全实践有效性的持续可见性,并为持续改进提供见解。 这可能涉及跟踪关键指标,如进入工作流后期阶段的关键漏洞数量,以及整体安全健康状况的改善(以评估持续安全培训的效率)。 在确定这些度量标准时,请记住,DevSecOps 是一段永无止境的旅程。 度量标准和 关键绩效指标 (KPI)不应只盯着结果,而应关注 持续改进和向成熟度发展的趋势。 。

现在您对定义 DevSecOps 工作流中的额外流程有了一些了解,接下来让我们关注 DevSecOps 的工具方面 。 DevSecOps 的工具链。

选择 DevSecOps 工具链的考虑事项

要实施 DevSecOps 流程,我们需要 正确的工具集。 一个常见的错误是试图将那些没有为 DevOps 工作流设计的安全工具强行融入生态系统中。 并不是所有的安全工具都能很好地集成到 DevOps 工作流中! DevSecOps 最适合使用 以开发者为中心 的安全工具,这些工具是以开发者为核心用户而设计的。 这些工具优先考虑速度和与开发者所使用工具的集成兼容性,而不仅仅关注于 生产环境。

工具集还应考虑到一些新的云原生技术,如容器化(Docker、Kubernetes 和 Helm charts)、基础设施即代码(Terraform、ARM 模板和 Bicep 模板)、微服务以及云服务,如托管平台计算服务 和无服务器计算。

在选择工具时,我们需要考虑许多 因素。 一些因素,如支持范围、兼容性和集成,涉及工具的技术能力。 其他因素,如易用性、情境性和成本,则与商业考虑和用户体验相关。 这两组因素都非常重要。 决策应当通过协作方式进行,涉及到将使用这些工具作为日常工作一部分的安全实践者、开发者和运维团队。 他们的意见至关重要。

以下是选择工具集时需要考虑的一些关键事项: 选择工具集时需要考虑的事项:

  • 在你的组织中,构建和部署软件使用了哪些工具? 你的组织使用了哪些工具?

    理解这一点很重要,这有助于确保我们选择的工具与我们环境中正在使用的工件兼容。 在选择工具之前,考虑以下事项。 我们的环境中使用了哪些技术? 有哪些安全工具可以用来评估和解决安全问题? 这些工具的先进程度如何?它们的成熟度如何? 例如,它们是否可定制? 以下是一些需要识别的工件: 需要识别的工件包括:

    • 了解当前环境中使用的各种应用代码语言和平台,如 C#、Java、Node.js 和 Python。 你的组织是否与特定的技术栈保持一致?这种一致性多大程度上会发生变化? 是否允许在不同项目中选择不同的语言? 项目之间的语言选择是否灵活?

    • 了解基础设施代码和模板的使用。 哪些模板格式在基础设施 部署中使用? 示例包括 Azure 资源管理器 (ARM) 模板、Terraform 模板以及 Bicep 模板。

    • 评估 作为代码的镜像 技术在贵组织中的作用,例如 Dockerfiles、Packer 模板以及用于 Azure 的共享镜像库,帮助创建一致且 可重复的环境。

    • 考虑 作为代码的部署 方法论,使用 Kubernetes 清单文件和 Helm 图表等技术来自动化您的容器化 解决方案部署。

    • 检查正在使用的容器镜像,例如 Linux 镜像、Windows 镜像或 无发行版镜像。

    • 最后,考虑配置 代码和脚本,如 Puppet 清单、Chef 菜谱、Ansible YAML 模板、PowerShell 脚本或 Bash 脚本,这些有助于保持基础设施的一致配置。

  • 哪些安全问题 被检测到?

    这个考虑是重要的,但也应由价值驱动。 它涉及决定您希望在开发周期的早期捕捉哪些安全问题,并为开发人员提供更短的反馈循环。 决定这一点将影响您选择的工具。 一些工具通过与 技术、战术和程序 (TTPs) 对齐来提升其检测能力。 这种对齐有助于防御恶意实体采用的特定策略和威胁向量。 逐步解决这一问题是完全可接受的,从对开发人员造成最小干扰但对组织安全态势有意义影响的问题开始。 随着团队信心的增长,我们可以慢慢地加入其他问题检测方法。 在决定您的工具集时,以下是一些需要关注的问题: 工具集:

    • 硬编码密钥检测:检测硬编码密钥的能力,例如 API 密钥、数据库凭证或嵌入代码中的加密密钥。 如果这些密钥被暴露,可能会带来严重的安全风险,导致未经授权的访问或 数据泄露。

    • 代码漏洞:检查应用程序代码中的弱点的能力,这些弱点可能会被利用,从而危及系统安全。漏洞可能涉及应用程序代码中的问题,如缓冲区溢出、注入攻击、不安全的直接对象引用,或者基础设施或部署代码配置错误,如 IaC 模板、Kubernetes 清单文件和 Helm 图表中的错误配置。

    • 开源软件包漏洞:检测开源库或软件包中的漏洞的能力。现代应用程序在很大程度上依赖这些库,因此评估它们是否存在已知漏洞至关重要。如果攻击者利用软件包中的漏洞,他们可能会危及整个应用程序。

    • 开源许可证合规问题:评估开源软件包的许可证要求的能力,以确保组织不会因未遵守许可证规定而面临法律问题。开源软件包有多种许可证,每种许可证都有自己的一套义务和限制,因此在我们的环境中评估其使用至关重要。

    • 恶意软件:扫描和检测可能对应用程序或底层系统造成危害的恶意软件的能力。包括病毒、蠕虫、木马、勒索软件和间谍软件。

    • 软件材料清单SBOM):SBOM 是一个软件组件的全面清单。评估工具会审查 SBOM,确保每个组件都是最新的、安全的,并符合许可证要求。这有助于管理软件供应链风险,并促进有效的漏洞管理。

  • 支持哪些集成?

    DevSecOps 工具可以在软件开发生命周期的各个阶段进行集成。每个集成点都为在漏洞成为严重问题之前捕获并修正安全漏洞提供了机会。了解我们工具集支持的集成点非常重要。以下是一些关键的集成点:

    • 集成开发环境 (IDE):这些是开发人员花费大部分时间编写和测试代码的工具。 将安全工具集成到 IDE 中可以对潜在的安全问题提供即时反馈,使开发人员能够立刻修复漏洞。 它还可以帮助开发人员学习并调整编码习惯,从而提高所编写代码的整体质量。 此类集成的例子可能包括代码检查工具或静态代码分析工具,它们能够直接在 IDE 中突出显示并在某些情况下修复潜在问题。

    • 源代码控制仓库:当代码被提交到一个中央 源代码控制仓库时,比如 GitHub、Azure Repos 或 GitLab 仓库,进行自动化安全检查是非常有益的。 这可以包括我们之前提到的任何功能(如硬编码秘密检测、代码漏洞等)。 如果发现问题,可以提交一个拉取请求来解决它。 这不仅可以早期识别安全风险,还能帮助我们在周期的早期阶段衡量安全集成的有效性。 DevSecOps 是一个持续的过程,展示持续的价值是非常重要的。 将安全工具集成到 IDE 中可以帮助我们进行衡量并 展示这一点。

    • CI/CD:CI/CD 流水线是安全工具集成的另一个重要领域。 随着代码的合并并准备进行构建和部署,自动化的安全检查可以确保不会创建或发布有漏洞的构建工件到生产环境。 这可能包括动态安全测试、依赖检查、容器安全扫描或自动合规检查。 这 可能涉及的工具包括 静态应用安全测试 (SAST) 和 动态应用安全测试 (DAST)。 通过在每次代码合并或部署时集成自动化安全测试,我们可以应用防护措施,若发现漏洞,则阻止代码进入下一阶段,作为构建或部署过程的一部分。 我们还可以自动嵌入必要的运行时 安全功能,例如 运行时应用自我保护 (RASP) 代理,确保应用程序在部署到生产环境时的安全覆盖 。

    • 运行时:部署后,持续监控应用程序及其环境中的潜在安全漏洞或事件至关重要。 这可能包括监控异常行为、审计系统和应用日志,以及定期扫描运行时环境中的漏洞。 集成到这一阶段的工具旨在提供实时告警和自动响应功能,能够最小化发生的任何安全事件的影响。 值得注意的是,现代应用程序运行在各种云计算服务上。 这包括客户管理的虚拟机、托管平台服务(如 Azure App Service),甚至无服务器服务(如 Azure Functions 应用、Azure 容器实例和 Azure 容器应用)。 我们需要考虑运行时安全的价值,并思考如何为不同类型的 运行时环境集成合适的工具。

  • 成本是多少(购买与自建 与采用)?

    决定采用开源、购买商业产品或自行构建是选择 DevSecOps 工具集时的重要考虑因素。 这三种选择各有优缺点,应根据组织的具体需求进行评估。 在大多数情况下,组织会根据 DevSecOps 过程的具体需求和成熟度,选择这三种方案的组合。 当商业解决方案提供显著价值并满足组织需求时,组织可能会购买它们。 他们可能会采用开源解决方案来处理组织尚不成熟的领域,并为无法通过其他方式解决的独特挑战定制解决方案。 这种组合使组织能够享受各方面的优势,同时控制成本。 让我们讨论一下 这三种选择:

    • 开源:使用开源解决方案可能具有成本效益,因为它们不需要直接购买。 我们将在接下来的章节中详细介绍许多优秀的开源工具。 它们通常有活跃的社区贡献并改进软件。 然而,它们通常缺乏自动修复功能,且公司可能需要提供自己的支持和维护。 此外,如果工具缺乏强大的社区支持或项目被遗弃,组织可能会面临没有支持的工具。 开源工具是开始进行安全集成的绝佳方式,许多企业,甚至是大型企业,都依赖一些开源工具来处理其 DevSecOps 工作流的某些方面。

    • 商业解决方案:商业解决方案通常附带专门的支持和维护团队,并且在某些情况下,提供自动修复功能。 它们也可能更容易与现有系统集成,并且能够提供保修和责任保护。 然而,它们通常伴随更高的成本,企业可能最终为不需要的功能付费。 许多提供多个集成 DevSecOps 工具集的平台解决方案是 仅限商业的选项。

    • 内部构建:只有当您的组织面临开源或现成解决方案无法有效应对的独特挑战,并且与集成现有解决方案相关的工作量超过创建定制解决方案的成本时,才应考虑构建您自己的工具。 例如,大公司通常会开发定制工具集,以管理由于规模庞大而产生的独特情况。 还应考虑工具的长期可持续性。 关于工具如何进行维护、更新和改进的问题,应提前作出回答。

用户友好性 和上下文相关性等附加因素也非常重要。 然而,我们将在接下来的章节中探讨具体工具时涵盖这些方面。

DevSecOps 和供应链安全

自从美国行政命令 旨在增强软件供应链安全性和完整性宣布以来(见 图 2**.3),软件供应链安全性的话题获得了 相当大的关注。

图 2.3 – 美国关于软件供应链的行政命令

图 2.3 – 美国关于软件供应链的行政命令

2021 年 5 月美国提升国家网络安全的行政命令

访问以下链接以了解更多关于 美国行政命令 的内容: https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/

我(David)最近为微软 TechNet 写了一篇博客,提供了供应链安全的定义,我在这里重新陈述:

“软件供应链涵盖了创建和交付软件所需的一切,包括集成开发环境(IDEs)、源代码控制系统、构建系统、部署系统、CICD 平台、运行时环境以及各种工件,如应用代码、开源依赖、基础设施代码和部署工件。”

博客

这篇 使用 GitHub 和 Azure 保障代码到云管道安全 的博客文章可以在 此处找到: https://www.microsoft.com/en-gb/industry/blog/technetuk/2023/03/30/securing-the-code-to-cloud-pipeline-with-github-and-azure/?WT.mc_id=AZ-MVP-5003870

DevSecOps供应链安全 是两个不同但相互关联的概念。 DevSecOps 是将安全措施集成到 DevOps 工作流中的方法,而软件供应链安全则超越了这一点,涵盖了创建和交付软件所需的每个组件的安全性! DevSecOps 的主要目标是帮助组织在开发生命周期的早期快速解决关键的安全问题,防止它们在生产环境中成为漏洞,因为修复这些问题的成本要高得多! 软件供应链安全的主要目标是减少已知风险,防止攻击者利用这些风险劫持我们软件交付过程中的任何环节。 交付过程。

在现代软件开发和运维中,这两者都至关重要,因为威胁可能源自开发过程中的内部,或来自外部的第三方组件,甚至在分发过程中出现。 它们是相互关联的,安全的开发实践(DevSecOps)对保障软件供应链安全具有重要意义,而安全的供应链则有助于保护通过 DevSecOps 流程交付的软件。 我们在本书后续部分的做法 是将 DevSecOps 作为实施供应链安全的一种方法论来探讨,同时它也是更广泛的供应链安全框架中的一个组成部分。

总结

在本章中,我们讨论了 DevOps 快速节奏所带来的安全挑战,以及其工具集所增加的攻击面。 我们强调了向 DevSecOps 模式过渡的必要性,其中安全措施在开发周期的每个阶段都得到集成。 我们展示了实施 DevSecOps 方法的案例和好处。 我们总结了 DevSecOps 与供应链安全之间的相互关系,以及组织如何通过集成 DevSecOps 流程并优先考虑供应链安全来更好地保护其软件免受威胁。 本章使你对 DevOps 的安全挑战有了全面的理解。 它还为你提供了有关过渡到 DevSecOps 模式的必要性和好处的清晰见解。 在下一章中,我们将开始讨论如何在 DevOps 的所有阶段实施安全性,从计划阶段开始。 期待在 下一章见到你!

进一步阅读

要了解更多关于本章讨论的主题,请参阅以下资源: :

第二部分:保障 DevOps 计划和代码阶段的安全

在这一部分,你将学习如何在计划阶段实施 DevSecOps 原则,重点关注开发人员开始编写代码前可以解决的安全挑战。 我们还将讨论源代码控制中的安全实现。

这一部分包含以下章节: :

  • 第三章, 在 DevOps 的计划阶段实施安全性

  • 第四章, 实施预提交安全控制

  • 第五章, 实施源代码控制安全

第三章:在 DevOps 计划阶段实施安全性

DevOps 的 计划 阶段侧重于从关键利益相关者和客户那里收集需求和反馈,制定优先考虑关键需求的不断演进的产品路线图,并设计灵活的软件架构。 在这一阶段实施 DevSecOps 应该关注能够在开发人员开始编写代码之前解决的安全挑战! 此阶段的活动应包括实施敏捷的威胁建模过程,以更早地识别设计级别的安全问题,并为您的团队实施安全培训。

在本章中,我们将介绍在实施持续威胁建模过程时的有效方法。 我们还将讨论安全代码到云培训计划的不同成熟度级别。 通过本章的学习,您将对以下关键领域有了扎实的理解: 重点领域:

  • DevSecOps 中传统威胁建模的挑战

  • 如何在 DevSecOps 工作流程中实施敏捷的威胁建模过程

  • 如何使用 Microsoft Threat Modeling Tool 实施威胁建模

  • 持续安全代码到云培训的成熟级别

这些主题将为您提供重要的知识和策略,帮助您从 DevOps 生命周期的最开始阶段就优先考虑安全。 让我们 开始吧!

技术要求

要按照本章的说明操作,您需要 以下内容:

  • 一台带有 互联网连接的 PC

  • 一个活跃的 Azure 订阅

了解 DevSecOps 在计划阶段的应用

预防胜于治疗

我们生活在一个 世界中,许多组织 看重他们的软件甚于他们的物理基础设施。 亚马逊、Netflix、Airbnb 和 Uber 等行业巨头通过创新的软件平台改变了他们的行业,改变了我们阅读、观看电影、旅行和通勤的方式。 对于这些组织和大多数现代公司来说,他们的关键运营不依赖于他们拥有的物理建筑,而是依赖于他们开发的软件,用于向用户提供服务。 。

尽管软件系统在许多组织中扮演着至关重要的角色,但很多组织在规划时只关注功能性和稳定性。 安全性往往成为一个次要问题,通常是在开发工作开始后很久才考虑到。 正如我们在 第二章中讨论的那样,这种做法在 DevOps 工作流中并不适用。 这种将安全性考虑推迟的做法,部分原因是开发和运维团队缺乏有效评估和优先排序风险的专业知识,进而无法在早期阶段规划风险缓解措施。

这时,DevSecOps 发挥了作用。 它鼓励开发、运维和安全团队从一开始就进行持续的合作——在规划阶段。 目标是将安全性作为所有软件设计的核心原则! DevSecOps 提倡在所有参与创建和运行软件的团队中培养一种 安全设计 的思维方式。 为了实现这些目标,组织可以实施几种方法。 其中两个常见的方法是威胁建模和持续的 安全培训。

理解威胁建模及其好处

威胁是一个可能的事件 ,它可能利用应用程序设计或系统架构中的弱点,从而导致不良后果。 任何与应用程序交互的人,无论是组织内部还是外部,都可能成为这种事件的来源。 随着技术的发展,威胁的数量不断增加。 为了防止威胁利用系统漏洞,威胁建模方法可以在设计阶段应用,以指导 防御措施。

威胁建模 是一种结构化的方法,用于识别软件和系统设计中的潜在威胁和漏洞。 一旦发现这些威胁,我们可以根据其概率进行优先排序,并制定缓解计划,采取措施阻止或减少这些威胁的影响。

虽然威胁建模 可以在任何阶段进行,但最好在规划阶段进行,即在编写代码之前,在决定软件架构时进行。 这样,潜在的安全问题可以及早识别和解决,从而减少后期需要进行更加昂贵修复的情况。 在规划阶段实施威胁建模,还有助于培养预防文化,并促进主动的架构决策,从而最小化威胁的数量和影响。 就像土木工程师和汽车工程师在建造建筑物或汽车之前会规划安全功能一样,威胁建模确保我们从一开始就考虑到安全问题 在软件开发过程中。

一旦我们有了威胁模型,我们可以在软件演变的任何时候进行更新和改进。 这种方法很好,因为它可以帮助我们跟踪软件和系统的变化 如何影响威胁模型。

传统的威胁建模框架

威胁建模不是一个新概念 在软件设计领域。 早在 1990 年代,安全专家就开始关注如何识别和减轻软件系统中的威胁。 威胁建模的概念在 2004 年随着 Frank Swiderski 和 Window Snyder 出版的《 威胁建模》一书而引起了广泛关注。 这本书介绍了威胁建模的概念,并提供了如何将其纳入软件开发 生命周期的指导。

多年来,威胁建模不断发展和成熟,已经有多个方法论和框架 被开发出来 以协助这一过程。 一些 著名的威胁建模方法包括微软的 欺骗、篡改、否认、信息泄露、拒绝服务、权限提升 (STRIDE) 模型, 操作关键威胁、资产和漏洞评估 (OCTAVE) 框架,以及 攻击模拟和威胁分析过程 (PASTA) 框架。

没有一种通用的威胁建模方法;组织通常根据其项目的特定需求选择方法。 每个框架都提供了独特的视角和关注点。 有些方法侧重于以人为中心的考虑,而其他方法则侧重于风险识别(以风险为中心)或隐私缓解(以隐私为中心)。 有时,结合这些方法可以提供更全面和平衡的潜在威胁理解。 让我们来回顾一些更为 常见的框架。

12 种威胁建模方法

卡内基梅隆大学软件工程研究所的资深成员纳塔莉亚·谢甫琴科(Nataliya Shevchenko)撰写了一篇关于 12 种威胁建模方法的有趣文章。 这是一篇有趣的 文章,您可以在以下网址阅读: https://insights.sei.cmu.edu/blog/threat-modeling-12-available-methods/。您还可以访问 更详细的白皮书: https://resources.sei.cmu.edu/asset_files/WhitePaper/2018_019_001_524597.pdf

我们的目标不是涵盖 传统的威胁建模方法论——对于这个,我们建议参考一本全面的书籍,如 《威胁建模:设计安全》,作者是 亚当·肖斯塔克 ——我们的主要关注点是从 DevSecOps 的角度进行威胁建模。 不过,在本章后面,我们将使用微软威胁建模工具,该工具使用 STRIDE 框架进行 分析。

DevSecOps 中的威胁建模

传统的威胁 建模框架 例如 STRIDE、PASTA 和 DREAD,在整合到 DevOps 工作流程时,由于其高强度的性质,可能会带来挑战。 它们 速度较慢需要较高技能 (需要高水平的专业知识),并且 时间消耗大 (需要相当的时间投入)。 花费数天甚至数周时间构建 复杂的威胁模型,使用 数据流图 (DFD)和信息入口点,分类数据,识别相关威胁,及记录 缓解控制措施的过程并不少见。

然而,在一个软件更新频繁(每日或每周)或定期引入新微服务的动态 DevOps 环境中,传统的威胁模型可能并不是最有效的。 我们最终陷入了一种情况:在试图将安全集成到设计阶段的开始时,我们引入了一个早期瓶颈! 组织内的许多团队已经认为安全会拖慢他们的流程,这只是进一步验证了这种看法。 现实情况是,为每个微服务或软件更新创建一个全面的威胁模型根本 不切实际!

鉴于 DevOps 工作流的快速节奏,需要将威胁建模转化为一种轻量级、快速且增量化的过程。 这并不是一个新想法,但在我们的实践中,我们看到越来越多的组织开始采用现代敏捷威胁建模方法,这些方法优先考虑灵活性和效率。 这些方法将威胁建模过程分解为更小、更易于管理的 模块,这些模块可以持续进行。 Mozilla 的 快速风险评估RRA)和 Slack 的 goSDL 模型提供了很好的资源 ,以促进一种更轻量级的威胁建模和风险评估方法。 这些框架专注于快速评估软件设计和变更中的数据风险。 它们被设计 为快速进行评估,通常评估在 30 到 60 分钟内完成。

理解 Mozilla 的 RRA 过程

Mozilla 的 RRA 提供了一个 30 分钟的风险评估问卷,您可以在 https://docs.google.com/document/d/1uD-wofmkXBz5BVq49JQQqC3DnE77vwOPDSbHdWIve9s/edit找到它。当团队引入新服务时,他们可以与安全团队合作,利用这个问卷评估服务的威胁场景和风险等级。 RRA 模型有四个不同的阶段,如 图 3**.1所示:

Figure 3.1 – Mozilla RRA 的四个阶段

Figure 3.1 – Mozilla RRA 的四个阶段

我们将在本节中涵盖这些阶段。 然而,初步步骤是清晰地定义请求 RRA 会话的流程。 让我们从这一点开始!

定义 RRA 请求流程

为了在组织内引入 RRA ,需要有一个简单且沟通良好的流程,供产品和工程团队遵循。 他们应该能够轻松地请求 RRA,用于新的服务或后续的软件设计更改(例如收集新数据或处理)。 这可以是一个简单的请求表格,方便开发人员在组织中常用的规划工具中访问,无论是 JIRA、Confluence、Azure Boards 还是 GitHub 项目。 与此表格一起,应该有一个最新的可用性日历,用于预订 RRA 会议。 此外,还应该有一份简短的清单,列出参加会议时需要提供的详细信息,包括服务信息、软件架构图、数据流图以及服务 地图图。

当然,这个过程不应当孤立定义。 协作是至关重要的。 通过让来自工程和安全团队的领导者与成员参与其中,我们可以确保相关视角被考虑在内。 他们的集体洞察力、专业知识和反馈可以确保确定的流程与现有团队的实践相一致,并且能够被良好地接受。 最终目标是简化团队的 RRA 请求流程。这也可以嵌入到标准的组织程序中,用于在 Azure DevOps 或 GitHub 组织内请求新项目或代码库。

一个好的起点是组建一个专门的安全开发生命周期团队,致力于评估和改善生命周期的现状。 从战略上看,这强制要求相关利益相关者在场,并从一开始就将安全性融入流程中。 这个团队可以由来自不同团队的成员组成 ,包括 DevSecOps 负责人, 安全运营 (SOC)、云卓越中心、开发人员(由于该团队所做的所有决策都会影响开发人员,因此他们应当拥有发声权)、安全冠军、基础设施架构师以及管理层。 这将需要高层管理的支持 和赞助。

重要的是要认识到 采用敏捷威胁建模技术(例如 RRA)并不否定传统威胁建模方法的价值。 平衡的策略应该是为工程团队提供选择的灵活性。 他们可以选择在处理重要软件项目时采用全面的威胁模型,例如即将推出的旗舰产品,或者在处理较小规模任务时选择 RRA,例如构建微服务或修改软件设计,如 图 3**.2所示:

图 3.2 – 请求威胁建模会议的示例流程

图 3.2 – 请求威胁建模会议的示例流程

注意

明确定义什么算作 重要软件项目 对于避免混淆是有益的。 虽然这个定义可能会随着安全团队对组织的软件交付流程的熟悉而发展,但总是从一个具体的指导原则开始会更好。 从清晰开始,并在必要时进行调整,比在 指导方针中含糊其辞更为有效。

现在,让我们回顾一下 RRA 阶段。

阶段 1 – 信息收集(5 分钟)

本阶段的目标 是对服务有一个高层次的理解。 此时不需要深入到服务的实现细节;这些细节可以稍后再处理。 在这一阶段,安全团队应该花更多时间倾听和学习,而不是发言。 重点应该放在提出有意义的问题上,以理解产品/工程团队的设计、观点和计划。 团队应该积极参与讨论,做好记录,并收集所有相关的 文档链接。

重要的是确保创建一个舒适开放的环境,使产品/工程团队能够安全地分享有关服务和其工作设计的信息,而不必担心被评判。 以下是一些面向背景的问题,可以帮助更好地理解 这项服务:

  • 服务的 所有权

    • 公司内谁负责 这项服务?

    • 将参与此项工作的开发人员是谁 ?

    • 一旦服务上线,谁将负责监督其运营?

    • 如果发生安全 事件,谁将响应该服务?

  • 服务的 受众

    • 它是为内部使用设计的,还是对公众或指定的合作伙伴 和供应商开放的?

    • 公众用户是否会有直接访问权限? 他们将访问服务的哪些部分?

    • 内部用户是否会有直接访问权限? 他们将访问服务的哪些部分? 他们能访问哪些内容?

    • 合作伙伴/供应商是否会有直接访问权限? 他们将访问服务的哪些部分?

    • 每个受众将访问服务的哪些部分? 服务地图和架构图可能有助于快速定义 这一点。

  • 主要的 用户故事

    • 主要的 用户故事是什么?

    • 用户将如何使用 该服务?

  • 该服务将如何 构建?:

    • 是否有 设计文档?

    • 是否有 设计图?

    • 它将使用哪些服务来 存储数据?

    • 它将与哪些外部服务 进行通信?

    • 它将如何与外部服务 进行通信? 是通过直接的 API 调用吗? 还是通过消息队列?

现在,让我们看看 第二阶段。

第二阶段 – 构建数据字典(5-10 分钟)

这一阶段的重点是检查 该服务将处理的数据。 此阶段的目标是了解该服务将收集、处理或访问的数据。 需要考虑的一些问题包括将收集或访问什么样的数据?以及这些数据将存储在哪里? 随着细节的展开,安全团队必须记录这些信息,并按其各自的 分类级别进行标注。

谈到数据分类级别时,这需要在公司层面进行定义(而不是每个项目)。 它还需要由高层管理、安保、合规以及 法律团队确定并批准。

备注

有关定义全组织数据分类级别的建议和最佳实践,请参考 此 文档: https://learn.microsoft.com/en-us/compliance/assurance/assurance-create-data-classification-framework

图 3**.3所示,组织已经定义了四个级别的数据分类:

图 3.3 – 示例组织级别的数据分类

图 3.3 – 示例组织级别的数据分类

示例数据字典 如 图 3**.4 所示,提供了与在线购物平台 eShopOnWeb相关的四种数据类型的概述,以及它们的敏感性或分类级别。 这有助于做出有关数据处理、存储和安全的明智决策。 请注意,这仅仅是一个示例。 你定义数据字典的方法可能有所不同, 这也没问题。

图 3.4 – 示例数据字典

图 3.4 – 示例数据字典

接下来,我们将关注 第 3 阶段。

阶段 3 – 识别威胁场景(5-10 分钟)

此阶段的目的是识别 潜在问题,并通过赋予风险评级对其进行排序。 Mozilla RRA 过程使用 CIA 模型,侧重于机密性、完整性 和可用性:

  • 机密性:如果数据字典中突出显示的数据分类边界被破坏,会发生什么情况?

  • 完整性:如果数据未经授权访问和修改 会发生什么情况?

  • 可用性:如果数据被删除、恶意加密,或者服务 被压垮,会发生什么情况?

对于这些领域,我们应记录四个要素:威胁向量、影响、可能性和风险评级。 让我们来看看 它们:

  • 威胁向量:这些描述了攻击者可能如何危害领域(机密性、完整性和可用性)的方式。 在考虑威胁时,应该想到最严重但现实的情况,而不是极不可能发生的事件。 例如,我们不会担心 Azure 云中所有服务器同时崩溃,因为这是一个高度不可能的场景。

  • 影响:这是评估威胁发生时可能对组织造成的潜在影响。 理想情况下,影响级别应在组织层面进行定义,并涉及相关利益相关者(业务高管、法律团队、合规团队和产品负责人)。 该定义应在 RRA 会议之前提前完成。 确保涉及正确的人员至关重要,因为安全工程师可能倾向于低估企业的风险承受能力。 为了更加谨慎,安全工程师有时会将低影响的威胁评定为高风险甚至是关键威胁。 这可能会稀释真正关键问题的重要性,导致所有问题看起来都很重要,从而降低每个问题的紧迫性。 至少,业务高管应审核并批准影响级别。

    在确定影响级别时,应该考虑多个因素:对业务收入的影响;对服务用户的影响;对组织公众声誉的影响;以及可能的法律影响。 但是,请记住,并非每个因素都适用于你所遇到的每个威胁场景。 例如,要确定对业务收入的影响,可以先查看过去的收入。

    例如,要确定对业务收入的影响,可以从查看过去的收入开始。 将任何可能影响 20% 收入的威胁评为 关键。根据业务代表的反馈,这一基准可以进一步细化。 在考虑对用户的影响时,预计用户数量可以是一个有用的指标。 图 3**.5 提供了一个组织影响评级示例,详细说明了每个级别的条件:

图 3.5 – 组织级别影响示例

图 3.5 – 组织级别影响示例

  • 可能性:这评估威胁发生所需的努力。 这可能很难评估。 在存在设计缺陷的情况下,如何评估或预测它是否会被利用呢? 此外,威胁可能性的动态变化不断。 今天,难以利用 的缺陷可能会变成明天的 易于利用 的缺陷,因为攻击者 的能力在不断提高。

    有些威胁的可能性较低或非常低,因为它们需要付出巨大的努力才能实现。 这些类型的威胁只能由高度激励的对手,且拥有大量资源的对手(如国家级对手)实现。 这排除了机会主义对手,并减少了它们发生的机会。

  • 风险评级:这涉及通过结合威胁的影响和可能性来量化风险。 风险评级有助于优先处理威胁,以便可以有效地分配资源来管理和缓解最高评级的风险。 具有最高影响和最高可能性的威胁应获得最高的风险评级: 关键。只有少数威胁向量应属于 此类别。

    风险评级 = I影响 ** *L可能性

图 3.6 – 风险评级等级示例

图 3.6 – 风险评级等级示例

图 3**.7 显示了这一阶段输出的一个示例。 在这个示例中,识别出了三种威胁情景(每个安全领域各一个)。 第一个威胁的风险评级为中等,因为暴露 UserAddress 信息被业务认为是低影响,且发生的可能性高。 第二个威胁的风险评级为严重,因为通过更改我们提供的文件来感染其他用户可能会违反合规性(严重影响)、影响我们大部分用户(严重影响),并造成持续的声誉损害(严重影响)。 此外,发生这种情况的可能性很高,因为我们经常看到这种情况发生在 数据泄露中。

图 3.7 – 风险评级示例文档

图 3.7 – 风险评级示例文档

现在,让我们来看一下 第 4 阶段。

阶段 4 – 提出安全建议(5 分钟)

本阶段旨在提出解决已识别威胁场景的策略。 建议优先处理来自 上一阶段的最高风险。

图 3**.8 显示了这一阶段的输出示例:

图 3.8 – 示例风险建议文档

图 3.8 – 示例风险建议文档

记住,每个组织天生都会承担一定的风险。 企业并非通过完全避免风险来获取利润。 安全的角色不是阻止组织承担风险,而是识别、评估并提供关于这些风险的见解。 这里的主要角色是教育相关方(产品所有者、开发人员、经理)了解服务设计中存在的风险、潜在的后果和可能的缓解措施。 这确保了企业能够做出充分知情的决策。 虽然安全团队有时可能会感到需要将某些风险级别宣称为不可接受,但这种做法未必总是合理的,尤其是在企业通过抢占市场先机从而获益的场景中。 与其做出决策,目标是启发他人了解 这些风险。

在本节中,我们介绍了规划阶段的威胁建模及其好处。 理论部分已结束,接下来我们将进入一些动手操作,并从 实践的角度学习威胁建模。

动手练习 1 – 配置实验室虚拟机

为了跟随本章及本书后续部分的练习,我们将在 Azure 中配置一个实验室 虚拟机 (VM) 进行操作。 我们已经为此目的在本书的 GitHub 仓库中准备了一个 Azure ARM 模板。 该模板将在指定的 Azure 区域部署一个虚拟机和一个堡垒资源,如 图 3**.9所示:

图 3.9 – 通过提供的 ARM 模板部署的资源

图 3.9 – 通过提供的 ARM 模板部署的资源

以下是我们将在 本练习中完成的任务: 该练习的任务:

  • 任务 1 –在 GitHub 中初始化模板部署;完成参数并将模板部署到 Azure

  • 任务 2 – 使用 Azure Bastion 连接到实验室虚拟机

让我们开始吧!

任务 1 – 初始化模板部署到 Azure

步骤如下:

  1. 打开一个网页浏览器,访问github.com/PacktPublishing/DevSecOps-for-Azure/tree/main/chapter-3

    该链接将打开包含用于部署所需资源的 ARM 模板的 GitHub 仓库。

  2. 在打开的 GitHub 仓库中,点击部署到 Azure

图 3.10 – 启动模板部署

图 3.10 – 启动模板部署

  1. 如果提示您进行身份验证,请使用您的管理用户名和密码登录 Azure 门户。

  2. DevSecOps-Book-RG | azureuser

  3. 管理员密码:输入一个复杂的密码。这是为已部署的虚拟机实例设置的密码。 密码必须至少包含八个字符,并且至少包含一个小写字母,一个数字和一个特殊字符。 请记下这个密码,因为在本章和本书的后续练习中需要用到它。

  4. 选择查看 + 创建

图 3.11 – 填写模板参数

图 3.11 – 填写模板参数

  1. 验证通过后,点击创建

等待部署完成后再继续进行下一个练习。 部署可能需要最多 20 分钟完成,因此在继续之前 可以去喝杯水或咖啡。

任务 2 – 使用 Azure Bastion 连接到实验室虚拟机

这个任务的目的是使用 Bastion 服务建立与实验室虚拟机的连接。 请按照以下步骤操作:

  1. 在 Azure 门户的主页上,在搜索框中输入 DevSecOps-LabVM 并选择 DevSecOps-LabVM 虚拟机,当 它出现时:

图 3.12 – 选择 DevSecOps-LabVM 虚拟机

图 3.12 – 选择 DevSecOps-LabVM 虚拟机

  1. DevSecOpsLabVM 窗口中,在 连接 部分,点击 连接,然后点击 转到 Bastion

图 3.13 – 选择使用 Bastion 连接虚拟机的选项

图 3.13 – 选择使用 Bastion 连接虚拟机的选项

  1. azureuser

  2. 身份验证 类型密码

  3. 密码:输入你在 模板部署期间指定的密码 。

  4. 在新浏览器中打开 标签:已选择

然后, 点击 连接

如果提示,请启用弹出窗口以确保连接成功。 此外,如果提示,点击允许剪贴板访问 。

图 3.14 – 配置虚拟机凭证并启动连接

图 3.14 – 配置虚拟机凭证并启动连接

现在你 已经获得 访问实验室虚拟机的权限,让我们对一个 示例应用程序进行威胁建模。

动手练习 2 – 对电子商务应用程序进行威胁建模

要完成本次动手操作练习,你需要 先完成本章前面的动手操作练习。 在本次练习中,我们将使用 Microsoft 威胁建模工具进行威胁建模练习,这是 Microsoft 的一个基础 安全开发生命周期 (SDL)。这种方法包括创建一个应用程序架构图,使用该工具识别可能的威胁,并提供如何缓解这些威胁的信息。 在本次及后续的练习中,我们将使用 eShop 电子商务应用程序。 图 3**.15 显示了该应用程序的参考架构。 该应用程序有两个不同版本:一个是单体版本 eShopOnWeb(可访问 https://github.com/dotnet-architecture/eShopOnWeb),另一个是为容器部署设计的微服务版本 eShopOnContainers(可访问 https://github.com/dotnet-architecture/eShopOnContainers)。 这两种版本将在 本书中提及。

图 3.15 – eShopOnContainers 参考架构

图 3.15 – eShopOnContainers 参考架构

以下是我们将在本次练习中完成的任务: :

  • 任务 1 – 下载并安装 Microsoft 威胁建模工具

  • 任务 2 – 为 eShop 应用程序创建威胁模型图

  • 任务 3 – 对模型进行威胁分析

让我们开始实际的 威胁建模。

任务 1 – 下载并安装 Microsoft 威胁建模工具

  1. 在实验室虚拟机上,打开 一个 web 浏览器 并浏览至 https://aka.ms/threatmodelingtool。这将自动将安装程序下载到 下载 文件夹。

  2. 打开 下载 文件夹并双击 TMT7 应用程序:

图 3.16 – 要安装的 TMT7 应用程序

图 3.16 – 要安装的 TMT7 应用程序

  1. 当提示时,点击安装以安装 该工具。 如果出现警告要求安装 .NET Framework,请点击 以安装所需版本:

图 3.17 – 安装该工具

图 3.17 – 安装该工具

工具安装完成后,转到任务 2。

注意

在本次动手实验中,我们将使用微软威胁建模工具。请注意,还有更新的工具可用,例如 Threats Manager Studio(threatsmanager.com)。

任务 2 – 为 eShop 应用程序创建威胁模型图

  1. 在实验虚拟机上,点击开始按钮,然后点击微软威胁建模工具打开它:

图 3.18 – 打开微软威胁建模工具

图 3.18 – 打开微软威胁建模工具

  1. 如果系统提示您接受条款和条件,请点击我同意。如果系统提示您参与 客户体验,可以随意取消选中 此选项。

  2. 微软威胁建模工具区域的新模型模板部分,确保已选择Azure 威胁模型模板,然后点击创建 模型

图 3.19 – 微软威胁建模工具的登录页面

图 3.19 – 微软威胁建模工具的登录页面

  1. 这为创建新模型打开了窗口。 请查看右侧的可用模板。 根据您在创建模型时选择的模板,模板类型会发生变化。 以下是 Azure 威胁模型模板 下提供的模板类别: 通用数据流通用数据存储通用外部交互者通用进程通用信任边界,和 通用信任线边界。您可以展开 每个类别:

图 3.20 – 审查模板类别和模板

图 3.20 – 审查模板类别和模板

如前所述,我们将在练习中使用 eShop 应用程序。 我们希望从规划阶段开始识别威胁并添加缓解措施。 我们将基于已知的数据流,即 DFD ,来创建模型。

  1. 使用以下模板 绘制两个信任边界 区域,如 图 3**.21所示。您需要将每个模板拖动到 图表板上:

    • 通用信任边界 | 远程 用户区域

    • 通用信任边界 | Azure 信任边界

图 3.21 – 绘制信任边界

图 3.21 – 绘制信任边界

  1. 使用以下模板 将 浏览器移动客户端 模板添加到 图表板:

    • 通用外部交互者 | 浏览器

    • 通用外部交互者 | 移动客户端

图 3.22 – 添加浏览器和移动客户端模板

图 3.22 – 添加浏览器和移动客户端模板

  1. 将以下模板添加到 Azure 信任边界 部分的 图表板上:

    • 通用进程 | Web 应用程序

    • 通用进程 | Web API

    • 通用数据存储 | Azure SQL 数据库

    • 通用数据存储 | Azure Redis 缓存:

图 3.23 – 添加所需的通用过程和通用数据存储模板

图 3.23 – 添加所需的通用过程和通用数据存储模板

  1. 你也可以右键点击 每个模板,然后点击 选择 属性 来重命名它们并设置其他 可配置属性:

图 3.24 – 重命名模板(可选)

图 3.24 – 重命名模板(可选)

  1. 最后,使用以下模板 定义 连接,如 图 3**.25所示:

    • 通用数据流 | 请求

    • 通用数据流 | 响应

    要创建的连接如下:

    • 浏览器与 电子商店 Web 应用之间的请求/响应连接

    • 电子商店 Web 应用与 Web API 之间的请求/响应连接

    • 移动客户端与 Web API 之间的请求/响应连接

    • Web API 与 订购微服务之间的请求/响应连接

    • Web API 与 购物车微服务之间的请求/响应连接

    • 订购微服务与 Azure SQL 数据库之间的请求/响应连接

    • 请求/响应连接 在购物车微服务 和 Azure Redis 缓存之间:

图 3.25 – 简单的电子商店威胁模型

图 3.25 – 简单的电子商店威胁模型

此时,我们可以继续进行 任务 3。

任务 3 – 对模型进行威胁分析

按照以下步骤操作:

  1. 要分析模型中的威胁,请导航到 视图 顶部,然后选择 分析视图 从图标 菜单中选择:

图 3.26 – 打开分析视图

图 3.26 – 打开分析视图

  1. 基于模型的潜在威胁列表将在图表下方显示。 这些 根据 STRIDE 模型进行分类。 列表中的每个威胁都被分配了一个严重性等级,同时还添加了可能的缓解信息。 您可以 点击 导出 CSV 按钮以导出 该列表:

图 3.27 – 威胁列表

图 3.27 – 威胁列表

  1. 浏览生成的威胁列表及可能的缓解措施。 您可以将每个威胁的状态更新为 未开始需要调查不适用, 或 已缓解

  2. 一旦浏览完列表,选择 报告,然后点击 创建 完整报告

图 3.28 – 创建完整报告

图 3.28 – 创建完整报告

  1. 当系统提示 关于 自定义威胁属性时,保留所有选项并点击 生成报告

图 3.29 – 生成完整报告

图 3.29 – 生成完整报告

  1. eShopApp中。 点击 保存

图 3.30 – 将报告保存到桌面

图 3.30 – 将报告保存到桌面

  1. 当系统提示您打开文件时, 点击 确定

图 3.31 – 打开报告

图 3.31 – 打开报告

  1. 查看 报告:

图 3.32 – 审查生成的报告

图 3.32 – 审查生成的报告

恭喜! 您已成功 使用 Microsoft 威胁建模工具分析了应用模型中的威胁。 接下来,我们将探索安全培训,这是 DevOps 规划阶段的重要组成部分。

实施持续的代码到云安全培训

一个成熟的安全代码到云培训计划应重点解决学员理解上的差距。

在任何关于安全的对话中 都很容易陷入技术细节和工具的讨论中。 然而,正是人类因素和组织文化,而非任何技术缺陷,构成了对组织安全性最为显著的风险。 根据 2022 年数据泄露成本报告(由 IBM 发布),21%的数据泄露是由于人为错误造成的。 这些错误是员工或承包商的无意失误,证明即使是最复杂的软件安全程序也可能因简单的人为错误而受到威胁。 例如,开发人员可能会将生产凭证提交到代码中,或者在其 IDE 中安装恶意 扩展。

IBM 2022 年数据泄露成本报告

https://www.ibm.com/downloads/cas/3R8N1DZJ

为了解决 DevSecOps 过程中的这一风险,组织应实施一个具有明确目标和成功衡量标准的持续安全代码到云培训项目。 接受过安全编码培训的软件工程师更不容易引入安全漏洞,更了解支持工具,且倾向于设计优先考虑安全的软件架构。

然而,许多已实施某种形式安全代码培训的组织,并没有取得成功! 本章的目标不是指导您了解您的培训计划应包括哪些内容(关于这一点有很多文章和文档在讨论)。 相反,我们将重点介绍我们在实践中观察到的风险和挑战,这些通常导致 有限的成功。

根据我(David)在该领域咨询的经验,我观察到,具有较高成熟度的组织,通常会有清晰的预期成果和明确的战略,通常会取得更好的结果。 图 3**.33 展示了我在各种组织中观察到的五个成熟度级别: 各个组织:

图 3.33 – 面向安全代码到云的培训项目的五个成熟度级别

图 3.33 – 面向安全代码到云的培训项目的五个成熟度级别

让我们来看看这五个级别及 它们的特点:

  • 不存在:这不是一个成熟的阶段 而是一个组织完全缺乏安全的代码到云培训程序的阶段。 这导致在遵守组织政策或安全 最佳实践方面,结果不一致。

  • 聚焦合规:在这一成熟度水平中,培训主要旨在满足特定的合规或审计要求。 培训课程通常是定期的,通常每年举行一次,主要是为了满足审计基准。 由于没有全面的战略,遵循安全最佳实践和政策可能 会不一致。

  • 聚焦意识:在这一成熟度水平中,存在初步的战略,并已分配资源,但这些仍然是较为通用的。 培训围绕普遍推荐的做法展开,而非针对 组织特定的做法。

  • 聚焦行为变化:在这一成熟度水平中,重点放在度量分析上,以识别特定于组织的主要 代码到云 风险。 同时,能够有效缓解这些风险的行为也被识别出来。 然后,培训会根据这些行为进行定制。 该级别的成功通过安全事件的实际减少、员工对安全协议的合规性提高以及在 日常操作中一致应用已培训行为来衡量。

  • 聚焦文化变革:在这一成熟度水平中,组织不仅仅改变了已识别的特定行为,而是重塑了整个过程中,从代码到云的安全态度、认知和信念。 该项目得到了高层领导的坚定支持,并定期向高管更新进展。 项目的成功定期进行审查,至少每年一次,涉及个人和 领导层层面的评估。

总之,迈向成熟的安全代码到云培训程序的道路标志着组织成熟度的不断演进。 重要的是,应该优先考虑人和文化,而非 单纯的技术细节。

总结

在本章中,我们探讨了在 DevOps 的计划阶段融入安全性的重要实践,重点介绍了敏捷威胁建模和持续的安全代码到云端训练。 我们突出了在 DevSecOps 环境中传统威胁建模面临的挑战。 为了应对这些挑战,我们概述了如何无缝地整合敏捷威胁建模方法,并以 Mozilla 的 RRA 为例。 最后,我们详细说明了与持续的安全代码到云端训练框架相关的成熟度阶段。 本章为你提供了重要的知识和策略,帮助你从 DevOps 生命周期的计划阶段开始优先考虑安全。 接下来,本章将讨论如何在开发工作流的预提交阶段实施安全控制。 加入我们,继续这段 启发性的旅程!

进一步阅读

要了解本章涵盖的主题,请查看以下资源: 以下资源:

第四章:实施预提交安全控制

在初步规划阶段之后,应用程序开发过程转向代码开发阶段,这一阶段开始于开发者的系统或工作空间。 开发者虽然擅长功能开发和使用编程语言,但可能不知道或忽视了安全细节,导致出现错误。 如果这些错误没有早期发现并解决,可能会导致无意的漏洞,从而可能危及软件或它处理的数据 安全。

此外,如果开发环境/工作空间管理不当,可能会导致攻击者注入恶意代码或组件,成为 软件的入口点。

在本章中,我们将重点介绍可以在代码更改提交 到 版本控制系统 (VCS)之前实施的安全措施和检查。 这包括实施安全控制,以减少开发环境的风险,并设置安全保护措施,在代码提交到本地代码仓库之前,识别和修复漏洞及常见错误。 本章结束时,你将全面理解以下 关键领域:

  • 保持安全的 开发环境/工作空间

  • 防止敏感文件或密钥泄露到代码中的技术 方法

  • 在 IDE 中使用安全扩展以获取实时 安全反馈

  • 实施预提交检查,以确保在提交到 本地仓库 之前代码的安全性。

这些主题将为你提供必要的知识和技能,以便将安全实践融入到 DevOps 工作流的代码开发阶段。 让我们 深入了解!

技术要求

要跟随本章中的指示,你需要 以下内容:

  • 一台带有 互联网连接的 PC

  • 一个有效的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

DevOps 预提交编码阶段概述

理解 DevOps 工作流中的各个阶段 这一章节中 第一章, 敏捷、DevOps 和 Azure 概述,我们概述了标准 DevOps 工作流的八个阶段。 尽管这些阶段的实施在不同组织之间可能有所不同,一些阶段甚至可能为了效率而合并,但总体顺序 保持一致。 在规划阶段之后,过程进入代码开发阶段,从开发者环境开始。 为了使本书中的讨论更加清晰和结构化,我们将代码开发阶段分为 两部分:

  • git add 操作,表示这些更改已经准备好保存或提交(步骤 2图 4**.1)。 开发者接着使用 git commit 操作将暂存的更改保存到本地代码库(步骤 3图 4**.1)。 这不仅存储了更改,还记录了修改的日志。 值得注意的是,大多数情况下,暂存和提交作为单一操作完成 以提高效率。

  • git push 操作。 这一阶段专注于管理代码在该 中央代码库中的状态:

图 4.1 – DevOps 代码开发阶段

图 4.1 – DevOps 代码开发阶段

鉴于本章的主要关注点是 预提交阶段,理解活动发生的开发者环境非常重要。 开发环境的选择在这一阶段如何实现安全性起着至关重要的作用。 在我们讨论其对安全性的影响之前,先来仔细看看可用的开发环境选项。 以便更好地了解其安全性影响。

注意

我们的目标不是全面介绍开发者环境和工具,而是提供一个可用选项的广泛概述。 我们认为,对于负责 DevOps 实践安全性的人来说,了解这些选项及其相关 安全风险是有益的。

理解开发者环境选项

传统上,开发人员 使用本地工作站作为开发环境。 根据组织设备设置过程的不同,这可能包含或不包含编码和参与项目所需的基本工具,如用于源代码管理的 Git、所需语言的 SDK,以及像 Visual Studio 或 Visual Studio Code 这样的 IDE。 此外,许多扩展和工具,包括像 GitHub Copilot 这样的 AI 工具, 通常会被添加。

使用本地工作站进行开发有几个缺点,主要的问题是进入高效状态的延迟。 设置环境并安装所有必需的软件,如 IDE、SDK、扩展和库,可能需要耗费大量时间。 开发人员加入项目后,可能需要数小时、数天,甚至更长时间才能开始高效工作。 举个例子,我(David)最近与一位工程负责人讨论时,他们分享道,开发人员加入项目后通常需要一个月才能提交第一次 PR, 这在他们的组织中是常态!

本地工作站的另一个缺点是,如果系统崩溃或需要更换,整个设置过程通常需要重新开始。 如果有持续的备份,可以避免这种情况,但大多数工作站并没有备份。 另一个挑战是,开发人员需要同时处理多个项目。 在中型到大型组织中,开发人员通常不会仅专注于一个项目。 他们往往需要跨多个项目工作,或者同时为几个项目做贡献。 有时,一个项目所需的工具可能与另一个项目发生冲突,导致开发人员难以顺利从一个项目过渡到另一个项目。 另一个问题是,在处理大型项目时,本地工作站的计算资源有限,例如 像 机器学习 (ML)模型或复杂的 单体应用程序。

从安全角度来看,本地开发工作站通常通过 VPN 或直接连接到公司的内部网络。 如果这些计算机遭到入侵,威胁不仅仅是攻击者获取源代码;它还可能使攻击者能够在网络中横向移动,从而访问其他系统和数据。 这种横向移动可能导致更广泛的泄露和更 严重的损害。

为了解决这些挑战,组织正在探索现代开发环境选项,例如 以下几种:

  • 云端开发工作站:例如, 平台即服务(PaaS) (PaaS)解决方案,如 Azure 虚拟桌面 (AVD) 或 软件即服务(SaaS) (SaaS)产品,如 Azure 的 Dev Box。Dev Box 是为开发者设计的 云端工作站。 它为开发者提供了快速访问 强大计算机的能力,这些计算机已经准备好用于编码。 这些工作站由开发团队设置,配备了他们需要的工具。 IT 团队可以像管理常规笔记本一样管理这些云端工作站。 他们可以实施安全加固,部署工具,审计,并通过自动化维护环境,最大限度地减少数据丢失的风险。 开发者也喜欢它,因为他们可以在不同的 Dev Box 工作站之间切换,每个工作站都为各自的项目提供了资源,并且他们可以通过将工作站置于低功耗休眠模式来节省成本, 当工作站未使用时。

  • 云端集成开发环境(IDE):最近,云端 IDE 已成为代码开发的热门选择。 它们使开发者能够直接从网页浏览器中编写、运行和调试代码,无需本地开发环境。 最常见的云端 IDE 有 GitHub Codespaces、 亚马逊网络服务(AWS) Cloud9、Gitpod、Codeanywhere,以及 Eclipse Che。

    云端 IDE 解决了许多本地工作站面临的挑战。 它们显著缩短了 生产力提升时间 (TTP),让开发者在加入项目后几分钟内就能开始编写代码,而不是等待数小时或数天来安装工具。 对于资源密集型项目,云端 IDE(如 GitHub Codespaces)可以扩展到 32 个 CPU 核心和 64GB 的内存。 这非常强大! 此外,当开发者在多个项目中工作时,他们可以为每个项目维护一个独立的工作区,从而避免工具 之间的冲突。

    图 4**.2 展示了 GitHub Codespace 云 IDE 的架构。 如图所示,codespace 托管在运行 Linux 的容器中 虚拟机VM)在 Azure 上。 我们可以选择我们喜欢的编辑器连接到它。 虽然我们可以直接在 Web 浏览器中编码,但也可以选择使用各种桌面 IDE,包括 Visual Studio Code:

图 4.2 – GitHub Codespace 架构

图 4.2 – GitHub Codespace 架构

  • devcontainer.json 文件。 该文件告诉 Visual Studio Code 或 GitHub Codespaces 如何创建(或访问)一个开发容器,其中包含项目所需的明确定义的工具和运行时堆栈。

    这种设置的主要优势在于消除设置延迟,开发人员可以直接开始编码,无需设置工具和依赖项。 它还具有环境一致性的额外好处。 当多个开发人员共同参与项目时,这确保了每个人都使用 统一的环境。

    图 4**.3中,我们展示了 Visual Studio Code 中开发容器的工作原理。 基本上,Visual Studio Code 解析 devcontainer.json 文件,并创建一个带有 Visual Studio Code 服务器的开发容器。 然后,它会将本地 PC 的工作区文件挂载到容器中,或者将它们克隆到容器中。 在 devcontainer.json 文件中定义的任何额外扩展都会被安装到容器内。 这种设置允许开发人员通过简单连接到 另一个项目来轻松切换不同的项目环境:

图 4.3 – Visual Studio Code 中的开发容器架构

图 4.3 – Visual Studio Code 中的开发容器架构

在了解了可用的各种开发环境选项之后,还需要了解这个阶段的工作流程。 在本章中,我们主要关注预提交阶段的安全性,所以让我们进一步探讨 这一点。

理解预提交阶段中的安全类别

我们将要讨论的 此阶段的两个主要安全类别。 第一个关注开发环境或编码工作空间的有效安全卫生。 第二个旨在减少开发人员在编码过程中常犯的安全错误:

图 4.4 – DevOps 提交前编码阶段的两个主要安全类别

图 4.4 – DevOps 提交前编码阶段的两个主要安全类别

让我们从处理第一个风险类别开始,并采取适当的安全措施。 实施必要的安全措施。

确保开发环境的安全

攻击者 越来越多地针对开发者工具和工作空间(集成开发环境、扩展、SDK 等),无论它们是本地运行还是基于云的,旨在干扰提交前阶段的活动。 通过破坏这些工具,攻击者能够在软件开发过程的早期嵌入恶意代码,目的是影响大量的 下游用户。

但为什么要在提交前阶段针对活动进行防护? 因为这有时可以让它们绕过后续更严格的安全检查。 不幸的是,许多组织往往会在没有进一步审查的情况下信任开发人员提交的代码。 攻击者正是利用这种信任,悄悄地将恶意代码潜入系统。 一个显著的例子是 2019 年的 Solorigate 安全漏洞,黑客在早期阶段悄无声息地加入了 4000 行恶意代码,这使得该代码在提交到 代码库后,得以通过官方批准并数字签名。

Solorigate 漏洞

有关 Solorigate 漏洞的详细 概述和时间线,请参考此 文档: https://www.microsoft.com/en-us/security/blog/2020/12/18/analyzing-solorigate-the-compromised-dll-file-that-started-a-sophisticated-cyberattack-and-how-microsoft-defender-helps-protect/

有些人可能知道这个漏洞作为 Sunburst,这也是被 注入的恶意软件的名称。

这是我们采用 DevOps 工作流时必须发生的思维方式转变之一。 安全措施需要从 软件开发生命周期的早期阶段就开始强大 (SDLC)SDLC)。 仅仅因为代码来自内部源,就信任它是很有风险的。 不应给予隐性信任! 随着你在将安全性融入 DevOps(DevSecOps)的过程中成熟,你需要确保在验证开发者环境的安全性,并且代码经过严格的 安全审查后,才接收代码。

绝不应该因为代码来自内部源而给予隐性信任!

现在,让我们将注意力转向理解一些攻击者进入开发环境的入口点,并解决 这些风险。

风险 1 – IDE 漏洞风险

IDE,就像其他应用程序一样,可能 存在安全漏洞。 一个显著的例子是 CVE-2022-41034,这是 Visual Studio Code 中的一个关键漏洞,攻击者可以通过构造的链接或网站利用该漏洞,接管 Visual Studio Code 用户的工作站! 此漏洞还影响了 GitHub Codespaces、GitHub 的基于 Web 的编辑器( https://github.dev ),以及 Visual Studio Code for the web( https://vscode.dev )。

如果你认为这些问题较少见,你会错的。 自 2022 年 1 月以来,Visual Studio Code 已报告至少六个 远程代码执行RCE)漏洞! 这就是为什么保持本地安装的 IDE 更新至关重要。 像 GitHub Codespaces 这样的托管开发平台会自动处理安全更新,从而减少我们的维护任务。 然而,这并不涵盖插件 或扩展。

Visual Studio Code 漏洞查询

要 查看 Visual Studio Code 公布的漏洞列表,请访问以下 链接: https://www.cvedetails.com/vulnerability-list/vendor_id-26/product_id-50646/Microsoft-Visual-Studio-Code.html

有关 CVE-2022041034 的更多信息,请参考这个 国家标准与技术研究院 (NIST) 链接: https://nvd.nist.gov/vuln/detail/CVE-2022-41034

另外,使用如 GitHub Codespaces 等托管开发环境带来的附加好处之一是可以减少横向移动的风险。 通过将每个开发环境隔离在独立的虚拟机和网络中,Codespaces 确保了更严格的安全性。 虽然它并不能完全防范所有威胁,但潜在的安全漏洞在环境内蔓延的风险 大大降低!

风险 2 – 恶意和存在漏洞的 IDE 扩展

Visual Studio Code 是一款 轻量级 IDE,具有强大的扩展生态系统,支持可扩展性。 无论你在 Visual Studio Code 中想要完成什么任务,可能都有相应的扩展。 截至 2023 年 9 月, Visual Studio Code 市场(https://marketplace.visualstudio.com/vscode)已拥有超过 51,000 多个扩展!

图 4.5 – Visual Studio Code 市场

图 4.5 – Visual Studio Code 市场

对于扩展来说,信任至关重要! Visual Studio Code 中的扩展以与登录用户相同的权限运行。 对于许多开发人员来说,这就是本地管理员角色。 这意味着恶意扩展有可能安装其他应用程序(可能是恶意的),并在本地或远程修改代码。 安装恶意扩展的影响可能 是巨大的!

为了帮助减轻这一风险,开发人员必须能够评估扩展的可信度,以确保他们只安装 受信任的扩展。

因此,开发人员必须在安装扩展之前,能够评估其可信度。 为此,微软实施了多项措施,以确保市场中扩展的安全性:

图 4.6 – Visual Studio Code 市场扩展安全措施

图 4.6 – Visual Studio Code 市场扩展安全措施

在发布 之前,扩展会经过病毒扫描,并进行检查以防止名称抢注,检查内容包括 官方 发布者名称(图 4**.6)。 发布后,扩展会在每次发布者更新时重新进行病毒扫描。 如果社区报告某个扩展为恶意扩展,微软会进行评估。 如果验证通过,扩展将从市场中移除,并添加到 黑名单,使得每次安装时,Visual Studio Code 会自动卸载它(图 4**.6)。

虽然微软的安全措施值得称赞,但并非万无一失。 许多广泛使用的扩展是由社区贡献者创建的,这些贡献者不包括在官方发布者的名称抢注检查中。 一个真正的风险是仿冒流行扩展,诱使开发人员安装它们。 例如,Aqua Security 团队发布的研究就是一个案例。 他们创建了一个仿冒版本的 Prettier,这是一个受欢迎的 Visual Studio Code 扩展,拥有数百万次安装量,并成功发布到了市场。 他们将自己版本的 URL 命名为 pretier-vscode (只有一个 t),与正版 prettier-vscode (有两个 t)微妙不同——见 图 4**.7。发布后的 48 小时内,他们的版本就获得了来自多个国家约一千次开发者的安装。 世界各地的开发者纷纷安装!

图 4.7 – 比较市场中正版扩展和仿冒扩展

图 4.7 – 比较市场中正版扩展和仿冒扩展

不幸的是, 大规模检查的执行可能并不容易。 一些组织可能会在其企业防火墙或终端防火墙上阻止不允许的扩展安装,但这也可能在开发人员认为这会影响他们的工作效率时带来摩擦。 此外,使用 Codespaces 可以有一个独立的批准扩展列表。 然而,除非组织中有 Visual Studio Code 扩展的相关政策,否则没有办法防止某人同步或添加其他扩展,这会带来各种 其他问题。

开发者在安装扩展之前需要接受培训,保持谨慎。 他们应该验证发布者的详细信息,阅读扩展的评论和评分,并检查下载次数。 但是,这将把安全责任交给开发者。 一些实践方法,例如工作区信任,可以提供帮助(我们将在下一节中介绍),但一个更好的系统来展示和控制扩展权限将是理想的。 自 2018 年以来,关于这个问题一直在持续讨论! (https://github.com/microsoft/vscode/issues/52116)。

Aqua Security 研究

想了解更多 有关 Aqua Security 对 Visual Studio Code 扩展风险的研究,请参考以下 文档: https://blog.aquasec.com/can-you-trust-your-vscode-extensions

风险 3 – 使用不受信任的代码

开发者经常 在其集成开发环境(IDE)中利用来自各种来源的开源代码,包括公共或不受信任的代码库。 例如,在研究新功能或解决问题时,他们可能会寻找解决类似问题的开源项目或代码片段,并将其打开在开发环境中以获得启发。 这种做法虽然有益,但也可能带来安全风险。 从不受信任的来源加载代码可能会使开发者面临恶意代码执行和依赖项被篡改等威胁。 这些威胁可能会窃取开发者环境中的访问密钥和令牌。

Visual Studio Code 及其扩展提供了多种执行代码的方式。 虽然这些方法简化了开发过程,但也可能为利用提供了一个入口点。 一个显著的例子是 launch.json 启动配置文件,它位于项目的根文件夹或开发者的工作区设置中。 此文件允许开发者保存调试 设置详细信息:

图 4.8 – 启动配置属性

图 4.8 – 启动配置属性

launch.json中, preLaunchTask 属性定义了在调试开始前执行的任务,而 postDebugTask 属性决定了在调试会话结束后运行的任务(图 4**.8)。 虽然这些属性旨在增强调试体验,但它们可能被恶意行为者篡改。 攻击者可以修改这些任务,执行任意的潜在 有害代码。

注意

有关启动配置及其属性的更多详细信息,请参阅以下文档: https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes

当开发者使用来自不受信任来源的代码,并且这些代码包含一个预设的 launch.json 文件时,风险会放大。 此类配置可能包含执行 恶意代码。

为了减轻这一风险,Visual Studio Code 于 2021 年 5 月(版本 1.57)推出了 工作区信任 功能。 该功能在处理不受信任的代码时增加了一层额外的安全防护。 当开发者打开这类代码时,工作区信任对话框会提示他们为代码指定信任级别。 如果代码被判定为不可信,Visual Studio Code 将进入 受限模式

图 4.9 – 工作区信任提示

图 4.9 – 工作区信任提示

此模式 通过禁用或限制某些功能来防止潜在的有害 操作,包括任务执行、调试、工作区设置修改和特权扩展(图 4**.9)。 信任加载代码的责任最终由开发者承担。 因此,开发者必须接受持续的安全培训,确保他们能做出明智的决定,选择信任哪些代码。

要编辑工作区信任设置,我们可以随时通过按 Ctrl + Shift + P 打开命令面板并输入 Workspaces: Manage Workspace Trust

要完全禁用工作区信任,我们可以通过以下方式修改 Visual Studio Code 设置 security.workspace.trust.enabled: false

Figure 4.10 – Workspace Trust Visual Studio Code setting

图 4.10 – 工作区信任 Visual Studio Code 设置

让我们回顾一下 一个较少见但重大的开发环境风险——被篡改的 IDE 源代码。

风险 4 – 被篡改的 IDE 源代码

也存在 IDE 源代码被篡改的风险! 虽然这种情况不常见,但确实会发生。 想象一下,如果用于软件开发的工具本身被篡改了,会带来什么影响。 这不仅仅是一个假设的风险。 最近的一个现实事件涉及一位名为 RyotaK的安全研究员,他发现并利用了 GitHub 上 Visual Studio Code 仓库中的一个漏洞。 这个漏洞是由代码注入缺陷和一个 写错的 正则表达式(regex) 以及 持续集成(CI) 脚本中的问题所导致的,该脚本位于 Visual Studio Code 官方的 GitHub 仓库。 利用这一漏洞,他获得了写入该仓库源代码的权限。 这意味着他有可能修改全球开发者依赖的代码,影响 他们的工作。

如果 IDE 的源代码被恶意篡改且未被发现,可能导致篡改过的软件工具广泛传播,从而感染大量项目,注入恶意代码或后门。 这不仅会危及单个项目,甚至可能影响整个基础设施,特别是如果广泛采用的工具 受到影响的话。

要了解更多 RyotaK 的发现及其安全漏洞带来的影响,可以查看他的博客文章: https://blog.ryotak.net/post/vscode-write-access。博客是日文的,如果你不熟悉该语言,可能需要借助翻译服务,如 Google 翻译。

关于加强开发环境安全性的更多思考

根据我们的经验, 我们发现,某些我们讨论过的安全加固实践是广为人知的,在某些情况下, 常识,但它们在许多环境中仍未得到实施和监控。 这很难解决。 当人们知道该做什么 没有付诸实践时,仅仅提供工具或一些通用的安全培训并不能解决问题。 这些问题根深蒂固。 解决这个问题通常需要在组织内进行某种形式的倡导和推广——这是一项艰苦的工作,需要 文化变革。

这些环境硬化实践必须无缝集成,才能得以实施。 集成开发环境(IDE)必须默认配置为自动更新,插件也必须尽可能默认配置为自动更新,或者至少组织应该有明确定义的端点管理流程,包括开发工具和插件。 如果可能的话,应该移除或 强烈不建议调整这些安全默认设置。

这是一项艰巨的任务,因为开发人员有时可能需要为了性能或向后兼容性禁用某些功能。 我们不能采取全有或全无的方法,因为有些开发人员可能出于正当理由反对在其环境中使用这些安全默认设置。 我们应该理解并包容那些有效的例外,并采取适当的缓解措施。 记住,安全措施必须是合作性的,才能在 DevSecOps 文化中有效。

解决常见的开发安全问题

现代软件在开发过程中引入风险的方式有很多种。 现代软件应用大多数是由内部开发人员编写的专有代码和第三方组件的混合,这些组件可能来自开源仓库、 开放源代码 ,甚至是商业授权代码,虽然不常见,但确实存在(图 4**.11):

图 4.11 – 现代软件组成

图 4.11 – 现代软件组成

开放源代码软件

源代码可用软件意味着该软件的源代码是公开可供查看的。 然而,它并不一定赋予和 开源软件 (OSS) 相同的自由。 虽然 你可以查看代码,但可能会有关于如何使用、修改或分发它的限制。 可以将其视为一种 看看但别动手 的共享软件代码方式。

这些组件中的任何一个都可能给软件带来风险! 我们的 内部代码第三方代码和开源包 也可能存在漏洞,并且还有 暴露的密钥,这可能是一个大问题。 识别并解决这些风险应从提交前阶段开始。 如果我们在 DevOps 周期的最后阶段发现安全问题,可能会导致功能发布的延迟, 甚至更糟,变成技术债务,随着时间的推移变得越来越难以修复。 考虑到这一点,我们来分解在提交前阶段需要优先处理的前三大风险类别,从我们 内部代码中的安全问题开始。

风险 1 - 解决内部代码漏洞风险

开发者是 人类,在编写代码时可能会犯安全错误。 例如,开发者可能忘记在使用用户输入进行数据库查询之前对其进行清理,从而为 SQL 注入攻击打开了大门。 另一个例子是,开发者可能忽略了实施适当的会话超时,导致应用程序容易受到会话劫持。 在 最近的 Storm-0558 微软泄露事件中,发现微软 365 邮件系统的开发者假设他们实现的某些库 已经完全验证了所需的范围,但他们没有添加必要的发行者/范围验证。 这一疏忽放大了当签名密钥 被泄露时事件的影响。

微软安全响应中心(MSRC)对 STORM-0558 泄露事件的分析

要查看 Storm-0558 漏洞的完整分析,请参考以下 文档: https://msrc.microsoft.com/blog/2023/09/results-of-major-technical-investigations-for-storm-0558-key-acquisition/

内部代码中的漏洞根本原因是多样的,因此没有单一的解决办法。 解决这一挑战需要一个全面的策略,融合文化变革和技术措施。 我们希望确保每次开发人员编写代码时,他们都能拥有所需的知识和工具,以编写最安全的代码。 解决这一风险的基础步骤是为开发人员提供安全编码培训,但尽管经过最佳的培训努力,安全疏忽还是不可避免。 为了 增加额外的缓解层,集成一个 静态应用程序安全测试 (SAST) 解决方案,在 DevOps 的提交前阶段进行测试可能会 带来好处。

理解 SAST 工具的工作原理

SAST 工具 分析应用程序源代码、字节码或二进制代码,以在不运行程序的情况下识别漏洞。 因为它们可以自动化操作,所以比传统的手动审查更快。 随着准确性的提高,它们正在成为优于手动代码审查的首选,尤其是在已经采纳 DevOps 模式的组织中。 随着准确性提高,它们正成为比手动代码审查更受青睐的选择,尤其是在已经采用 DevOps 模式的组织中。 SAST 工具使用多种方法来实现这一目标,每种方法都有其优缺点。 和局限性。

一种常见的 方法是 语法和语义分析。在此方法中,工具将代码分解以理解其结构和模式。 例如,在用户输入直接添加到 SQL 查询中的情况中,这种方法会将该模式识别为潜在的 SQL 注入漏洞。 它通过解析代码并构建抽象表示来做到这一点,像是 抽象语法树 (AST),以 识别此类模式。 虽然这种方法可以发现许多漏洞,但它也可能会标记出一些并不是真正问题的内容(假阳性)。 对于大型 代码库,它也可能是资源密集型且运行缓慢的。

另一种方法 是 数据流分析,它跟踪数据如何通过程序流动,并分析数据是否被不安全地处理。 它使用启发式方法和预定义规则来追踪数据流动并识别不安全处理;例如,如果一个网页应用接受用户在表单中输入,并在没有首先清理数据的情况下直接在网页上显示。 通过绘制数据从输入点到其在网页上的目的地的旅程,数据流分析可以识别此类行为作为 潜在的 跨站脚本 (XSS) 漏洞并标记它。 这种方法在识别与数据处理相关的漏洞方面非常有效,如 SQL 注入或 XSS。 它不适用于检测与数据流不直接相关的逻辑漏洞,如身份验证绕过。 如果工具未完全理解数据的生命周期,它可能还会产生误报。

污点分析 是 数据流分析的一种专业形式。 它跟踪用户控制的输入,以查看是否在没有验证或净化的情况下处理,可能导致漏洞。 例如,在聊天应用中,用户发送的消息如果未经检查或净化即显示给其他用户,污点分析将标记此类行为为潜在的存储型跨站脚本(XSS)漏洞,攻击者的消息可能包含恶意脚本在另一个用户的浏览器上运行。 它对于发现与用户输入相关的漏洞非常有效,比如注入攻击。 如果工具无法识别所有净化方法,则可能产生误报。 它通常使用启发式方法和 基于规则的检查。

SAST 工具采用的另一种方法 是 true/false。例如,考虑一个电子商务网站,该网站应在处理购买前检查用户是否已登录,这种方法将识别代码中是否存在跳过此检查的方式,从而导致潜在的未经授权访问。 这种方法非常适用于识别诸如身份验证绕过或缺失安全控制等逻辑漏洞。 但它在识别与数据相关的漏洞,如 SQL 注入 或 XSS 时效果较差。

配置审查 是 SAST 工具用于分析的另一种方法。 它的工作原理非常直接。 它通过分析配置文件和设置,以确保安全的默认值和设置。 它通过将配置与最佳实践或已知的安全配置进行比较来实现这一点。 例如,如果应用程序配置设置为显示详细的错误信息,配置审查将标记此为信息泄露漏洞,因为攻击者可能通过这些信息获取有价值的线索。 这种方法非常适合捕捉那些在手动审查中可能被忽视的不安全应用设置。 它不会检测到 代码逻辑中的安全问题。

大多数 SAST 工具采用多种方法相结合的方式,提供可能漏洞的全面视角。 它们旨在获得精确的结果,考虑到不同编程语言和框架的特性。 此外,这些工具通常会有预设的规则或查询,用于我们提到的不同分析技术。 有些工具甚至允许开发人员/安全团队创建自定义规则,以便在 代码中发现更独特的不安全编码模式。

SAST 工具的挑战

SAST 工具有 优点,但也有局限性。 一个大局限性是它们在不运行代码的情况下进行分析,因此 它们无法完全掌握应用程序的行为上下文,这可能导致很多误报。 误报是指工具错误地识别出 安全问题。

以应用程序开发人员编写前端逻辑为例。 他们可能没有在代码中实现用户输入验证和清理,因为这部分工作由后端代码处理,而后端代码可能位于一个单独的代码库中。 分析代码的 SAST 工具无法获取到这个上下文信息,因此它会将缺失的实现标记为 漏洞。

一些 SAST 工具 使用简单的启发式方法或仅仅寻找基本模式来识别漏洞。 像这些工具在分析复杂代码结构时会遇到困难。 仅仅因为一段代码符合一个简单的模式,并不意味着它就有漏洞。 这就是 为什么在使用这些工具之前进行测试非常重要。 有些工具在避免误报方面比其他工具更为优秀。 事实上,有些工具的误报率可能高达 80%! 这会让开发人员感到沮丧。 这些工具本应帮助简化工作,但开发人员却不得不花时间弄清楚哪些警告是真实的,哪些不是。 这可能会让他们想跳过使用 这些工具。

此外,一些工具仅指出已识别的漏洞,但没有清楚地解释为什么会被标记。 其他工具则更善于提供明确的原因,甚至提供自动修复来纠正 安全问题。

在我们看来,这些挑战并不会削弱 SAST 工具所带来的好处。 我们建议安全专家和开发人员共同合作,微调所选 SAST 工具的配置、查询和模式,并通过集成反馈逐步减少误报。 将其与手动审查相结合也是一个好主意,我们将在 第五章 中进一步讲解 这一部分内容。

理解 SAST 在预提交阶段的集成点

在 DevOps 的 pre-commit 阶段正确地集成 SAST 可以在应用程序代码中检测到关键的漏洞, 这些漏洞在修复时最为简单且成本最低,尤其是在开发人员仍专注于任务时。 这种集成可以通过 IDE 安全插件或作为 pre-commit hooks进行。 每种方法都有其独特的优点。 IDE 插件集成 为开发人员提供即时的安全问题反馈, 在他们编写代码时。 一些插件甚至用波浪线突出显示安全问题,类似于语法错误指示,如 图 4**.12所示。 这种即时反馈就像是 及时JIT)安全编程培训, 能够实时提醒开发人员潜在的安全漏洞。 然而,一个限制是并非所有的 SAST 提供商都提供 这样的插件:

图 4.12 – IDE 扩展(Checkov)在代码编写时标记安全问题的示例

图 4.12 – IDE 扩展(Checkov)在代码编写时标记安全问题的示例

要 理解什么是 pre-commit hooks,我们首先需要了解每个 Git 仓库的 .git/hooks 目录。 默认情况下,Git 在此目录中提供示例 hooks,但它们是未激活的(它们的扩展名为 .``sample )。

Git hooks 有多种类型,例如 pre-commit、post-commit、pre-push、post-receive 等等。 每种类型对应 Git 工作流中的不同阶段。 pre-commit hook 是众多 Git hooks 中的一种。 它会在提交记录之前触发,使我们能够对即将提交的代码进行自动化检查(图 4**.13):

图 4.13 – Pre-commit hooks 在提交记录之前被触发

图 4.13 – Pre-commit hooks 在提交记录之前被触发

Pre-commit 钩子是多功能的,可以运行各种脚本。 任何可以从命令行执行的脚本都可以用作 pre-commit 钩子。 鉴于大多数 SAST 工具作为命令行工具可用,将它们作为 pre-commit 钩子来进行自动化代码 评估变得非常简单。 如果 pre-commit 钩子脚本以非零状态退出,则会中止提交,给开发者一个在重新尝试提交操作之前修复问题的机会。

Git 默认设置的一个挑战是钩子是每个仓库本地的。 然而,团队通常希望在所有开发者之间共享和强制一致的钩子。 这就是像 pre-commit 框架这样的工具派上用场的地方,它帮助管理共享配置并 确保一致性。

pre-commit 框架与 pre-commit 钩子

术语 pre-commit 钩子 有时可能会与一个名为 pre-commit 框架的工具混淆。正如我们之前讨论的,pre-commit 钩子是一种特定类型的 Git 钩子,它会在提交记录之前触发。 pre-commit 框架是一个独立的工具,旨在简化设置和管理 pre-commit 钩子的过程。 它不需要手动编写和管理 .git/hooks 目录中的脚本,pre-commit 框架使开发者能够利用各种现有钩子,并轻松地将它们集成到仓库中。 使用 pre-commit 框架,我们在 .pre-commit-config.yaml 文件中定义所需的钩子,工具会负责将它们安装到适当的 Git 钩子目录中。

尽管 pre-commit 钩子非常宝贵,但有时开发者可能需要绕过它们。 这可能是由于错误的假阳性警告或有充分理由覆盖钩子。 像 git commit --no-verify 这样的命令允许绕过这些钩子,但它们应该谨慎使用。

与 pre-commit 阶段集成的 SAST 工具

多个 SAST 提供商 在 DevOps 的 pre-commit 阶段提供集成。 其中一些提供商完全是开源的,另一些则是纯商业性质的,少数提供了基础的开源版本,用户可以选择升级到功能齐全的商业版本。 图 4**.14 展示了常见的产品概览:

图 4.14 – 流行的 SAST 工具及其在 pre-commit 阶段的集成方式

图 4.14 – 流行的 SAST 工具及其在 pre-commit 阶段的集成方式

本章稍后 我们将提供选择合适工具的建议。 现在,本节旨在介绍一些流行的 可用选项。

那么,AI 配对编程工具呢?

如 GitHub Copilot、Tabnine 和 Amazon CodeWhisperer 等 AI 工具将 生成式 AIGenAI)的力量带入了开发团队。 毫无疑问,它们帮助开发者更快地编写代码,并且让他们对自己的工作感到更加满意。 最近的 GitHub 研究发现,使用这些工具的开发者比未使用工具的开发者工作速度快 55%。

来源 – GitHub Copilot 对开发者生产力影响的研究

若想更深入了解 GitHub 的研究,请查看此 文档: https://github.blog/2022-09-07-research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/

然而,人们对这些工具生成的代码的安全性表示担忧。 以 GitHub Copilot 为例,它基于一个 OpenAI 大语言模型LLM)。 这个模型是通过从公开的资源中获取代码进行训练的,包括 GitHub 上的开源代码。 这些代码来源中有些因使用过时的 API 和实施不安全的编码模式而臭名昭著。 因此,AI 可能会建议不安全的 代码片段。

研究 表明,许多开发者认为 AI 生成的代码质量很高,但研究却得出了相反的结论。 最近的一项研究对 ChatGPT(另一个 OpenAI 工具)在 21 个编程任务中的表现进行了评估。 它只生成了 5 个安全的程序,而其他 16 个程序在评估的漏洞方面存在安全问题。 例如,在被要求用 C++创建 FTP 服务器时,ChatGPT 的代码缺乏输入验证,容易受到注入攻击。 然而,在进一步的提示下,ChatGPT 确实修正了它的错误。 这表明,AI 生成代码的质量和安全性取决于开发者如何精确地提供经过精心设计的提示。

我们强烈建议那些希望使用这些工具的公司,应优先培训他们的开发者提供清晰、安全特定的提示。 你可以称之为 安全代码提示 工程培训

进一步阅读 – ChatGPT 生成的代码有多安全?

有关引用研究的更多详细信息,请查看来自加拿大魁北克大学的研究人员的论文: https://arxiv.org/pdf/2304.09655v1.pdf

风险 2 – 开源组件风险

开源软件包 提供 灵活性、成本节约和快速开发的优势。 然而,它们也可能给软件项目引入风险。 这些风险可能来源于 安全漏洞软件包被篡改,或 混淆攻击

当开发者将一个软件包添加到项目中时,他们也承担了该软件包的安全风险。 尽管许多开源项目维护者优先考虑安全性,但许可条款并没有要求他们确保安全——这并非他们必须履行的责任。 让我们讨论一些这些风险,以及如何在预提交阶段应对它们,从 安全漏洞 开始:

在预提交阶段解决已知开源软件漏洞风险

已知漏洞 是 开源软件代码中的 安全漏洞(可以将其看作是船只使用组件中意外产生的孔洞)。当安全研究人员识别出这些漏洞时,它们会被负责任地披露,并以 常见漏洞与暴露 (CVE)的形式公开记录,如 MITRE 的 CVE 列表(https://cve.mitre.org)和 国家漏洞数据库 (NVD)(https://nvd.nist.gov)。 这些 数据库可以被安全工具搜索,用以识别特定版本的开源软件包中的已知漏洞。 虽然开发人员选择的包中的直接漏洞令人担忧,但还有另一个隐藏的风险:传递性依赖。 这些是作为所选开源软件包的依赖项自动包含的包(图 4.15**.)。 Endor Labs 研究团队最近的一项研究发现,95%的安全问题出现在这些 传递性依赖中:

图 4.15 – 开源软件包依赖关系

图 4.15 – 开源软件包依赖关系

Endor Labs 的《依赖管理现状》报告

你可以参考此文档访问 报告: https://www.endorlabs.com/state-of-dependency-management#

在提交前阶段解决 OSS 已知漏洞 风险的基础步骤是 为开发人员提供有关如何为其项目选择安全的开源软件包的知识。一些公司正在尝试新的方法来帮助开发人员做出这些选择。 例如,一些公司已经开始尝试使用 LLMs 和 GenAI 来简化这个过程。 因此,开发人员不再需要强制阅读关于如何选择安全软件包的长篇指南,他们只需问一些问题,比如 是否有比 OpenSSL 库更安全的替代品?,就会得到解释的回答。 一种名为 DroidGPT**的新工具,由 Endor Labs 制作,正试图实现这一目标。 它旨在帮助开发人员更轻松更快速地为其项目选择安全的开源软件包。 但它仍然是新的(并且处于私人预览阶段),我们尚不清楚它在实际情况中的表现如何。

在提交前阶段处理开源软件已知漏洞的另一种常见方法是 集成 软件组成分析 (SCA) 工具,类似于我们描述的 SAST 工具集成。 这些工具检查应用程序中使用的开源组件和第三方库,以识别已知漏洞。 它们通过将这些组件与已知漏洞的数据库进行比较来运作。

SCA 工具面临的挑战

我们看到组织常见的一个严重错误是将 DevSecOps 的实施简化为工具采用。 有效实施 DevSecOps 不仅仅是部署 SCA 工具;它需要仔细的规划和对工具功能和限制的深刻理解。 为了理解项目中包含的依赖关系,大多数 SCA 工具会扫描项目的包管理文件,解析文件以提取依赖信息,并基于列出的依赖关系进行漏洞分析。 例如,当处理使用 NuGet 包管理器的 .NET Core 应用程序时,SCA 工具将分析 .csproj 文件以提取依赖数据,并根据 这些依赖关系进行漏洞评估。

然而,仅仅依赖包管理器数据来识别依赖关系可能会导致盲点。 包管理文件中声明的依赖项与代码中实际使用的存在时常不匹配。 有些依赖项可能在代码中声明但实际上未被使用,被称为未使用依赖项。 有些依赖项可能在代码中使用但未在包管理器文件中列出,称为虚假依赖项。

这种差异 可能会产生实际影响。 首先,警告未使用依赖项中的漏洞可能会导致大量不必要的警报,增加了开发人员的认知负担,他们本已时间紧迫。 另一方面,忽视扫描虚假依赖项可能会引入显著的安全盲点,这更加危险。

警告未使用软件组件(未使用依赖项)中的漏洞增加了噪音,这增加了已经在紧张进度下工作的开发人员的认知负担。 未能识别和扫描虚假依赖项会导致盲点,这更加危险。

通过识别这些挑战,更成熟的 SCA 工具已经发展。 这些工具不仅仅关注包管理器文件,还将这些数据与直接代码分析结合起来,提供更全面的评估。 我们的目标不是为特定工具进行宣传,而是认为团队需要意识到这些挑战,并将其纳入其 DevSecOps 策略中。

在提交前解决开源软件包妥协的风险

eslint 包。 然后,插入的代码从调用该包的人们的系统中窃取了 Node Package Manager(npm)凭据。

攻击者不仅可以修改主包,还可以将恶意包添加为依赖项。 在 EventStream 攻击中,恶意包 flatmap-stream 被添加到 event-stream 包中。 该恶意包含有一个加密负载,专门设计用于从 Copay 应用程序中窃取比特币。

ESLint 和 EventStream 攻击

有关 ESLint 攻击的事后分析,请参考这个 链接: https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes/

有关 Snyk 对 EventStream 攻击的事后分析,请参考这个 链接: https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/

防止 包被篡改需要我们建立一个安全的包管理过程。 这包括确保开发者只能从可信的、知名的源或官方仓库下载包,并通过校验和或类似技术验证这些包的完整性,以确保它们没有被篡改。 保持关注你使用的包的安全警报也是一种防护措施。 像 GitHub 这样的平台经常发布安全公告。 以最小权限运行包可以进一步减少被篡改包可能造成的损害。 我们将在本书的 第六章 中进一步讨论安全依赖管理,敬请期待。

解决预提交阶段的依赖混淆攻击

依赖混淆攻击 是一种欺骗性战术,攻击者将恶意包命名为与真实包类似的名称,并将其上传到公共包仓库。 目标是欺骗开发者下载并集成这些恶意包,认为它们是合法包,从而将漏洞或后门引入他们的软件项目中。 包名称中的一个简单拼写错误可能会导致开发者下载到恶意代码,而这些代码最终会被分发给应用程序用户。 想象一下,你以为你正在绑紧救生衣,实际上却绑上了 一块重物。

在最近的一起事件中,Checkmarx、JFrog 和 Sonatype 的研究人员追踪到一个名为 RED-LILI 的威胁行为者,该行为者通过恶意的 npm 包 以攻击 Azure 开发者。该小组发布了恶意的 Azure SDK 包,但将 @azure 的作用域替换为 azure-,并且在某些情况下,他们完全移除了作用域,仅发布了一个与原名相同的包(图 4**.16):

图 4.16 – RED-LILI 组发布的恶意 npm 软件包

图 4.16 – RED-LILI 组发布的恶意 npm 软件包

这个组别的独特之处在于他们的复杂性。 他们自动化了整个过程,从 npm 帐户创建到恶意软件包发布,甚至绕过了 一次性密码OTP)验证。 此外,他们并非使用单一帐户发布多个恶意软件包,而是为每个软件包创建了一个独特的帐户,这使得检测和清理工作更加具有挑战性。 仅在 1 周内,他们发布了大约 800 这样的软件包!

RED-LILI 攻击

阅读更多 关于供应链威胁行为者 RED-LILI,请参阅此 页面: https://github.com/checkmarx/red-lili

依赖混淆攻击也可以采取其他形式。 例如,目标可能是组织内使用的私有包,而不是开源软件包。 这里有一个例子 :

假设有一家公司名为 TechCorp ,它为内部应用程序使用一个名为 SecureLogin 的私有包。 这个包的版本是 1.5 ,并且不对公众开放。 有一个攻击者通过某些泄露的文档或内部信息得知 SecureLogin 的信息。 他们接着创建了一个恶意包,也命名为 SecureLogin,但是给它赋予了一个更高的版本号——例如, 2.0。这个恶意包包含了当执行时会将敏感用户数据发送到攻击者服务器的代码。 攻击者将这个恶意的 SecureLogin 版本 2.0 上传到公共包仓库。 现在,当 TechCorp 的开发者获取他们的包更新时,包管理器看到 更新的 版本 2.0SecureLogin ,并可能会自动下载并集成它,认为它是来自自己团队的合法更新(标记为 图 4 中的 3 .17*)。 一旦集成,恶意代码就会激活,危害 公司的应用程序,并将敏感数据发送给 攻击者:

Figure 4.17 – 依赖混淆攻击目标:私有包

图 4.17 – 依赖混淆攻击目标:私有包

这并不是一种异常攻击。 Alex Birsan 记录了他是如何进行这种类型的依赖混淆攻击,突破苹果和微软等大公司的防线的,详情请见: https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610

在此次攻击中,他扫描了目标组织的公共仓库,特别寻找诸如 package.json这样的包管理文件。通过这些文件,他识别出了组织内部使用的、但未在公共包仓库中提供的私有包名称。 然后,他在公共仓库中创建了相同包名的更高版本,并等待它们被 下载。

为了应对依赖混淆的风险,我们需要一个明确的计划。 首先,开发人员应该接受安全开发培训,重点强调版本锁定的重要性,并教会他们识别依赖混淆的迹象。 工具如 npmpackage-lock.json 或 Python 的 Pipfile.lock 可以帮助确保安装正确的包版本。 如果使用内部包,最好避免从公共源下载。 在考虑新的依赖项时,仔细审查其历史、维护者的可信度、贡献过程以及其 最近的变更 是有益的。 在包选择和相关安全实践方面的谨慎应成为任何安全培训策略的核心组成部分。 所有这些都是全面依赖管理策略的一部分,我们将在本书的 第六章 中讨论。

风险 3 – 曝露的机密风险

为了增强 功能,现代应用程序常常与各种服务进行交互,如数据库、云存储和第三方 API。 因此,开发人员在编码过程中经常处理诸如认证令牌、密码和 API 密钥等机密,以便启用和测试 这些集成。

一个常见的错误是无意中将这些机密提交到版本控制系统(VCS),例如 Git。 一旦推送,尤其是推送到公共仓库,这些机密就会被恶意行为者访问,可能导致数据泄露或未经授权的访问。 这在私人仓库中也是一个风险,内部威胁的危险性与外部威胁一样大。 请记住,私人仓库未来可能会变为公开。 一个近期的例子是 Microsoft AI 研究人员在其公共 GitHub 仓库中意外泄露了 Azure Storage 共享访问签名 (SAS)令牌。 这次泄露导致 38 TB 私人数据泄露。

注意 – Microsoft AI GitHub 仓库泄露分析

要了解更多关于此次数据泄露的信息,请参阅此 文档: https://www.wiz.io/blog/38-terabytes-of-private-data-accidentally-exposed-by-microsoft-ai-researchers

在代码中管理机密的挑战是多方面的。 这不仅仅是避免将它们提交,还包括安全地存储、访问和轮换它们。 需要一种整体的方法来应对这一风险。 应实施清晰的机密管理流程,并且开发团队应接受在 Azure 生态系统中进行机密管理的培训。 我们将在本书后面讨论如何使用 Azure Key Vault 进行 DevOps 过程中的机密管理。 本书后续将详细讲解。

在提交前 阶段,可以集成类似于 SAST 工具的机密扫描工具,以检测代码库中的机密或敏感信息。 它们扫描代码,寻找与常见机密格式匹配的模式,如 Azure 服务密钥或 连接字符串。

这些工具通过使用模式匹配、熵检查,有时还会使用机器学习来识别代码中的潜在机密。 例如,看起来像 Azure 服务密钥的字符串将会被标记出来。 它们可以无缝集成到提交前阶段,类似于 SAST 工具,以便在代码提交到 源代码管理系统之前捕获潜在的泄露。

选择合适的以开发者为中心的安全工具

最好的工具能让工程师更轻松地完成工作,或让工作变得更加愉快。

工具在实施 DevSecOps 中扮演着 至关重要的角色。 选择适合提交前阶段的工具应该是一个由所有软件开发过程中的团队共同决定的过程。 为了简化管理并在大规模推广时更为高效,建议采用那些提供平台优先、以开发者为中心的工具。 由于技术栈支持限制或 预算问题,这可能并不总是可行的。

以开发者为中心的安全工具是指那些在软件开发过程中优先考虑开发者需求的安全工具和解决方案。 这些工具类别专注于为开发者提供必要的功能,从一开始就帮助他们开发安全的应用程序,并能与标准的 开发工作流良好集成。

开发者通常倾向于选择能够提升生产力、让工作更轻松愉快的工具。 2020 年 Stack Overflow 和 JetBrains 的调查显示,开发者重视那些易于使用、与环境良好集成,并支持其首选语言和框架的工具。 与他们合作,选择最适合的工具。 选择不被使用的工具是毫无意义的。

除了满足开发者需求外,这一阶段的工具还应促进所有利益相关者之间的协作。 这确保每个人都参与到集体的安全责任中。 例如,工具应允许团队之间轻松共享安全发现 。 如果一个团队创建了一个出色的查询,用于检测易受攻击的编码模式,你的工具应允许轻松将该自定义查询推广到组织中的其他团队。 。

选择工具时应重点考虑那些能提供 有用可操作 反馈的工具。 许多工具可能会提供信息,但如果信息不可操作,则价值不大。 可操作的反馈至关重要,因为它可以教育开发者了解安全警告背后的原因,并告诉他们如何避免未来的类似问题。

动手练习 1 – 在 IDE 上执行代码审查、依赖检查和秘密扫描

要完成 这个动手练习,你需要先完成前一章节中的动手练习(动手练习 1 – 配置实验室虚拟机),我们在其中配置了实验室虚拟机。 在这个练习中,我们将进行 代码审查、检查依赖关系漏洞,并扫描代码中的秘密信息。 这是实现安全左移的重要阶段,因为我们可以在提交 代码之前识别并修复许多漏洞。

在这个练习中,我们将使用eShopOnWeb应用程序。该应用程序与 eShopOnContainers 应用程序相关,后者专注于容器和微服务。 另一方面,eShopOnWeb 则专注于传统的 Web 应用程序开发。 图 4**.18 展示了 eShopOnContainers 应用程序的参考架构:

图 4.18 – eShopOnContainers 参考架构(来源: https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/introduce-eshoponcontainers-reference-app)

图 4.18 – eShopOnContainers 参考架构(来源: https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/introduce-eshoponcontainers-reference-app)

以下是我们将在 本次练习中完成的任务:

  • 任务 1:使用 Azure Bastion 连接到实验室虚拟机

  • 任务 2:在 Visual Studio Code 上配置 Snyk

  • eShopOnWeb 到你的 Visual Studio Code 工作空间

任务 1 – 使用 Azure Bastion 连接到实验室虚拟机

此任务的目标是 使用 Bastion 服务 建立与 实验室虚拟机的连接:

  1. 在 Azure 门户主页的搜索框中,输入 DevSecOps-LabVM 并在出现时选择 DevSecOps-LabVM 虚拟机:

图 4.19 – 选择 DevSecOps-LabVM 虚拟机

图 4.19 – 选择 DevSecOps-LabVM 虚拟机

  1. DevSecOps-LabVM 窗口中,在 连接 部分,点击 连接 | 前往 Bastion

图 4.20 – 选择使用 Bastion 连接虚拟机的选项

图 4.20 – 选择使用 Bastion 连接虚拟机的选项

  1. azureuser

  2. 身份验证 类型密码

  3. 密码:输入你在 模板部署时指定的密码

  4. 在新浏览器中打开 标签:已选择

  5. 点击 连接

图 4.21 – 配置虚拟机凭证并启动连接到虚拟机

图 4.21 – 配置虚拟机凭证并启动连接到虚拟机

  1. 如果出现提示,启用 弹出窗口 以确保连接成功。 另外,如果提示,点击允许访问剪贴板 :

现在你已经可以访问 实验室虚拟机,让我们在 IDE 中进行代码审查、依赖检查、秘密扫描和 软件物料清单 (SBOM) 生成。

任务 2 – 在 Visual Studio Code 中配置 Snyk

在本任务中,我们将 在 Visual Studio Code 中设置扫描工具。 我们 将使用 Snyk(snyk.io):

  1. 在实验室虚拟机的桌面上,你会找到 Visual Studio Code。 这个程序已经为你预先安装好。 请打开 Visual Studio Code。

  2. 在 IDE 中,你可以使用多种开源和商业工具进行代码扫描、依赖检查、秘密扫描和 SBOM 生成。 选择源代码分析工具取决于多个因素,包括使用的编程语言、工具是否开源或 商业化、工具的准确性、是否作为扩展支持常用的 IDE 等等。 因此,了解哪些工具适合你的使用场景,并在继续使用某个工具之前进行适当的 概念验证 (POC) 非常重要。 在使用特定工具之前,进行充分验证。 以下是 全球开源应用程序安全项目 (OWASP)(https://owasp.org/www-community/Source_Code_Analysis_Tools)列出了市场上可用的一些工具、支持的平台和扫描的编程语言。 对于这个练习,我们将 使用 Snyk,它可以扫描开源安全性、代码安全性以及 基础设施即代码 (IaC) 安全性。

  3. 我们通过在搜索栏中输入 Snyk 来安装 Snyk Visual Studio Code 扩展。 点击搜索结果中的第一个 Snyk 实例,如下图所示,然后 点击 安装

图 4.22 – 安装 Snyk Visual Studio Code 扩展

图 4.22 – 安装 Snyk Visual Studio Code 扩展

  1. 接下来,让我们配置 Snyk Visual Studio Code 扩展。 我们从扩展设置开始配置 ,可以通过点击左侧的 Snyk 图标并点击 设置图标来访问,接着选择 扩展设置

图 4.23 – Snyk 扩展设置

图 4.23 – Snyk 扩展设置

  1. 现在,让我们按以下步骤配置 Synk 扩展 :

    • --all-projects

    • 高级:自动依赖管理 已选中

    • 高级自动扫描开源安全 已选中:

图 4.24 – Snyk 高级扩展设置

图 4.24 – Snyk 高级扩展设置

  1. 勾选 以下 Snyk 特性: 代码质量代码安全基础设施即代码开源安全

图 4.25 – Snyk 特性扩展设置

图 4.25 – Snyk 特性扩展设置

  1. 最后,确保 Snyk: 扫描模式 已设置为 自动 并且 Snyk: 严重性 已选中 用于 严重,如下面的截图所示:

图 4.26 – Snyk 扫描和严重性扩展设置

图 4.26 – Snyk 扫描和严重性扩展设置

  1. 为了让 Synk 扫描你的项目,你必须使用 Snyk API 密钥进行身份验证。 点击 Snyk 图标,然后选择 信任工作区 并连接

图 4.27 – 设置 Snyk 代码扩展身份验证

图 4.27 – 设置 Snyk 代码扩展身份验证

  1. 点击 信任工作区并连接 将带你进入 Snyk 网页应用程序 进行身份验证。 点击 身份验证

图 4.28 – Snyk 网页应用程序身份验证

图 4.28 – Snyk 网页应用程序身份验证

  1. 认证成功后,你将收到如下确认信息。 关闭浏览器并返回 Visual Studio Code:

图 4.29 – Snyk 认证成功

图 4.29 – Snyk 认证成功

现在我们可以 继续进行 任务 3 ,在成功配置 Snyk 扩展后。

Visual Studio Code 扩展认证

请注意,如果上述步骤无法成功配置你的 Snyk 扩展,你可能需要手动设置 token,方法是 按照以下步骤操作:

任务 3 – 将 eShopOnWeb 导入到你的 Visual Studio Code 工作区

在此任务中,我们将 导入我们将要使用的应用程序:

  1. 我们将 审查 eShopOnWeb 应用程序,检查 Visual Studio Code 编辑器中的安全漏洞。 导航到 EXPLORER 在 Visual Studio Code 编辑器的左侧窗格中,然后点击 克隆仓库

图 4.30 – 克隆仓库

图 4.30 – 克隆仓库

  1. 粘贴 eShopOnWeb 仓库(https://github.com/PacktPublishing/eShopOnWeb_DevSecOps),然后选择 从 URL 克隆 https://github.com/PacktPublishing/eShopOnWeb_DevSecOps 选项:

图 4.31 – 从 GitHub 克隆

图 4.31 – 从 GitHub 克隆

  1. 你需要选择一个文件夹作为仓库的目标。 点击 eShop,然后点击 选择为 仓库目标

图 4.32 – 选择文件夹作为仓库目标

图 4.32 – 选择文件夹作为仓库目标

  1. 一个弹出窗口 将 出现在 Visual Studio Code 的右下角,显示克隆状态。 完成后,你将被要求打开克隆的仓库; 点击 打开

图 4.33 – 打开克隆的仓库

图 4.33 – 打开克隆的仓库

  1. 你将被问到是否信任文件夹中的文件作者。 选择 是,我信任 作者

图 4.34 – 信任文件的作者

图 4.34 – 信任文件的作者

  1. Snyk 将 然后 在 Visual Studio Code 的右下角发送一个通知,询问 信任文件夹并继续不信任文件夹。选择 信任文件夹并继续 并继续

  2. Snyk 将开始分析文件,并在 Visual Studio Code 编辑器的左下角显示安全问题的数量: 代码编辑器:

图 4.35 – Snyk 显示安全问题的数量

图 4.35 – Snyk 显示安全问题的数量

  1. 点击问题的数量;这将显示 Snyk 找到的安全漏洞的详细信息: 由 Snyk 提供:

图 4.36 – 在 eShop 上发现的安全问题列表

图 4.36 – 在 eShop 上发现的安全问题列表

  1. 查看 代码安全性、配置和代码质量问题的列表,以了解发现的一些 问题:

图 4.37 – eShop 上的代码安全性、配置和代码质量

图 4.37 – eShop 上的代码安全性、配置和代码质量

查看生成的代码安全性、配置和代码质量错误列表。 选择一个代码安全错误以了解漏洞的详细信息、易受攻击的代码行以及修复建议 漏洞。

实践练习 2 – 在 IDE 上安装和配置 Git 提交前钩子

在本练习中,我们 将安装并配置 Git 预提交钩子。 如前所述,预提交钩子是 Git 钩子的一种类型,它会在提交记录之前被触发。 我们将使用预提交框架(https://pre-commit.com)。 该 框架允许开发者利用各种现有的钩子,并将它们轻松集成到仓库中。 支持的钩子列表可以在此查看: https://pre-commit.com/hooks.html。这些钩子在 .pre-commit-config.yaml 文件中定义,工具会将它们安装到适当的 Git 钩子目录中。

以下是我们将在本练习中完成的任务:

  • 任务 1:在 Visual Studio Code 中安装预提交框架

  • 在 Visual Studio Code中配置detect-private keydetect-secrets预提交钩子

任务 1 – 在 Visual Studio Code 中安装预提交框架

在此任务中,我们 将在 Visual Studio Code 中设置一个 预提交框架工具:

  1. 使用pip安装预提交包管理器。请在 Visual Studio 终端中运行以下命令:

    pre-commit --version to show what version of pre-commit was installed:
    

图 4.38 – 安装的预提交版本

图 4.38 – 安装的预提交版本

任务 2 – 在 Visual Studio Code 中配置 detect-private key 和 detect-secrets 预提交钩子

在此任务中,我们 将配置两个预提交钩子。 查看 支持的钩子列表 在 https://pre-commit.com/hooks.html。你可以在 .pre-commit-config.yaml 文件中配置多个钩子。 在本任务中,我们将配置 detect-private-key ,该钩子来自 https://github.com/pre-commit/pre-commit-hooks 以及 detect-secrets ,该钩子来自 github.com/Yelp/detect-secrets

  1. eShoponWeb应用程序的根目录中创建一个文件,并命名为.pre-commit-config.yaml

  2. .pre-commit-config.yaml文件中添加以下脚本:

图 4.39 – 配置预提交钩子

图 4.39 – 配置预提交钩子

  1. 现在让我们通过运行pre-commit install来安装 Git 钩子脚本:

图 4.40 – 安装 Git 钩子脚本

图 4.40 – 安装 Git 钩子脚本

  1. 我们现在将针对eShoponWeb目录中的所有文件运行钩子:

图 4.41 – 运行 Git 钩子以处理所有文件

图 4.41 – 运行 Git 钩子以处理所有文件

我们看到两个预提交钩子都失败了,因为检测到私钥,并且在多个列出的位置发现了秘密。最好的做法是修复错误,然后提交更改。

由于我们已配置了这两个预提交钩子,如果发现任何私钥和秘密,它们将阻止提交。

概述

本章中,我们研究了此开发阶段的两个主要安全问题。首先,我们讨论了确保安全的开发环境或工作空间。这意味着确保编码发生的工具和平台,如 IDE,是安全的,免受漏洞的威胁。我们还提到了恶意 IDE 扩展的风险以及处理不受信任的代码时的挑战。我们强调了需要采取措施应对可能的 IDE 漏洞。其次,我们解决了可能导致安全问题的常见编码错误。我们介绍了诸如秘密扫描工具,以检测暴露的敏感数据,SAST 用于查找代码漏洞,SCA 用于检查第三方组件的安全风险等工具。凭借这些知识,你现在更有能力在 DevOps 过程中处理安全挑战。直到目前为止,我们的 DevSecOps 讨论并未聚焦于 Azure。这是因为在预提交阶段之前,Azure 并没有太多特定内容可供讨论。接下来的章节将有所变化,我们将讨论源代码管理中的安全集成,并重点介绍 Azure 工具的使用。到时候见!

第五章:实施源代码控制安全

在前一章中,我们将 DevOps 代码开发过程分为两个关键阶段:提交前阶段和源代码管理阶段。 这种划分是为了简化我们关于安全集成的讨论。 我们已经讨论了提交前阶段的安全实践。 接下来,我们将把焦点转向 源代码控制中的安全方面。

源代码控制在 DevOps 中是通过 源代码管理 (SCM) 系统(如 Git 或 团队基础版本控制 (TFVC))来组织和跟踪项目代码的方式。 在源代码控制中实施 DevSecOps 时,重要的是要考虑如何管理和保护代码仓库。 如果代码仓库的访问被破坏,或保护措施容易被绕过,那么很难信任其中存储的代码。 本章结束时,你将对以下关键领域有一个深入的了解: 关键领域:

  • 理解 DevOps 的提交后阶段 的内容

  • 保障源代码 环境的安全

  • 解决源代码控制中的常见编码安全问题 源代码控制

这些主题将为你提供必要的知识和技能,以将安全实践集成到 DevOps 工作流的源代码控制阶段。 让我们 深入了解吧!

技术要求

要跟随本章的指示,你将需要 以下资源:

  • 一台带有 互联网连接的 PC

  • 一个活跃的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

理解 DevOps 的提交后阶段

在本地提交代码更改后,开发者的下一步是将这些更改同步到 中央远程代码库,如 图 5**.1 (git push 操作。 中央代码库作为所有参与项目的开发者共同存储代码的地方:

图 5.1 – DevOps 的代码开发阶段

图 5.1 – DevOps 的代码开发阶段

中央仓库可以托管在自托管或云托管的源代码管理平台上。 根据 2022 年 Stack Overflow 开发者调查,GitHub 在个人和专业项目中都是最受欢迎的源代码管理平台。 其他平台,如 GitLab、Bitbucket 和 Azure Repos,在专业环境中更为常见(图 5**.2)。 在 第一章中,我们提供了微软两个 DevOps 平台的概述:GitHub 和 Azure DevOps。 这两个平台都提供源代码管理 服务。 在 GitHub 中,我们有 GitHub 仓库,而在 Azure DevOps 中,我们 有 Azure Repos。GitHub 仓库和 Azure Repos 都提供自托管和云托管选项。 自托管版本提供更多控制权,但需要更多管理,而云托管版本管理开销较小,但在 某些情况下可能会提供较少的控制。 这些场景包括:

图 5.2 – Stack Overflow 的源代码管理平台调查(2022)

图 5.2 – Stack Overflow 的源代码管理平台调查(2022)

注意

你可能会 遇到 版本控制源代码管理 这两个术语在各种 文档和文章中。 这两个术语指的是同一件事,可以互换使用。 在本书中,我们将使用术语 源代码管理 以保持一致性。

了解源代码管理阶段的安全措施

鉴于其 作为将要部署到生产环境的代码的 真相来源 的关键作用,确保代码在源代码管理中得到保护并经过安全性测试是至关重要的。 在这个阶段,我们将关注两类主要的安全措施:

  • 保护 SCM 环境的安全:这一类措施强调保护存储代码的环境。 它涉及确保源代码管理本身的完整性和安全,防止未经授权的访问、数据泄露以及其他潜在的安全威胁。 SCM 系统的安全。

  • 解决常见的编码安全问题:这与前一章讨论的目标类似,但应用于源代码控制的背景。 它重点识别并纠正代码中常见的安全漏洞,无论是在代码合并到主代码库之前还是之后。 这包括定期审查代码中的安全缺陷(无论是第三方还是第一方的),实施自动化安全扫描,并确保遵循最佳编码实践以 最小化风险。

下图展示了我们已经讨论过的两个类别:

图 5.3 – DevOps 源代码控制阶段的两大安全措施类别

图 5.3 – DevOps 源代码控制阶段的两大安全措施类别

让我们从 解决第一类问题——保护源代码管理环境 开始。

保护源代码管理环境

在 DevOps 工作流中,保护源代码管理平台对于维护 软件发布的完整性至关重要。 为了实现这一点,我们强烈建议遵循 源代码 部分中概述的指导方针 ,这些指导方针来自 互联网安全中心(CIS)软件供应链 安全指南

CIS 软件供应链安全指南

CIS 软件供应链安全指南 提供了一个全面的框架 用于安全的软件供应链管理。 截至写作时,该指南包含 100 多条建议,分为五大类:源代码、构建流水线、依赖关系、工件和部署。 要访问完整指南,你可以从 下载 https://www.cisecurity.org/insights/white-papers/cis-software-supply-chain-security-guide

该指南 提供了一系列建议,涵盖 五个关键领域 以安全地管理源代码平台:

  • 安全地管理代码仓库:本节包括 7 条建议,重点关注代码仓库的安全性,确保它们得到正确设置、维护,并防止未经授权的访问 或泄露。

  • 安全管理代码贡献:本节包括 13 项建议,重点关注如何安全地处理代码贡献。 这些建议包括审查、接受和合并来自不同开发者/贡献者的贡献的安全指导方针。 这些操作应以安全的方式进行。

  • 安全管理代码更改:本节包括 19 项建议,指导如何安全地管理代码库中的代码更改。 它包括审查、测试和批准更改的指导方针,以确保这些更改不会 引入漏洞。

  • 安全管理代码风险:本节包括 6 项建议,提供了识别、评估和缓解与代码开发相关的风险的指导方针。 其中包括定期进行安全审计和 风险评估的做法。

  • 安全管理第三方集成:最后一节包含 3 项建议,专注于如何安全地将第三方工具集成到源代码控制库中。 该部分强调了对这些集成进行安全漏洞审查并维护其更新的重要性。 确保其安全性。

由于本书篇幅有限,我们无法涵盖所有建议的实施细节。 然而,我们将重点介绍一些 关键建议。

安全管理代码库

确保代码库的安全的起点是确保这些库在创建和维护过程中都是安全的,保护代码的整个生命周期。 与其强制执行一个适用于所有情况的代码库生命周期模型(这种模型很少有效),不如更加有效地专注于定义组织 标准 ,明确如何安全地设置和操作代码库。 为了达到最佳的安全效果,工程团队和安全团队需要共同合作,制定这些标准。 他们应该考虑不同团队的工作方式,以确保这些标准既切实可行又有效。 确保在实施过程中可以真正发挥作用。

随着组织的成熟,这些标准应转化为自动化流程。 这样,新的安全代码库可以快速建立,并与组织的安全需求保持一致,同时减少手动操作中常出现的错误。 这种方法不仅可以提升安全性,还能使设置代码库的过程 更加高效。

以下是该领域的一些指导方针。 我们将讨论如何在 GitHub 和 Azure DevOps 中实施这些指导方针。

推荐 1 – 确保仓库创建仅限于特定成员

在 GitHub 中,当 在组织内设置仓库时,有三种可见性选项: 公开私有,和 内部公开 仓库对所有人可见,包括非组织成员。 私有 仓库仅对已授权的组织成员可见。 最后, 内部 仓库对同一企业内任何组织的所有成员可见。 无论使用哪种可见性选项,保护代码安全非常重要,以确保只有授权用户能够访问并 修改它。

默认情况下,所有组织成员都可以创建任何类型的仓库(图 5**.4)。 然而,修改此默认设置以 增强安全性是一个好做法:

图 5.4 – GitHub 组织中的默认仓库创建权限

图 5.4 – GitHub 组织中的默认仓库创建权限

我们可以 要么完全禁止成员创建仓库,要么限制他们可以创建的仓库类型。 此更改可以在组织级别进行,也可以在企业级别进行,如果您有企业账户并希望在多个组织中应用更改。

  • https://github.com/enterprises/{ENTERPRISE_NAME}) 访问 ENTERPRISE_NAME 是您有效的 GitHub 企业名称的占位符。

  • 组织级别:在 组织设置 页面,访问 成员权限 | 仓库创建

图 5.5 – 修改成员的默认仓库创建权限

图 5.5 – 修改成员的默认仓库创建权限

无论此设置如何,某些组织级别的角色仍然保留创建仓库的权限。 这些角色包括 所有者版主安全管理员 (图 5**.4)。 此外,在企业级别, 企业所有者 角色具有修改组织级别权限的特权,因此可以作为创建仓库的路径。

在 Azure DevOps 中,管理仓库创建权限的流程与 GitHub 略有不同,这是由于平台结构的原因。 Azure Repos 中的仓库可以设置为 公开私有。一个 公开 仓库对所有人开放,包括组织外的人。 另一方面, 私有 仓库仅对已被特别授权的组织成员可见。 Azure DevOps 没有 像 GitHub 那样的 内部 可见性选项,主要是因为它不支持企业账户结构。 为了增强安全性,你可以通过禁用在 Azure DevOps 组织内创建公开项目的选项来限制公开仓库的创建。 此更改会影响组织中的所有成员,无论其角色或权限级别如何,从而阻止任何人创建公开仓库。 要实现这一点,我们可以导航至 Azure DevOps | 组织设置 | 安全 | 策略 | 安全策略 | 允许公开项目。微软最近宣布此选项已默认禁用 。

默认情况下,只有被分配以下角色的用户才能在 Azure DevOps 中创建仓库:

  • 组织级别:项目集合管理员;项目集合服务账户;项目集合有效用户;项目集合构建管理员;项目集合构建服务账户;项目集合代理服务账户;项目集合测试服务账户

  • 项目级别: 项目管理员

我们可以通过严格控制角色分配来实施 此推荐。

推荐 2 – 确保敏感仓库操作仅限特定成员执行

某些 仓库操作因其潜在的恶意攻击风险,被认为是高风险或敏感的。 这包括如删除仓库、分叉仓库和更改仓库可见性等操作。 建议限制允许执行 这些操作的成员数量。

要限制谁可以删除仓库并更改其在 GitHub 上的可见性,请前往 组织 | 设置 | 访问 | 成员权限 | 管理员仓库权限。取消勾选 允许成员删除或转移该组织的仓库允许成员更改该组织仓库的可见性,然后保存 您的更改。

要 限制谁可以在 Azure DevOps 项目中删除仓库,请前往 项目设置 | 仓库 | 仓库 | 安全 并编辑该用户或组的权限(图 5**.6):

图 5.6 – 配置删除仓库的权限

图 5.6 – 配置删除仓库的权限

默认情况下,Azure DevOps 项目中的贡献者角色可以 分叉仓库。

推荐 3 – 确保定期审查和归档非活动仓库

非活动仓库可能成为安全隐患或杂乱无章。 例如,它们可能会导致 误报,使安全团队花费宝贵时间处理无关紧要的问题。 建议定期审查此类仓库,以确定是否应该将其归档。 这样做不仅能提高安全性,还能帮助保持监控环境的清洁,避免 不必要的干扰。

要审查 GitHub 中最近的仓库相关活动,请进入仓库,然后点击 洞察。审查 脉冲提交代码 频率 区域:

图 5.7 – 审查 GitHub 最近的代码仓库活动

图 5.7 – 审查 GitHub 最近的代码仓库活动

要审查 Azure DevOps 项目的最近仓库相关活动,请导航到 Azure DevOps 项目,选择 概览 | 摘要,并审查 项目统计信息 区域,特别是最近的提交和 拉取请求:

图 5.8 – Azure DevOps 项目概览

图 5.8 – Azure DevOps 项目概览

这些 信息也可以通过 API 获取,用于生成自动化报告,虽然你也可以实施第三方解决方案,以更 简化的方式呈现这些信息。

推荐 4 – 应创建启用审计的仓库

在发生安全漏洞时,审计对识别和分析攻击者在我们环境中的 行为至关重要。 从主动的角度来看,我们可以利用日志监控可疑的访问模式,这些模式可能是恶意活动的迹象,或违反了关键的 组织政策。

要在 GitHub Enterprise 中启用仓库活动的事件日志,请按照 以下步骤操作:

  1. 进入你的 GitHub 组织的 设置

  2. 选择 归档 | 日志 | 审计 日志 部分。

  3. 审计日志默认启用。 但是,为了确保源 IP 信息也被记录,请点击 设置 并启用 启用源 IP 披露 选项:

图 5.9 – 审查 GitHub 审计日志设置

图 5.9 – 审查 GitHub 审计日志设置

默认情况下,GitHub 跟踪各种仓库事件,包括创建、修改、删除以及其他重要操作。 要全面了解 GitHub 审计日志中记录的事件,请参考 GitHub 官方文档中的 审计日志事件 ,链接如下: https://docs.github.com/en/enterprise-cloud@latest/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/audit-log-events-for-your-organization。

要为 Azure Repos 中与仓库相关的活动设置事件日志,请按照 以下步骤操作:

  1. 前往 组织设置

  2. 选择 安全性

  3. 前往 政策

  4. 启用 审计日志 事件 选项:

图 5.10 – 在 Azure DevOps 中启用审计日志

图 5.10 – 在 Azure DevOps 中启用审计日志

开启此功能后,我们将能够记录与仓库相关的各种事件,如创建、分叉、修改、启用、禁用、删除和恢复删除。 有关 Azure DevOps 审计的所有事件的完整列表,请参阅官方 文档: https://learn.microsoft.com/en-us/azure/devops/organizations/audit/auditing-events?view=azure-devops

注意

许多组织将这些日志发送到 SIEM 解决方案中,以便进一步汇总和分析。 例如,可以使用 GitHub 的 Sentinel 连接器将 GitHub 审计日志 导入 Microsoft Sentinel。 更多信息,请参阅 此处: https://learn.microsoft.com/en-us/azure/sentinel/data-connectors/github-enterprise-audit-log

解决源代码管理中的常见编码安全问题

保护 我们的源代码管理平台至关重要,但同样重要的是在源代码管理系统中持续测试代码的安全性和合规性。 即使我们已经有了预提交或 IDE 安全集成,也需要这样做。 原因很简单:预提交的代码安全措施可能被绕过;开发人员可能禁用 Git 钩子或通过修改 配置来绕过 静态应用程序安全测试 (SAST) 或 软件组成分析 (SCA) 工具的检查。 然而,源代码管理系统中的安全集成提供了更具执行力和 更可靠的保护。

此外,在源代码管理系统中扫描代码比在 IDE 中扫描提供了更广泛的覆盖。 它 捕获了在开发者的工作空间中可能不存在的提交,尤其是在预提交时。 这增加了发现预提交扫描中遗漏的漏洞的机会。 第三个原因是漏洞具有动态性。 例如,一个依赖项可能在开发和预提交阶段通过了安全检查,但此后却发现了新的漏洞。 我们需要定期扫描源代码管理系统中的代码,以检测和解决 这些问题。

当涉及到在源代码管理中处理常见的编码安全问题时,重点通常是我们在预提交阶段讨论过的相同问题: 检测第一方代码和第三方依赖项中的漏洞 (直接和传递的依赖)以及 识别/防止代码提交中的密钥。如果你需要回顾这些问题,请随时查阅 处理常见开发安全错误 部分 第四章

然而,我们集成这些安全措施的具体位置有所不同,使用的工具也可能不同。 以下图展示了我们将在本章中介绍的四个集成点:

图 5.11 – 代码安全集成点在源代码管理中的位置

图 5.11 – 代码安全集成点在源代码管理中的位置

说到工具,GitHub Enterprise 平台有一套出色的工具套件(GitHub 代码安全),用于在其源代码控制系统中集成安全扫描。 它包括各种工具,用于识别和解决源代码控制中的代码安全问题。

理解 GitHub 代码安全

GitHub 代码安全不是工具;它是 GitHub 平台提供的一组功能,用于识别和修复源代码控制中的代码安全问题。 下图概述了 这些功能:

图 5.12 – GitHub 代码安全功能

图 5.12 – GitHub 代码安全功能

注意

在上图中,星号表示适用于 GitHub Enterprise 和 Azure DevOps 的功能。

在接下来的几节中,我们将介绍一些可以在源代码控制中实现的代码安全集成。 其中一些集成可以使用 GitHub 的代码安全功能来实现。 我们将在相关章节中进一步展开讨论。

建议 1 – 在源代码控制中实施依赖跟踪

在源代码控制中集成代码安全的起点之一是持续评估和跟踪组织中项目中使用的依赖关系。 在安全事件期间,拥有一个集中的位置来检查包是否在组织的各个项目中使用,对于快速确定我们是否受到新披露的漏洞的影响非常有益,例如 Log4j 漏洞披露的情况(CVE-2021-44228)。 GitHub 平台具有我们可以用于此的本地能力,称为 依赖图。不幸的是,Azure DevOps 尚未直接提供此功能。 但是,可以使用多种第三方解决方案来实现类似的功能。

理解并实现 GitHub Enterprise 中的依赖图

依赖图提供了在 GitHub 代码仓库中引用的直接和传递依赖的摘要。 它通过分析每个仓库中清单文件和锁定文件中列出的依赖关系来实现这一点。

如前所述,通过清单文件分析检测依赖关系有其局限性,包括未清理的未使用依赖项带来的噪声以及可能在代码中使用但未在清单文件中列出的虚假依赖项。 如果需要回顾此内容,请参见 SCA 工具的挑战 章节 第四章

截至写作时,依赖关系图支持 13 种语言中的 14 种包管理器类型。 这包括 NuGet(.NET)、pip(Python)和 npm(JavaScript)。 完整且最新的列表可以在 以下位置查看: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph#supported-package-ecosystems

依赖关系图会自动为 GitHub 企业版组织中的所有公共仓库生成。 它也可以在组织级别或直接在仓库级别为私有仓库和派生仓库启用。 要在组织级别启用,组织管理员可以导航到 组织 | 设置 | 安全 | 代码安全 | 配置| 新建配置 | 依赖关系图

图 5.13 – 在组织级别为私有仓库启用依赖关系图

图 5.13 – 在组织级别为私有仓库启用依赖关系图

创建新的代码安全配置后,我们可以将其应用于单个仓库、所有仓库,或没有现有配置的仓库,方法是前往 组织 | 设置 | 安全 | 代码安全 | 配置 然后选择 应用配置应用至

图 5.14 – 将代码安全配置应用于仓库

图 5.14 – 将代码安全配置应用于仓库

启用后,我们可以通过导航到 仓库 | 洞察 | 依赖图 | 依赖项,在仓库级别查看发现的依赖项。在组织级别,我们可以通过导航到 组织 | 洞察 | 依赖项

图 5.15 – 审查依赖项洞察

图 5.15 – 审查依赖项洞察

对于 每个依赖项,我们可以 查看许可证信息和漏洞的严重性。 我们还可以通过提供的 搜索框 来搜索特定的依赖项。

注意

依赖图还提供了一个 API,可以用来提交项目的依赖关系。 通常用于提交未通过标准扫描清单和锁定文件流程识别的依赖项。 这些可能是直接在代码中引用的依赖项,或来自不支持的清单文件类型或语言。 通过这种方式,依赖图将能更准确地反映项目中使用的依赖项。 有关如何使用 API 的更多信息,请访问 这里 https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api

建议 2 – 在源代码控制中实施依赖漏洞评估和管理

识别 我们项目中使用的包是一个重要的第一步。 然而,我们还需要 实施流程来检测包中的漏洞,优先处理这些漏洞,并在可能的情况下自动修复它们。 即使我们已经有了 预提交检查,如上一章所讨论的那样,这一点仍然很重要。 预提交检查可以被绕过,因此在源代码管理中实施类似的检查 可以作为另一层安全防护。 此外,漏洞是动态变化的。 一个在开发过程中通过了漏洞检查的包,可能会在之后被发现有新的漏洞。 定期在源代码管理中进行依赖项漏洞检查,确保我们能够领先于 这些问题。

GitHub Enterprise 提供了如 Dependabot 警报、Dependabot 安全更新、依赖项版本更新和 Dependabot 自动分类规则等功能,可以解决其中的一些需求,尽管可能会有一些空白和限制。 不幸的是,这些功能目前在 Azure DevOps 中尚不可用,但有多种第三方 SCA 解决方案可以直接与 Azure Repos 集成,实现类似的功能。 最重要的是,你需要使用适合你 使用场景的工具来实施这些流程。

在 GitHub Enterprise 中理解和实现 Dependabot 警报

识别 我们项目中的包使用依赖项图是一个重要的第一步。 然而,Dependabot 更进一步,通过在检测到已识别的包中存在漏洞时提醒并通知我们。 Dependabot 提供了三种功能来管理项目依赖项中的漏洞:

  • Dependabot 警报:此 功能 会生成关于我们仓库依赖项中发现的漏洞的警报和通知。

  • Dependabot 安全更新:此 功能会自动创建拉取请求以更新具有已知 安全漏洞的 依赖项。

  • Dependabot 版本更新:此 功能 会自动创建拉取请求,以将你的依赖项更新到 最新版本。

注意

Dependabot 功能需要启用依赖项图 。

要接收来自 Dependabot 警报的通知,必须启用该功能。您可以在企业、组织或仓库级别启用。要为未来的仓库启用 Dependabot 警报,请按照以下步骤操作:

  1. 企业级:前往企业 | 设置 | 代码安全与分析 | Dependabot | Dependabot 警报

    1. 要为所有现有仓库启用此功能,请点击启用全部图 5.16)。

    2. 要为在您的企业中创建的所有新仓库自动启用此功能,请切换自动为新 仓库启用:

图 5.16 – 在组织级别启用 Dependabot 警报

图 5.16 – 在组织级别启用 Dependabot 警报

  1. 要在仓库级别启用 Dependabot 警报,请导航到仓库 | 设置 | 安全性 | 代码安全与分析 | Dependabot | Dependabot 警报 | 启用

  2. 一旦Dependabot 警报启用,我们可以在任意一个范围内审查触发的警报——企业、组织和仓库:

    • 要在企业级别审查 Dependabot 警报,我们可以导航到企业 | 代码安全 | Dependabot 警报

    • 要在组织级别进行审查,请导航到组织 | 安全性 | 警报 | Dependabot图 5.17):

图 5.17 – 在组织级别审查 Dependabot 警报

图 5.17 – 在组织级别审查 Dependabot 警报

  • 要在仓库级别进行审查,请导航到 仓库 | 安全 | 漏洞警报 | Dependabot
  1. 要查看在企业或组织内跨多个仓库的 Dependabot 功能(警报、安全更新等)的状态,可以导航到 企业 | 代码安全 | 覆盖情况 组织 | 安全 | 覆盖情况 (图 5**.18):

图 5.18 – 审查组织中的 Dependabot 覆盖情况

图 5.18 – 审查组织中的 Dependabot 覆盖情况

理解漏洞优先级排序

仅仅识别漏洞并不能解决它们。 将未经优先排序的漏洞扫描报告呈现给工程团队,并指示他们 紧急修复这些问题 并不是一种有效的安全策略,在 DevSecOps 框架下也无法奏效。 同样," 只关注所有关键性和高危漏洞" 这种做法也不可行,因为通常这些漏洞数量较多。 根据 https://www.cvedetails.com/,55%的 CVE 的 CVSS 评分为 7 分及以上。

当在软件堆栈中的开源软件包(OSS)中发现漏洞时,进行风险评估是很重要的,以确定该漏洞是否构成真实威胁。 此评估应指导开发人员如何优先处理该问题。 然而,准确的优先级排序通常依赖于对软件运行环境及其与其他组件交互的深入理解。 在开发的早期、提交前阶段,这些信息可能是有限的,因此很难全面评估漏洞的影响和紧迫性。

在一个 DevSecOps 工作流中,速度是一个关键因素,因此此风险评估应该是快速的,并且最好是自动化的。 这就是一个好的 SCA 工具价值所在。 一个好的 SCA 工具不仅仅是识别漏洞;它还应该提供有意义的风险评估,帮助开发人员在继续之前优先处理需要修复的部分,即使在此早期阶段上下文信息有限。 SCA 工具在此阶段优先排序已发现漏洞的风险时使用了几种方法。 接下来,我们将总结一些这些方法及其所提供的价值。 提供的价值如下。

理解漏洞严重性评分

严重性 评分方法提供了评估已知漏洞影响和紧急性的标准化方式。 最广泛使用的框架是Common Vulnerability Scoring System (CVSS)版本 3.1。 它根据不同的指标组(基本评分指标、时间评分指标和环境评分指标)为漏洞分配分数。 基本评分指标(最广泛使用的指标)衡量漏洞的技术严重性, 而不是风险。

然而,CVSS 3.1 框架的基本评分指标有一个局限性,即它侧重于技术严重性,而非实际的利用风险。 例如,开源库中只有 10%的漏洞是可被利用的。 为什么开发人员要花费宝贵的时间关注那些不可利用的漏洞呢? 这就是为什么像Exploit Prediction Scoring System (EPSS)这样更新的评分方法变得有价值。 EPSS 旨在预测漏洞被利用的可能性,依托于各种数据源,如网络安全建议、社交媒体和公开提及。 这一预测至关重要,因为两个具有相同 CVSS 分数的漏洞,在实际被利用的可能性上可能会有显著差异。 基于 EPSS 优先进行修复工作,在管理实际风险方面可能更为有效。 实际风险。

实际上,结合 CVSS 和 EPSS 提供了一种全面的漏洞优先排序方法。 虽然 CVSS 提供了严重性的基准理解,EPSS 则增加了漏洞被利用可能性的维度。 这种双重视角帮助开发人员在继续提交之前,确定需要优先处理的事项。 他们的提交。

理解依赖路径分析和漏洞上下文分析

虽然 CVSS 和 EPSS 提供了一个可靠的起点来优先排序 漏洞,但它们应当作为更大策略的一部分。 CVSS 和 EPSS 帮助对安全漏洞进行评分,但它们都侧重于开源软件包漏洞的内在和外部属性,而没有考虑这些脆弱功能是否在您的代码中被使用,或如何被使用。 例如,许多开发者导入的开源包可能在最终的应用中没有被使用,从而不会立即构成被利用的风险。 然而,漏洞排名分数并没有捕捉或考虑到这一点。

所以,即使 EPSS 将漏洞评分为可能被利用,而 CVSS 将其评分为严重漏洞,如果您的代码没有调用脆弱的功能,这可能并不重要。 没有这种优先排序技术,开发者可能会花费过多时间修复那些在 您的代码上下文中无法被利用的漏洞。

依赖路径分析和漏洞上下文分析都是基于您的软件项目如何使用脆弱的开源软件包来优先排序漏洞的高级技术。 它们的工作原理如下: 它们是如何工作的:

  1. 依赖路径分析:该方法检查您的项目的依赖树。 依赖树是一个展示不同软件组件(如库和包)如何在您的应用中相互连接和依赖的图谱。 通过分析这棵树,您可以看到一个脆弱组件如何融入到整个 应用结构中。

  2. 了解漏洞路径:这部分分析查看漏洞可能被利用的路径。 它就像是追踪攻击者可能通过互联组件进入 您的软件的路径。

  3. 漏洞上下文分析:这一步骤深入到漏洞的具体细节。 它 考虑到漏洞在代码库中的位置、哪些函数受影响,以及您的应用如何使用该脆弱组件。 这个上下文非常重要,因为代码中某部分的漏洞如果从未被使用或执行,可能就不会构成 真正的威胁。

  4. 影响评估:在分析了依赖路径和上下文之后,你能清楚地了解漏洞是否仅仅是理论上危险,还是在 你的应用程序中实际存在的风险。

需要注意的主要问题是,许多 SCA 工具(包括 Dependabot)并未实现这些技术,因为它们可能复杂且耗时,尤其是在依赖关系多的大型项目中。 一种供应商实现这种优先级排序技术的例子是 可达性分析 方法,Endor Labs 就使用了这种方法。

无论你的工具使用哪种技术组合,我们都不能过分强调与开发团队合作的重要性,以确保这一过程尽可能顺利。 理想情况下,你的 SCA 工具或流程应专注于清晰地向开发团队呈现需要修复的优先级风险,而不会因为不必要的信息而使他们不堪重负。 这些优先级风险需要与你组织的风险承受度相一致,并平衡修复漏洞对 开发者生产力的影响。

修复优先级漏洞

当一个漏洞被 CVSS 评定为高危/严重漏洞,EPSS 评估为可利用,且进一步 分析确认该漏洞的函数在代码中被调用时,下一步是开发人员修复漏洞并重新提交代码。 这取决于是否有官方修复。 大多数 SCA 工具会在扫描结果中突出显示这一点。 它们甚至会突出显示包含安全修复的包版本。 如果有官方修复,开发团队可以将其包升级到带有安全修复的新版本(图 5**.19):

图 5.19 – 修复优先级漏洞的决策过程

图 5.19 – 修复优先级漏洞的决策过程

然而,这个新版本可能会带来一系列问题,比如错误、兼容性问题、性能下降,甚至新的漏洞。 这可能导致之前稳定的代码出现意外 行为。 因此,在应用新版本之前,进行基本的自动化构建测试是很重要的。

另一方面,如果没有官方修复,你的处理方式取决于 OSS 包是否 仍在维护:

  • 对于仍在维护的包:获取项目维护者的指导非常重要。 他们可能会提供修复的预计时间表,或建议采取临时措施来缓解安全漏洞。 在这种情况下,开发者可以将其标记为工作项,并继续 进行其他工作。

  • 对于不再维护的包:这种情况更为棘手。 如果原开发者没有提供预期的更新,你有 几种选择:

    • 分叉依赖:你可以创建并维护自己的依赖版本,应用必要的安全修复。 然而,这需要 持续的维护。

    • 缓解风险:寻求不更新 库的替代方案以降低风险。

    • 替换依赖:寻找并切换到一个积极维护的替代品。 依赖一个不再维护的组件通常不是一个可行的 长期策略。

在 GitHub Enterprise 中理解并实现 Dependabot 安全与版本更新

在本章前面,我们讨论了如何实现 Dependabot 警报,以获取项目中所用包的漏洞通知。 对于每个警报,我们可以手动创建一个 Dependabot 安全更新拉取请求(图 5**.20)。 此操作会生成一个拉取请求,并触发 GitHub Actions 工作流。 该工作流会测试修补后的包版本与我们的代码库的兼容性,确保合并前无问题。 虽然这是一个不错的功能,但需要手动管理项目中多个包的更新可能会拖慢开发效率,并且给开发过程带来摩擦。 这时,Dependabot 的其他功能就派上用场了—— Dependabot 安全更新Dependabot 版本更新

图 5.20 – 手动创建 Dependabot 安全更新拉取请求

图 5.20 – 手动创建 Dependabot 安全更新拉取请求

Dependabot 安全更新 可以通过自动创建 拉取请求来更新具有已知安全漏洞的依赖项,从而自动化这一过程。 要在仓库级别启用此功能,请导航到 仓库 | 设置 | 代码安全与分析 | Dependabot 安全更新 | 启用所有:

图 5.21 – 在组织级别启用 Dependabot 安全更新

图 5.21 – 在组织级别启用 Dependabot 安全更新

Dependabot 版本更新 可以进一步通过自动创建拉取请求来更新依赖项,即使它们没有安全漏洞。 要启用此功能,请导航到 仓库 | 设置 | 安全 | 代码安全与分析 | Dependabot 版本更新 | 启用所有

建议 3 – 实施开源许可证合规扫描

开源许可证是任何软件项目中的一个关键方面。 当在你的项目中使用开源软件包时,定期评估它们的许可证风险等级是一种良好的做法。 这个风险等级应考虑包的许可证条款对你组织合规性、知识产权和独占权的影响。 你可以将风险从低到高进行评级,高风险意味着可能对你组织的合规性产生影响。 如前所述,依赖图显示了每个已识别依赖项的许可证信息,但为了强制执行特定类型的许可证,我们需要实施 依赖审查操作。我们将在下一章中讨论如何在 DevOps 的构建和测试阶段实现安全性时介绍这一点。 现在,让我们来看看各种开源许可证类别及其管理规则。 图 5**.22 展示了一个开源许可证的范围:

图 5.22 – 开源许可证类别

图 5.22 – 开源许可证类别

左侧是 署名 许可证,它们更为宽松;而右侧是 copyleft 许可证,它们更为严格。 让我们更详细地探索这些许可证类型:

  • 署名许可证:这些 许可证非常灵活。 我们可以将库用于任何目的,包括商业软件。 主要要求是给予原始包创建者署名。 这种类型的许可证在合规性和知识产权方面通常具有 较低的风险 。 值得注意的是,并非所有的宽松许可证仅仅是署名许可证。 例如,MIT 许可证和 Apache 许可证是宽松的,但它们包含了比简单署名更多的额外条款。

  • Copyleft 许可证:这些许可证更加严格。 你只能在具有相同许可证条款的项目中使用这些库。 这对于商业软件来说可能会很棘手。 它们通常被称为“病毒”许可证,因为它们可以 将条款扩展到你项目中使用的其他软件组件。 GNU 通用公共许可证 (GPL) 就是一个著名的例子。 如果你实现了一个使用 GPL 许可证的软件包,那么任何派生作品也必须在 GPL 许可证条款下分发。 这确保了 GPL 的自由在所有派生作品中得以保持。 这些许可证 通常具有 较高的风险评级 ,因为它们可能对合规性、知识产权和 独占权产生影响。

  • 下游或弱复制左许可证:这些是中间地带。 它们比强复制左许可证更宽松。 与复制左许可证不同,它们 要求整个衍生项目采用相同的许可证 条款。 一个常见的例子是 GNU 较宽松通用公共许可证 (LGPL)。 与 GPL 不同,LGPL 允许你将库与非 LGPL 软件链接,而无需将整个合并作品以 LGPL 许可证发布。 然而,对 LGPL 许可证组件的任何更改必须以 LGPL 发布。 这使得 LGPL 更适合与专有软件混合使用,同时仍保持对 LGPL 组件的改进开放。 这些 许可证具有 中等风险评级 因为它们对于专有集成更加宽松,但仍确保 LGPL 许可证组件的开放性。

推荐 4 – 在源代码控制中实施机密保护

我们之前 讨论了 GitHub 高级安全性。 它提供的其中一个功能是机密扫描。 这意味着我们可以实施此功能来持续扫描我们的代码库,以检测暴露的凭证。 此外 它还提供了 推送保护,该功能可为 GitHub 企业版和 Azure DevOps 平台启用接收前机密扫描。 该功能会阻止包含机密的代码提交,以防止意外 机密泄露。

推送保护应自动启用在所有仓库中。 为了审计该功能是否 在我们的 GitHub 组织中启用,我们可以使用 Microsoft Defender for Cloud 的 DevOps 安全功能,其中包含对此的推荐(图 5**.23)。 在撰写本文时(2024 年 4 月),还未为 Azure DevOps 添加等效的推荐:

图 5.23 – Microsoft Defender for Cloud 推送保护推荐

图 5.23 – Microsoft Defender for Cloud 推送保护推荐

实操练习 – 执行接收前检查和依赖项审核

在本次练习中,我们将在 GitHub 和 Azure DevOps 上执行预接收检查。 我们还将审查 eShopOnWeb 应用程序的依赖关系,查找任何 安全漏洞。

我们将执行以下任务:

  • 任务 1:在 Azure DevOps 上启用推送保护

  • 任务 2:在 GitHub 上启用推送保护

  • 任务 3:审查 GitHub 上的依赖关系

让我们开始吧!

任务 1 – 在 Azure DevOps 上启用推送保护

此任务 旨在配置预接收条件,以便在推送被接受到仓库之前,强制执行仓库或组织的政策。 在本任务中,我们将启用推送保护,以阻止包含机密的提交:

  1. 在 Azure 门户主页上,在搜索框中输入 Azure DevOps Organizations 并选择 Azure DevOps Organizations。选择你现有的组织之一,或者 创建 新组织

  2. 创建一个私有项目,并命名为 eShopOnWeb

图 5.24 – 在 Azure DevOps 上创建私有项目

图 5.24 – 在 Azure DevOps 上创建私有项目

  1. 点击左侧的 Repos ,然后选择 Import ,位于 Import a repository 部分。

  2. .git中,然后点击 Import

图 5.25 – 克隆 eShopOnWeb

图 5.25 – 克隆 eShopOnWeb

  1. 我们将使用 GitHub 高级安全 的秘密扫描推送保护功能, 推送保护可以防止凭证首次被提交到源代码中。 另一个功能是 GitHub 高级安全 中的 秘密扫描,它可以扫描你现有的 源代码中的机密信息。

  2. GitHub 高级安全功能 为 Azure DevOps 启用时,秘密扫描会在后台启动,并生成秘密扫描警报。 你可以通过进入 高级安全 标签下的 仓库 | 高级安全 区域,然后点击 秘密 标签来查看这些警报。

  3. 首先,我们需要启用 GitHub 高级安全功能。你可以在组织、项目或仓库级别启用 高级安全功能 。我们将通过导航到 项目设置 | 仓库 | Repositories 并选择 eShopOnWeb 仓库来启用它。 在 设置下,切换 高级安全功能 按钮。 一个启用并开始计费的弹出窗口将出现。 点击 开始 计费 按钮:

图 5.26 – 启用高级安全功能

图 5.26 – 启用高级安全功能

秘密 扫描推送保护和仓库扫描现已自动启用:

图 5.27 – 启用高级安全功能后,推送保护和仓库扫描中的秘密扫描功能会被激活

图 5.27 – 启用高级安全功能后,推送保护和仓库扫描中的秘密扫描功能会被激活

当秘密在提交之前被识别时,推送保护会发出警报。 这些警报通过命令行、Azure DevOps Web 界面,甚至通过 你的 IDE 发出。

让我们尝试提交一个包含秘密的文件,看看它是否会被阻止:

  1. 导航到 仓库,选择右上角的三个点,并选择 新建 | 文件

图 5.28 – 创建新文件

图 5.28 – 创建新文件

  1. 将文件命名为 secrets.txt 并点击 创建 按钮。

  2. 将以下内容添加到新创建的文件中,然后点击 提交 按钮:

     SLACK_API_TOKEN = 'xoxp-6597890047-3599393255-7878181812-f140b8'
    

    图 5**.29 展示了创建的秘密文件。 添加 Slack API 令牌。

图 5.29 – 向 secrets.txt 文件添加秘密

图 5.29 – 向 secrets.txt 文件添加秘密

  1. 我们将看到推送被拒绝,因为它 包含了秘密:

图 5.30 – 被高级安全阻止的秘密文件

图 5.30 – 被高级安全阻止的秘密文件

现在,让我们 学习如何在 GitHub 上启用推送保护。

任务 2 – 在 GitHub 上启用推送保护

在此 时,我们需要学习如何通过推送保护防止在 GitHub 仓库中提交秘密。 让我们 开始吧:

  1. 导航到 GitHub 仓库 网址 https://github.com/PacktPublishing/eShopContainers

  2. 将仓库 Fork 到你的 GitHub。 确保仓库 是公开的。

  3. 现在,选择 设置 选项卡。 在左侧边栏中,点击 安全,然后点击 代码安全 与分析

  4. 秘密扫描下,启用 推送保护 ,点击 启用

图 5.31 – 在 GitHub 上启用推送保护

图 5.31 – 在 GitHub 上启用推送保护

秘密 扫描作为推送保护可在企业、组织和 仓库级别启用。

  1. 现在,让我们尝试提交一个包含秘密的文件,看看它是否会 被拒绝。

  2. 点击 添加文件 | 创建 新文件

图 5.32 – 在 GitHub 上添加新文件

图 5.32 – 在 GitHub 上添加新文件

  1. 命名文件为 secrets.txt,添加以下秘密内容,然后点击 提交更改…

     AWS_ACCESS_KEY_ID = 'AKIAYVP4CIPPERUVIFXG'
    AWS_SECRET_ACCESS_KEY = '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'
    SLACK_API_TOKEN = 'xoxp-4797898847-4799393255-4778181812-f140b6'
    

    图 5**.33 展示了带有机密信息的文件。

图 5.33 – 向新文件中添加机密信息

图 5.33 – 向新文件中添加机密信息

  1. 提交 将被拒绝,因为使用 推送保护检测到了机密信息:

图 5.34 – 因源代码中的机密信息而被拒绝的提交

图 5.34 – 因源代码中的机密信息而被拒绝的提交

您现在可以尝试使用其他平台进行提交,例如 VS Code。 提交将 被拒绝。

任务 3 – 审查 GitHub 上的依赖项

对于这个 任务,我们将检查依赖项中存在的安全漏洞。 我们将 审查依赖关系图,导出依赖项为 软件材料清单 (SBOM),并使用 Dependabot 执行依赖项审查。 请按照 以下步骤进行操作:

注意

我们将用于此任务的工具适用于 GitHub 平台。 对于其他 SCM 平台,微软有一个公共工具用于 SBOM 生成,您可以通过以下链接访问 这里: https://github.com/microsoft/sbom-tool

  1. 首先,让我们配置依赖关系图,以便它能够识别我们所有的项目依赖关系和依赖者。 每个依赖项将具有许可证信息和指定的漏洞严重性。 该依赖关系图会自动为所有公共仓库生成,也可以为私有仓库启用 。

  2. 要在私有仓库上启用依赖关系图,请导航至 设置 | 代码安全性与分析 (在 安全 下) 依赖关系图 并 点击 启用

图 5.35 – 依赖关系图

图 5.35 – 依赖关系图

  1. 您可以通过导航到 Insights 来查看依赖关系图:

图 5.36 – Insights

图 5.36 – Insights

  1. 然后,点击 依赖关系图

图 5.37 – Insights 下的依赖关系图

图 5.37 – Insights 下的依赖关系图

  1. 点击 侧边栏中的 依赖关系图 选项后,依赖项列表将显示其版本和安全严重性详情。 每个依赖项都会列出其所在的清单文件的详情,以及 其许可证:

图 5.38 – 依赖关系图详情

图 5.38 – 依赖关系图详情

  1. 您还可以从依赖关系图导出您的仓库的 SBOM。 SBOM 显示开源使用和供应链漏洞。 SBOM 将通过 GitHub 用户界面或 REST API 生成,并采用 SPDX 格式。

    SBOM 是一个结构化且机器可读的列表,详细列出了项目的依赖关系,以及版本、包标识符和许可证等相关信息。 SBOM 在通过以下方式减轻供应链风险中起着至关重要的作用:

    • 增强关于在 您的仓库中使用的依赖关系的透明度

    • 促进在 开发过程中的早期漏洞检测

    • 提供关于代码库中潜在许可证合规性、安全性或质量问题的见解 代码库

    • 帮助遵守各种数据保护标准,以提高 合规性

  2. 要生成 SBOM,请点击 导出 SBOM

图 5.39 – 导出 SBOM

图 5.39 – 导出 SBOM

导出将采用机器可读格式,以便数据可以进一步 处理。

  1. 最后,让我们启用 Dependabot。 您可以通过访问 设置 | 代码安全性和分析 | 依赖项警报 并选择 启用全部或直接依赖关系图 页面启用,如下所示:

图 5.40 – 从依赖关系图页面启用 Dependabot

图 5.40 – 从依赖关系图页面启用 Dependabot

  1. 这两种选项都有效。 这将触发一个新的工作流,并且来自 Dependabot 的安全漏洞将在 安全性 标签页中可见:

图 5.41 – GitHub 上的 Dependabot 警报(左侧有 126 个 Dependabot 警报)

图 5.41 – GitHub 上的 Dependabot 警报(左侧为 126 个 Dependabot 警报)

查看 Dependabot 发现的问题并审查这些安全漏洞的严重性。

总结

在本章中,我们讨论了 DevOps 源代码控制阶段的两个主要安全问题。 首先,我们查看了可以遵循的指南,以实现受保护的源代码控制环境。 其次,我们探讨了如何整合安全工具来识别和修复可能导致 安全问题的常见编码错误。

在接下来的章节中,我们将讨论如何在 DevOps 的构建和测试阶段 实施安全性。

第三部分:确保 DevOps 构建、测试、发布和操作阶段的安全性

在本部分中,你将探索在 Azure 云中构建、测试、发布和操作阶段的最佳安全实践。

本部分包含以下章节:

  • 第六章, 在 DevOps 的构建阶段实施安全性

  • 第七章, 在 DevOps 的测试和发布阶段实施安全性

  • 第八章, 在 Azure 上进行持续安全监控

第六章:在 DevOps 的构建阶段实施安全措施

构建 阶段的目标是 确保代码成功编译并准备就绪。 实施 DevSecOps 的这些阶段应包括在编译之前检查代码中的漏洞,保护构建过程免受可能危及代码完整性的安全漏洞和配置错误,并确保编译后的应用程序不包含可能危害系统或 用户数据的安全漏洞。

通过本章的学习,您将对以下内容有一个坚实的理解:

  • 加强我们的构建过程以使其 更加安全

  • 将 SAST、SCA 和密钥扫描集成到 构建过程

让我们 开始吧!

技术要求

要按照本章的说明进行操作,您需要 以下内容:

  • 一台带有 互联网连接的 PC

  • 一个活跃的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

理解 DevOps 的持续构建和测试阶段

在本书的开篇 章节中,我们讨论了 DevOps 的五个核心实践。 我们涵盖的第三个实践是 持续集成,或者简称 CI 。 CI 是一种开发实践,开发人员通过将代码提交并推送到共享存储库中频繁地集成源代码更改。 然后,每个代码提交都会经历自动化的代码验证过程。 其目标是确保新的代码更改持续验证,以确保其与现有代码库良好集成并不引入 任何错误。

图 6**.1 展示了这个示例。 在这种情况下,开发人员将代码更改提交到他们正在开发的功能分支(例如, 聊天机器人搜索),并将更改推送到中央代码库(标记为 1图 6**.1)。 此推送操作触发了自动构建和测试过程(标记为 2图 6**.1)。 CI 系统从源代码管理中拉取最新的代码(包括新的更改),编译以确保构建成功,并为测试做准备(标记为 3图 6**.1)。 如果构建成功,它会运行自动化测试来验证代码质量(标记为 4图 6**.1)。 如果构建或测试失败,CI 系统会提醒开发人员,提供关于已识别问题的信息,并最好提供如何修复这些问题的指导(标记为 5图 6**.1)。

图 6.1 – CI 示例场景

图 6.1 – CI 示例场景

如果 CI 过程成功,开发人员可以 创建一个 拉取请求 (PR) 将功能分支中的更改合并到主分支中(标记为 6图 6**.2)。 主分支代表将部署到生产环境的代码库,通常会受到分支保护策略的保护(标记为 7图 6**.2)。 这可能包括如最少审阅者数量、自动化构建和测试管道状态,以及需要满足的其他必要条件。 作为 PR 过程的一部分,代码会被其他开发人员或自动化系统审查,以确保其符合团队的标准 和实践。

如果 CI 过程成功完成,开发人员可以提交 PR,将其功能分支的更改合并到主分支(标记为 10图 6**.2)。 主分支是将要进入生产的代码,通常会使用分支保护规则进行保护,例如要求一定数量的审阅者(标记为 8图 6**.2)并通过自动化测试(标记为 9图 6**.2)。 在 PR 过程中,代码将经过另一次构建、额外的自动化检查,并由 其他开发人员进行审查,以确保其符合团队的 质量标准。

图 6.2 – PR 示例场景

图 6.2 – PR 示例场景

当 PR 满足分支保护规则所设定的所有标准,包括成功的自动化测试(标记为 7图 6**.2)以及定义的审阅者数量批准(标记为 8图 6**.2),代码更改随后会被合并到主分支(标记为 9图 6**.2)。

在更改合并后,可以触发另一个流水线,验证新代码是否能够在整个项目的大环境中良好集成,并发布一个可以部署的构件(标记为 1图 6**.3)。 该过程包括在合并后的代码上运行额外的测试,以确保它与现有的代码库正确协作。 它可能还包括额外的验证步骤,例如将代码部署到暂存环境中,进行端到端测试、冒烟测试或在生产之前的其他检查。 如果这些验证成功,则代码将被打包并准备好部署(标记为 2图 6**.3)。

图 6.3 – CI 与 PR 场景结合

图 6.3 – CI 与 PR 场景结合

所描述的场景仅是一个示例,展示了组织如何为功能分支和主分支以及在 DevOps 环境中的各种自动化代码评估设置 CI。 每个组织可能使用不同的方法来 实现这一目标。 实现这一目标。

了解构建系统选项

为了自动化构建 和测试,开发和 DevOps 团队 使用构建环境。 该环境用于定义与组织软件构建自动化相关的所有内容——调度器、流水线执行器以及构建 工作者操作的地点。

Microsoft 提供了两项服务: GitHub ActionsAzure Pipelines。GitHub Actions 可在 GitHub 平台内使用,而 Azure Pipelines 是 Azure DevOps 平台的一部分。 这两项服务都与 Azure 云深度集成,并且根据 JetBrains 最近的调查,它们位列前四大 CI 工具(图 6**.4)。

图 6.4 – JetBrains 开发者生态系统报告 2022

图 6.4 – JetBrains 开发者生态系统报告 2022

使用构建 系统,开发人员创建 .github/workflows 代码库中的文件夹。 在 Azure Pipelines 中,它们被称为 流水线 并且 可以通过网页控制台可视化创建,也可以使用 YAML 代码创建。

无论使用 GitHub Actions 还是 Azure Pipelines,流水线定义通常包含六个核心组件,如下图所示: 以下图所示:

图 6.5 – 流水线定义的六个核心组件

图 6.5 – 流水线定义的六个核心组件

以下是这六个组件的简要 描述:

  1. 触发器:触发器是启动流水线执行的 条件或事件。 这可以是在某人将代码推送到仓库时(CI 触发器),或者创建了一个拉取请求(PR 触发器),也可以是在预定的时间或其他构建完成时。 在写作时,GitHub Actions 支持 36 种事件,可以启动一个流水线(工作流),而 Azure Pipelines 提供了根据代码存储位置不同而有不同的触发器。 如果代码在 Azure Repos 中,开发人员可以使用触发器,例如代码推送或 PR。 如果代码在第三方仓库中,例如 Bitbucket 或 GitLab,Azure Pipelines 仍然可以与它们一起工作,但可用的触发器可能会 更加有限。

  2. 流水线/工作流:流水线或工作流是一组自动化步骤,用于处理代码的构建、测试和部署(我们将在下一章讨论测试和部署)。 Azure DevOps 将此称为流水线,而 GitHub Actions 使用工作流一词。 这些过程包括各种阶段、作业和步骤,将代码从原始状态带到构建、测试,最终到部署。 具体结构和组件可能会根据 项目的不同而有所变化。

  3. 阶段:阶段用于将流水线组织成清晰的、逻辑明确的阶段。 例如,流水线可能会分为三个阶段:构建、测试和部署。 这些阶段代表了将代码从开发到生产的三个关键步骤。 当在 Azure DevOps 中定义多个阶段时,默认情况下它们是按顺序运行的,这意味着下一个阶段仅在上一个阶段完成后才会开始。 这个默认行为是可以修改的。 例如,开发人员可以配置阶段以并行运行或基于特定条件运行。 从技术上讲,GitHub Actions 不支持阶段,但 作业 可以用于相同的目的,即将工作流组织成 不同的阶段。

  4. 作业:一个管道或工作流由作业组成。 每个作业包含按顺序运行的步骤。 有三 个 主要 类型的 无代理作业代理作业容器作业。无代理作业直接在平台上运行,无需特定的 系统或环境设置来运行它们。 它们通常用于较简单的任务,如添加延迟或进行简单的 REST API 调用。 代理作业需要计算机来运行,而容器作业则需要容器来运行。 大多数 涉及构建或测试代码的作业使用代理或容器,而不是无代理作业。 Azure DevOps 支持这三种类型,但 GitHub Actions 仅支持代理和 容器作业。

  5. 步骤:这些是作业内部的单独任务。 它们可以是 预定义脚本 (在 Azure DevOps 中称为 任务 或在 GitHub Actions 中称为 操作 )或 开发者编写的自定义脚本 。 Azure DevOps 和 GitHub Actions 都允许通过市场扩展安装额外的任务/操作。 大多数工作流程/管道中的常见第一步是 checkout,从 代码库下载源代码。

  6. 代理/运行器:这是运行自动化任务的计算系统。 它可以是物理系统、虚拟机或容器,用于运行 GitHub 工作流或 Azure DevOps 管道作业。 在 GitHub Actions 中称为 运行器。在 Azure DevOps 中称为 代理

现在我们已经 对管道的核心组件有了一些理解,让我们把注意力转向保护 构建阶段。

构建阶段中安全措施的理解

CI 系统广泛 访问组织的源代码和在构建过程中使用的服务 凭证。 若发生泄露,可能导致严重的安全漏洞,如恶意代码篡改或凭证盗窃,从而导致未经授权的访问敏感服务,如云基础设施和数据库。 为防范这些威胁,应将重点放在两个 主要领域:

  • 保护 CI 环境和流程:这包括采取措施保护构建和测试环境免受未经授权的访问、代码注入以及可能危及 系统的其他威胁。

  • 解决常见的编码安全问题:基于前一章讨论的原则,本节重点在于识别和解决在构建和测试阶段(包括第一方和第三方代码)中常见的安全漏洞。 它涉及将安全代码审查、自动化安全扫描和执行最佳编码实践作为我们持续测试的一部分,以减少潜在的 安全风险。

图 6.6 – DevOps 构建和测试阶段的两大主要安全措施类别

图 6.6 – DevOps 构建和测试阶段的两大主要安全措施类别

让我们从 处理第一类问题——保护 CI 环境 和流程开始。

保护 CI 环境和流程

在 DevOps 工作流中,确保 源代码管理平台的安全性对于维护软件发布的完整性至关重要。 例如,我们需要确保只有受信任和经过验证的贡献者可以对代码进行任何更改,并且第三方插件需要经过严格评估和监控,以发现安全漏洞。 为了实现这一目标,我们强烈建议遵循 源代码 部分中概述的指南, 互联网安全中心 (CIS) 软件供应链 安全指南。

CIS 软件供应链安全指南

CIS 软件供应链安全指南提供了 一个全面的框架,帮助安全地管理软件供应链。 该指南目前包括 100 多条推荐,分为五大类:源代码、构建流水线、依赖关系、工件和部署。 要访问完整的指南,您可以从此 链接下载: https://www.cisecurity.org/insights/white-papers/cis-software-supply-chain-security-guide

本指南提供了一套 针对四个关键领域的推荐 ,旨在保障 DevOps 的构建阶段 的安全性:

  • 保障构建环境的安全:本节包含六条推荐,重点是单一责任的流水线、不变的基础设施、日志记录、环境创建自动化、访问限制和构建环境的身份验证要求。

  • 保障构建工作者的安全:本节包含八条推荐,重点是确保构建工作者是一次性使用的,安全地传递环境和命令,分离职责,最小化网络连接,执行运行时安全,扫描漏洞,维护版本控制中的配置,并监控 资源消耗。

  • 保障流水线指令的安全:本节包含八条推荐,重点是将构建步骤定义为代码,为构建阶段指定输入/输出,保障输出存储的安全,跟踪和审查流水线文件变更,最小化对构建触发器的访问,扫描流水线中的配置错误和漏洞,防止敏感 数据泄露。

  • 保障流水线完整性的安全:本节包含六条推荐,涵盖了对所有发布工件进行签名、锁定外部依赖、在使用前验证依赖、创建可重现的构建,并为每个构建生成并签署 一份 软件材料清单 (SBOM) 。

为了保持本章简洁,我们不会详细涵盖所有方面。 相反,我们将专注于我们认为是 关键推荐的领域。

注意

Microsoft Defender for Cloud 的 Defender CSPM 计划包括一个 DevOps 安全功能,提供一些针对这些建议的评估子集。 你可以通过此链接获取更多信息: https://learn.microsoft.com/en-us/azure/defender-for-cloud/recommendations-reference。在本章稍后的实操练习中,你将使用此功能来评估你的 DevOps 构建 平台的安全态势。

保护构建服务和工作者

在本章前面,我们已明确开发人员和 DevOps 团队使用 构建服务 例如 GitHub Actions 和 Azure Pipelines 来定义构建软件的自动化流程。 这些流程运行在 被称为 构建工作者的系统上。不同的平台对这些工作者有不同的名称。 在 Azure Pipelines 中,它们被称为 代理agents),在 GitHub Actions 中,它们被称为 运行器runners) 。

作为构建阶段安全努力的一部分,我们需要确保构建服务、自动化流程和构建工作者的安全。 如果攻击者获取了构建服务或工作者的访问权限,他们可能会插入恶意代码或操控构建过程,从而导致 软件受到危害。

保护构建工作者

构建工作者主要有两种类型: 平台托管工作者自托管工作者。平台托管工作者是由平台提供商(如微软托管/ GitHub 托管)提供和管理的虚拟机。 自托管工作者是由客户提供和管理的计算资源。 图 6**.7 展示了这些工作者选项在 GitHub Actions 和 Azure Pipelines 中的区别。 它们都支持 macOS、Ubuntu 或 Windows 操作系统,但它们在功能上有所不同,例如支持容器中的作业或在 私有网络中运行。

图 6.7 – Azure Pipelines 和 GitHub Actions 的构建工作者选项

图 6.7 – Azure Pipelines 和 GitHub Actions 的构建工作者选项

平台托管工人的优势在于它们无需开发者进行管理。 平台负责所有维护工作,包括更新操作系统和任何预装的软件。 这意味着开发者不必担心这些方面,但也限制了他们对这些工人上预装的软件和网络连接的控制。 另一方面,自托管工人则为开发者提供了更多的控制权和灵活性。 他们可以预先安装构建和测试软件所需的任何工具,并且这些工人可以连接到内部网络。 然而,这种 灵活性伴随着维护、更新和保护 这些系统的责任。

根据信任级别和安全要求使用合适的工人类型

每种类型的 工人适用于不同的场景。 例如,自托管的工人,尤其是那些可以访问公司内部网络的工人,绝不应被用于从不受信任的来源(如公共仓库或包含外部贡献的代码)构建代码。 这可能会被滥用,泄露内部机密或在 环境中横向移动。

自托管工人绝不应被用于从不受信任的来源(如公共仓库或外部贡献)构建代码。

一个最近的例子是 PyTorch 的供应链攻击,由安全研究员 John Stawinski 演示。 该攻击使用了 Gato,这是 Praetorian 开发的 GitHub 利用工具,用于识别 PyTorch 公共仓库中的自托管运行器。 通过利用一个错误配置,允许未批准的 PR 工作流,研究员在自托管运行器上安装了 持久 命令与控制 (C2) ,并破坏了 敏感令牌,修改了 仓库发布。

注意

要了解更多关于 John Stawinski 研究的信息,请参考此 文档: https://johnstawinski.com/2024/01/11/playing-with-fire-how-we-executed-a-critical-supply-chain-attack-on-pytorch

你也可以通过以下链接访问 Gato 工具: https://github.com/praetorian-inc/gato

实施一次性构建工人

在可能的情况下,我们 希望确保每个构建作业都使用一个全新的、干净的环境,并在构建完成后丢弃。 这种方法通过隔离每个构建作业来增强安全性,防止残留的工件或先前构建中暴露的秘密在同一工人上造成风险。 图 6**.8 展示了一个例子,其中项目 A 的构建作业被攻陷并修改,以在构建工人上放置一个持久的恶意服务。 当项目 B 的构建作业在同一工人上运行时,恶意服务可以窃取项目 B 使用的秘密。

图 6.8 – 使用持久化构建工人的秘密暴露风险

图 6.8 – 使用持久化构建工人的秘密暴露风险

Azure Pipelines 和 GitHub Actions 上的平台托管工人默认已经实现了这一做法。 它们为每个作业分配一个新的虚拟机,并在作业完成后丢弃它。 然而,自托管工人不会自动遵循 这种模式。

与您的开发团队合作,了解常见的构建过程模式是非常重要的,因为可能会出现需要一系列作业在同一构建工人上运行的场景。 避免在没有适当团队讨论和参与的情况下强制执行此做法。 这违背了 DevSecOps 的协作精神。 最好与 团队合作,找到安全需求与 工作流效率之间的平衡。

最小化构建工人的网络连接

对于您的最 敏感和关键的工作负载,您可能希望强制它们在网络连接受限且启用了运行时安全措施(如 EDR)的构建工人上运行。 这可以作为额外的防御层,防止横向移动、持久性或后门攻击对被攻陷 的构建工人进行攻击。

过去,限制平台托管工人的网络连接是一个挑战,导致一些组织更倾向于选择自托管工人。 然而,微软最近推出了一项新功能,允许 GitHub 托管的运行器在私有 Azure 虚拟网络中运行。 这结合了 GitHub 管理的 CI/CD 基础设施的好处,并完全控制构建工人的 网络策略。

组织所有者可以在企业或组织级别进行设置。 要在企业级别进行配置,前往 设置 | 托管计算网络 | 新建网络配置 | Azure 私有网络 | 添加 Azure 虚拟网络。有一些先决条件,但已在文档中 列出: https://docs.github.com/en/enterprise-cloud@latest/admin/configuration/configuring-private-networking-for-hosted-compute-products/configuring-private-networking-for-github-hosted-runners-in-your-enterprise.

实现对构建环境和工作节点的安全访问

另一个关键的安全 措施是确保安全访问构建和测试资源。 这包括保护网络和用户访问构建服务。 仅实施安全访问是不够的;我们需要采用最强的 身份验证方法。

限制网络访问到构建服务环境

一个主要的防护领域 是确保用户/管理员只能从受信任的网络连接到我们的构建环境。 默认情况下,Azure DevOps 和 GitHub Enterprise Cloud 支持来自任何 IP 地址的连接,但我们可以 进行修改。

GitHub Enterprise 通过 IP 允许列表功能支持直接网络访问限制,功能可在 设置 | 身份验证安全 | 启用 IP 允许列表 (图 6.9). 此功能可以在企业或组织级别进行设置。 启用后,GitHub Enterprise 仅接受来自允许列表中 IP 地址的连接,无论用户的 角色、权限或连接方式(Web UI、API 或 Git)。

图 6.9 – 配置 GitHub 的 IP 允许列表

图 6.9 – 配置 GitHub 的 IP 允许列表

我们还可以选择自动将我们安装的 GitHub 应用使用的 IP 地址加入到 IP 允许列表中。 此功能确保来自安装的 GitHub 应用的连接不会被阻止。 要启用此功能,我们可以选择 为安装的 GitHub 应用启用 IP 允许列表配置 设置(图 6**.9)。 如果启用了此选项,GitHub 应用创建者指定的 IP 地址将自动添加到我们的允许列表中。 此外,GitHub 应用创建者所做的更新将自动反映在我们的列表中(图 6**.10)。 这要求我们在安装 GitHub 应用时采取谨慎的态度,因为被攻破的应用可能会被用来绕过我们的网络限制规则。 只有在你有验证已安装 GitHub 应用的流程时,才应启用此设置。 你的组织应确保有此流程。

图 6.10 – GitHub 应用创建者的 IP 列表更新将自动允许

图 6.10 – GitHub 应用创建者的 IP 列表更新将自动允许

注意

如果团队使用的是自托管的 runner 或者具有静态 IP 地址的大型 GitHub 托管 runner,我们必须将我们的 runner 的 IP 地址或范围添加到 IP 允许列表中,以便与 GitHub 企业平台建立连接。

Azure DevOps 没有像 GitHub Enterprise 那样直接限制网络访问的选项。 然而,由于它可以与 Entra ID 集成进行登录,我们可以实现 Microsoft Entra 条件访问策略 (CAPs) 来进行 IP 限制。 这种方法同样适用于通过 Microsoft Entra ID 认证的 GitHub 企业帐户,其 企业托管用户 (EMU)进行认证。 图 6**.11 展示了其工作原理:

图 6.11 – 实现 Entra CAPs 进行 IP 限制

图 6.11 – 实现 Entra CAPs 进行 IP 限制

以下是 步骤:

  1. 用户尝试使用 EMU 和受支持的 客户端应用程序访问 Azure DevOps 或 GitHub 企业版。

  2. 连接请求将被重定向到 Entra ID 进行认证。

  3. Entra ID 验证用户身份,并且如果配置了 多因素身份验证MFA),可能会要求进行身份验证。

  4. 条件访问检查登录请求是否符合配置的 IP 限制。

  5. 如果满足 IP 限制,客户端将获得 Azure DevOps 或 GitHub Enterprise 的访问令牌。 如果不满足,访问尝试 将被阻止。

如果此选项在 Azure DevOps 中实施,我们可以启用 启用 IP 条件访问策略验证 设置,位于 组织设置 | 安全 | 策略图 6**.12)。 这将把 IP 限制检查从 Entra CAPs 扩展到 Web 交互和非交互式流程。 这包括来自第三方客户端的操作,例如使用 个人访问令牌 Personal Access TokenPAT)进行 Git 操作。

图 6.12 – 在 Azure DevOps 中启用 IP CAP 验证

图 6.12 – 在 Azure DevOps 中启用 IP CAP 验证

现在我们对如何保护网络访问构建环境有了初步了解,接下来让我们 回顾一下 保护用户和 服务访问的可用选项。

理解 GitHub 身份验证选项

GitHub Enterprise 提供了多种身份验证机制,供用户和应用程序访问构建环境,具体取决于身份验证场景。 用户在通过 Web 控制台访问 GitHub Actions 时,可以使用用户名和密码进行身份验证,或者使用 PAT 进行 命令行界面CLI)访问(图 6**.13)。

图 6.13 – GitHub Enterprise 身份验证选项

图 6.13 – GitHub Enterprise 身份验证选项

使用用户名 和密码有三种主要的身份验证 选项:

  • 个人 GitHub 身份:用户可以使用他们的个人 GitHub 身份进行身份验证。 通过 此选项,用户保持对其身份的控制(因为这是他们的个人账户),并且可以使用相同的身份为其他企业、组织以及 GitHub 以外的仓库做贡献。 该身份适用于组织外的资源。

  • 外部身份提供者(IdP)与 SAML 单点登录(SSO):用户可以 通过与其 GitHub 身份相关联的外部 SAML 提供者进行身份验证。 身份验证由外部提供者管理,但访问权限会授予 GitHub 企业版中的组织资源。 此选项可以在企业层级 组织层级进行配置。

  • 企业管理用户(EMU):此选项类似于 SSO 选项,但它为企业用户提供了更多控制权。 使用 EMU,用户将通过由外部 IdP 创建和管理的单一身份访问 GitHub 组织资源,包括构建环境。 用户无需拥有个人 GitHub 身份。

企业的推荐方案 是选择使用 SAML SSO 选项或 EMU 选项。 这两种选项都依赖于外部身份提供者(IdP),并且相较于使用个人 GitHub 身份,提供了更高的安全性。 然而,它们的运作方式仍然存在区别,如 图 6**.14所总结。

图 6.14 – 比较 GitHub EMU 与 SAML SSO

图 6.14 – 比较 GitHub EMU 与 SAML SSO

例如,实施 EMU 涉及更复杂的设置过程,需要与 GitHub 团队协调,以启用带有 EMU 的企业账户。 相比之下,设置 SAML SSO 更为直接,可以独立完成,无需联系 GitHub 团队。

另一个区别 是,EMU 支持仅限于两个 IdP—Entra ID 和 Okta。 如果要使用不受支持的 IdP,EMU 只能通过联合到两个支持的 IdP 之一来使用。 相比之下,SAML SSO 支持更广泛的 IdP。 Microsoft 官方支持六个 IdP 用于 SAML SSO:Entra ID、 Active Directory 联合身份验证服务 (ADFS)、Okta、OneLogin、PingOne 和 Shibboleth。 SAML SSO 在技术上兼容任何实现 SAML 2.0 协议的 IdP,但如果它们未被 官方列出,支持将受到限制。

另一个关键区别是,EMU 实施需要 SCIM,而 SAML SSO 不需要 SCIM。 SCIM 代表 跨域身份管理系统 和 EMU 使用它在 GitHub Enterprise 中创建托管用户帐户。

此外,EMU 身份不能用于访问或贡献给外部组织。 他们可以查看公共资源,如存储库、要点或页面,但不能用于对其进行更改。 这是为了防止企业成员意外地向公众泄露企业拥有的内容。 此外,他们创建的内容仅对企业其他成员可见。 SAML SSO 身份没有 这种限制。

最后,EMU 身份受到限制,不能为 GitHub Actions 创建启动工作流程或安装 GitHub 应用程序,而 SAML SSO 身份则没有 这些限制。

理解 Azure DevOps 的身份验证选项

与 GitHub 相似,Azure DevOps 根据 用例提供多种身份验证方法(图 6**.15)。

图 6.15 – Azure DevOps 的身份验证选项

图 6.15 – Azure DevOps 的身份验证选项

大多数组织将其 Azure DevOps 组织连接到其 Entra ID 租户,允许用户使用其 Entra ID 凭据登录。

保护在 GitHub 和 Azure DevOps 中使用 PATs

PAT 是用户生成的、长期有效的令牌,用于在 GitHub Enterprise 或 Azure DevOps 环境中进行身份验证。 通常用于使用命令行工具进行身份验证或在使用基本身份验证进行 API 调用时。 这些令牌与生成它们的用户帐户直接相关联,并且如果用户的访问权限被撤销,令牌将失效。

GitHub 支持两种类型的 PAT: 精细粒度经典。精细粒度 PAT 比经典 PAT 提供了更细粒度的访问控制。 例如,精细粒度 PAT 可以用于指定按仓库级别的访问(图 6**.16)。 它还允许对账户级别和 仓库级别的资源进行更精细的权限设置。

图 6.16 – 精细粒度 PAT 支持按仓库级别的访问

图 6.16 – 精细粒度 PAT 支持按仓库级别的访问

Azure DevOps 还支持两种类型的 PAT:全局级和组织级(图 6**.17)。 全局级 PAT 可以 用于授予用户有权限的所有组织中的资源的广泛访问权限。 组织级 PAT 限制 对单个组织内资源的访问。

图 6.17 – Azure DevOps 中的组织级和全局级 PATs

图 6.17 – Azure DevOps 中的组织级和全局级 PATs

GitHub Enterprise 和 Azure DevOps 都支持可以用来管理 PAT 使用的策略, 在我们的 环境中。 图 6**.18 概述了这两个平台中令牌类型和策略支持的区别。

图 6.18 – 比较 Azure DevOps 和 GitHub PATs

图 6.18 – 比较 Azure DevOps 和 GitHub PATs

例如,Azure DevOps 支持以下策略,用于控制 PAT 的使用。 这些策略可从 组织设置 | 常规 | Microsoft Entra | 策略 (图 6**.19)配置:

  • 限制全局个人访问令牌创建:启用此策略后,将阻止所有用户创建全局范围的 PAT,仅允许组织范围的 PAT。

  • 限制完全范围的个人访问令牌创建:启用此策略后, 将阻止 所有用户创建完全访问令牌。 只有限定于特定范围的 PAT 才允许创建。

  • 强制执行最大个人访问令牌生存期限:我们可以使用此策略为新的 PAT 设置最大允许的生存期限。 我们可以指定从 1 到 365 天的任何值。

  • 自动撤销泄露的个人访问令牌:此策略默认启用,并建议保持启用状态。 它会自动撤销在公共 GitHub 仓库中检测到的 PAT。 还会通知令牌所有者并在组织的审计日志中记录事件。 建议保持此策略启用,或者至少实施类似的流程。

图 6.19 – Azure DevOps 中的 PAT 治理策略

图 6.19 – Azure DevOps 中的 PAT 治理策略

GitHub 企业版 还支持以下 用于控制 PAT 使用的 策略。 这些策略可以在组织级别从 组织 | 设置 | 第三方访问 | 个人访问令牌 或在企业级别从 企业 | 策略 | 个人访问令牌 (图 6**.20)配置:

  • 限制通过细粒度个人访问令牌访问:此策略可用于启用或限制 细粒度 PAT 的创建

  • 要求批准细粒度个人访问令牌:此策略可用于要求管理员审核和批准创建的 PAT 。

  • 通过个人访问令牌(经典)限制访问:此策略可用于允许或限制创建 经典 PAT

图 6.20 – GitHub 企业云中的 PAT 治理策略

图 6.20 – GitHub 企业云中的 PAT 治理策略

现在你 理解了如何在 DevOps 环境中 安全地 管理 PAT,让我们回顾一下最近的攻击中被利用的另一种令牌: 管道令牌。

保护 GitHub 和 Azure DevOps 中管道令牌的使用

在某些场景中,我们需要在自动化管道中访问 GitHub 企业或 Azure DevOps 资源,例如,在需要通过调用其 API 来更改平台时。 GitHub 企业和 Azure DevOps 都为这种场景提供了专门的访问令牌供工作流/管道使用。 在 GitHub 企业中,该令牌被称为一个名为 GITHUB_TOKEN的密钥。在 Azure DevOps 中,它被称为一个名为 System.AccessToken的特殊变量。

作为良好的安全实践,这些令牌应授予确保影响的最低访问权限 的 中毒管道执行 (PPE) 攻击,该攻击会妥协令牌 的影响被限制。

在 GitHub 中,令牌的默认权限可以配置为 宽松严格,可以在企业、组织或仓库级别进行设置。 宽松选项(标记为 1图 6**.21)授予对仓库中所有范围的读写访问权限,而严格选项(标记为 2图 6**.21)限制对内容和包范围的只读访问。 选择宽松选项会增加在 PPE 攻击中攻击者提升权限或横向移动的风险。 这种类型的攻击将在 本章后续讨论。

图 6.21 – 配置 GitHub 工作流令牌的默认权限

图 6.21 – 配置 GitHub 工作流令牌的默认权限

此配置可以在 企业、组织或 仓库级别进行设置:

  • 企业: 企业 | 设置 | 策略 | 操作 | 策略 | 工作流权限

  • 组织: 组织 | 设置 | 代码、规划与自动化 | 操作 | 常规 | 工作流权限

  • 仓库: 仓库 | 设置 | 代码与自动化 | 操作 | 常规 | 工作流权限

无论是在企业、组织还是仓库级别设置的默认权限如何,任何具有写权限的用户都可以在工作流级别修改权限。 例如,如果 GITHUB_TOKEN 的默认权限较为严格,工作流拥有者可能希望提高权限,以允许某些操作和命令在工作流中成功运行。 相反,如果默认权限较宽松,工作流拥有者可以通过编辑工作流文件来降低 GITHUB_TOKEN 的权限。 在工作流文件中设置权限的示例如下所示: 图 6**.22

图 6.22 – 在工作流文件中配置 GitHub 工作流令牌的权限

图 6.22 – 在工作流文件中配置 GitHub 工作流令牌的权限

对于 Azure DevOps,我们可以通过作业授权范围策略来管理令牌(System.AccessToken)的访问权限(图 6**.23)。 这些 策略可以在 组织或项目级别进行配置。 对于组织级别,导航到 组织设置 | 管道 | 设置。对于项目级别,转到 项目设置 | 管道 | 设置。请注意,组织级别的设置不能在 项目级别被覆盖。

图 6.23 – 在 Azure DevOps 中配置作业授权范围策略

图 6.23 – 在 Azure DevOps 中配置作业授权范围策略

可用的设置包括 以下内容:

  • 将作业授权范围限制为当前项目(仅适用于非发布管道):我们可以启用此设置,限制令牌的访问权限仅限于运行管道的项目。 此设置仅适用于 YAML 和经典构建管道。 如果禁用此设置,访问令牌将具有组织范围的访问权限,并授予访问组织中不同项目的资源的权限。 这会增加在成功发生 PPE 攻击时的潜在影响。

  • 将作业授权范围限制为当前项目(仅适用于发布管道):我们可以启用此设置,限制令牌的访问权限仅限于运行管道的项目。 此设置仅适用于经典 发布管道。

如果在组织级别和项目级别都禁用这些设置,那么每个管道作业将可以访问组织范围的访问令牌。 这意味着,如果攻击者破坏了任何项目中的任何管道,他们可能会利用令牌来访问我们组织中的所有代码库! 这就是为什么建议启用这些设置以限制 访问范围 并 确保成功的攻击仅限于一个 单一项目。

保护构建环境免受恶意代码执行

确保管道 配置是确保构建环境安全的重要方面。 管道定义了代码在部署到生产环境之前的处理流程。 如果管道被攻破,攻击者可能会修改配置文件,绕过安全检查或执行 恶意代码。

主要挑战在于在安全性与促进创新和协作之间取得平衡。 正如我们之前讨论的,DevOps 文化强调团队合作与协作。 因此,开发团队通常将管道配置文件与源代码存储在同一个代码仓库中。 这种做法允许并鼓励团队成员将他们的测试贡献到构建过程中,类似于代码贡献。 虽然这种做法有助于协作,但也伴随着一定的风险。 例如,如果开发人员的凭证被攻击者泄露,攻击者可能利用这些凭证修改配置文件,从而绕过安全检查或执行窃取 敏感凭证的恶意代码。

为了解决这一挑战,需要采取平衡的方式。 开发人员可以被授权修改功能分支的 CI 管道配置。 然而,必须严格控制访问权限,以修改与主分支相关联的管道配置文件。 这种方式在不破坏主分支完整性的前提下,为开发团队提供了灵活性。 主分支。

未能保障主管道配置文件完整性的组织面临 PPE 攻击的风险。 在这种攻击中,攻击者获得访问权限修改管道配置,并利用此访问权限执行恶意代码(从而 污染 CI 管道)。 这种攻击的典型目标是访问并窃取敏感凭证。 PPE 攻击有两种类型: 攻击: 直接 (也称为 D-PPE) 和 间接 (也称为 I-PPE**)。

理解直接和间接 PPE

在直接 PPE 场景中,攻击者 获得 权限访问存储管道配置的源代码仓库。 这可以通过被攻破的凭证,例如开发者的凭证、访问令牌、SSH 密钥或 OAuth 令牌。 一旦进入,攻击者修改管道配置以执行恶意命令。 图 6**.24 展示了一个示例,其中恶意命令已被注入到管道配置中,用于提取带有敏感凭证的环境变量(AZURE_STORAGE_CONNECTION_STRING)并使用 curl发送到外部服务器 :

图 6.24 – 示例直接 PPE

图 6.24 – 示例直接 PPE

为了实现直接 PPE,攻击者需要获得修改管道配置文件的访问权限。 在无法获得此访问权限的情况下,可能是因为管道配置文件位于一个独立或受保护的仓库中,或者它是通过经典构建管道方法(如 Azure Pipelines)定义的,而不是 YAML。 在这些情况下,攻击者仍然可以通过向管道配置文件使用的文件、代码或脚本中注入恶意代码来污染管道。

处理未经审查代码的管道面临更大的 PPE 攻击风险。 这包括由任何仓库分支或未经审查/验证的 PR 激活的管道。 使用 SAST 工具检查管道配置中的有害元素是一个好的且推荐的做法。 这些工具应经常用于扫描 仓库 其中 存储管道配置的 位置。

为市场扩展设置审批流程

GitHub 和 Azure DevOps 都提供了市场,供开发者集成额外工具,以增强和定制 CI/CD 流程。 GitHub 的市场(https://github.com/marketplace)允许开发者安装 动作应用,而 Azure DevOps 市场(https://marketplace.visualstudio.com/azuredevops)提供 扩展

截至本文写作时,GitHub Marketplace 上已托管超过 21,000 个操作和超过 850 个应用,而 Azure DevOps Marketplace 上列出了超过 2,200 个扩展。 这些数字 还在不断增加。

虽然这些可用的附加工具(操作、应用和扩展)对于自定义和改善 CI/CD 体验非常有帮助,但也存在安装易受攻击或恶意工具的风险。 安全研究人员 Rob Bos 和 Jesse Houwing 近期进行的分析揭示了这些风险。 他们的研究表明,Azure DevOps Marketplace 中 35%的任务和 GitHub Marketplace 中 30%的操作存在安全问题,主要是由于直接漏洞或 易受攻击的依赖关系。

鉴于这些发现,建议实施审批流程,以确保来自公共市场的任何工具(操作、应用或扩展)在安装之前都经过彻底的安全风险评估。 采取这种预防措施有助于减轻将潜在有害或被妥协工具集成到 CI/CD 流水线中的威胁。 在本节中,我们将介绍 GitHub Enterprise 中的操作和 Azure DevOps 中的扩展。 稍后我们将讨论 GitHub 应用程序 在本章中。

注意

查看 Rob Bos 和 Jesse Houwing 的完整报告,链接如下:

GitHub Enterprise 有可用于控制可在工作流中使用的操作的策略。 这些设置可以在企业、组织或 仓库级别进行配置:

  • 企业级别配置: 企业 | 设置 | 策略 | 操作 | 策略

  • 组织级别配置: 组织 | 设置 | 代码、规划与自动化 | 操作 | 常规 | 策略

  • 仓库级配置仓库 | 操作 | 通用 | 操作

名为 允许企业及部分非企业操作和可重用工作流 的策略提供了多个选项,用于控制开发者在工作流中可以使用的操作(图 6**.25):

图 6.25 – 定义可以在工作流中使用的操作

图 6.25 – 定义可以在工作流中使用的操作

  • 允许 GitHub 创建的操作:此设置允许使用由 GitHub 开发的所有操作。 这些操作可以在 actions(https://github.com/actions)和 GitHub(https://github.com/github)组织中找到。

  • 允许由市场验证的创建者提供的操作:此设置仅允许使用来自 GitHub 市场的操作,前提是这些创建者已通过验证。 这一点可以通过 验证的创建者 徽章表示(图 6**.26)。 需要注意的是,使用来自验证创建者的操作仍然存在风险。 该徽章表明操作的创建者已经通过 GitHub 确认了其身份,通常是通过域验证过程。 但这并不意味着该操作已经通过任何 安全检查。

图 6.26 – GitHub Actions 验证的创建者

图 6.26 – GitHub Actions 验证的创建者

  • 允许指定的操作和可重用工作流:此设置可用于将工作流限制为仅使用来自指定、批准的组织和仓库中的操作。 已批准的操作通过以下语法指定:

     OWNER-OR-ORGANIZATION/ACTION-REPOSITORY@TAG-OR-SHA
    

    语法中支持通配符,这为许多用例提供了可能性。 例如,指定通配符,如 azure/webapps-deploy@* 允许使用 任何 版本的 webapps-deploy 操作,前提是该操作来自 azure 组织。

    为了仅允许特定版本的操作,我们可以指定 TAG-OR-SHA。例如, azure/webapps-deploy@v3.0.1 将仅允许使用版本 3.0.1。但是,指定标签仍然存在相关风险。 如果创建者的仓库遭到破坏,攻击者可以轻松修改标签,指向恶意代码。 为了降低这一风险,可以使用提交 SHA,例如 azure/webapps-deploy@b45824004798750b8e136effc585c3cd6082bd6432。这定义了特定的提交,并确保 更严格的完整性。

    我们还可以对整个组织应用通配符。 通过指定 azure/*,Azure 组织中的任何操作都将被允许。 这为实施一种 内部市场提供了选项。实施这一过程的步骤包括 以下内容:

    1. 建立一个组织来托管批准的操作,例如, MY-ORG

    2. 通过将整个组织的操作添加到批准列表中,批准它们,例如, MY-ORG/*

    3. 执行对请求的 GitHub Actions 的安全审查。

    4. 将批准的操作叉到该组织中,使其对开发人员可用。

注意

最大可指定的操作定义数量为 1000

对于 Azure DevOps,默认情况下,组织所有者和项目集合管理员可以从市场安装扩展。 要允许其他用户安装扩展 而 无需将其添加到这些特权角色中,可以将其指定为扩展管理者。 此分配通过前往 组织设置 | 常规 | 扩展 | 安全 (右上角) | 添加,然后将用户或组添加为管理员(图 6**.27)。

图 6.27 – 在 Azure DevOps 中添加扩展管理者

图 6.27 – 在 Azure DevOps 中添加扩展管理者

没有扩展安装权限的用户可以提交扩展请求(图 6**.28)。 项目集合管理员随后通过电子邮件收到这些请求的通知。 在批准后,Azure DevOps 会自动安装请求的扩展。 要提交请求,用户必须在 他们的组织内拥有贡献者角色。

图 6.28 – 在 Azure DevOps 中请求将扩展添加到组织的用户体验

图 6.28 – 在 Azure DevOps 中请求将扩展添加到组织的用户体验

现在我们 已经了解了如何保护我们的构建服务和工作节点,接下来让我们回顾一下如何将安全评估集成到 构建过程中。

解决常见的编码安全问题

将 安全性集成到 CI 和构建阶段有助于发现以前源代码分析可能遗漏的漏洞。 这对于捕捉那些绕过提交前或源控制检查的风险非常有帮助,无论是由于上下文不足,还是因为开发人员可能跳过了这些检查。 这一点尤其重要,因为有些问题只有在代码被编译、链接或在 特定环境中运行时才会显现。

软件的动态特性意味着在构建和集成过程中,代码会与各种依赖项、库和运行时环境交互,从而可能引入通过仅评估源代码无法发现的漏洞。 在构建过程中添加的第三方组件可能带来其自身的安全风险。 一些安全问题,例如缓冲区溢出或编译语言中的内存管理问题,可能只在编译和链接时显现。 此外,构建过程通常涉及配置文件和环境设置,这可能导致因配置错误而产生安全问题。 这些问题可能源自错误配置。

在构建阶段集成安全性解决了许多在早期开发阶段已涉及的问题,但在更全面的背景下进行处理。 这包括对第一方和第三方代码进行漏洞扫描,检测潜在的秘密泄露,并评估许可证合规性。 这些检查与早期执行的检查类似,但由于所有组件的完全集成,它们在构建阶段可以更为全面。 所有组件的完整集成使得这些检查更加彻底。

构建阶段还引入了额外的安全措施机会。 可以执行恶意软件评估,以确保在开发过程中或通过第三方依赖项未意外引入恶意代码。 运行时环境检查 也可以在此阶段进行,允许团队识别只有在其 预期环境中执行软件时才可能出现的潜在安全问题。

实施 Microsoft Security DevOps 扩展

将安全检查集成到构建过程中时,工具通常作为命令行实用程序或市场扩展提供。 市场扩展简化了整个组织范围内工具的采用,但在 DevOps 平台之间的兼容性可能有限。 命令行工具提供更大的灵活性,但通常需要在构建工作器上安装,可以在工作流程中或作为自托管 工作器镜像的一部分安装。

对于 Azure DevOps,微软提供了一个名为 Microsoft Security DevOps的扩展,将多个静态分析工具集成到构建和部署管道中,用于安全评估。 图 6**.29 展示了该扩展中捆绑的工具列表。 Microsoft Security DevOps 扩展中的某些工具具有商业版本,其功能显著优于包含的开源选项。 例如,Trivy 有一个商业版本,在此比较中详细说明: https://github.com/aquasecurity/resources/blob/main/trivy-aqua.md。Palo Alto Networks 的 Checkov 在 Prisma Cloud 内的商业版本与开源版本相比,也具有更多功能。

图 6.29 – Microsoft DevOps 扩展工具

图 6.29 – Microsoft DevOps 扩展工具

要实现 Microsoft Security DevOps 扩展,首先在 Azure DevOps 组织中安装它。 然后,通过添加执行所需安全检查的任务将该扩展集成到流水线中。 配置任务参数以指定要运行的工具和任何自定义设置。 最后,将任务结果集成到构建过程中,可能通过设置质量门或基于 安全发现生成报告。

这种方法允许在 Azure DevOps 管道中进行全面的安全扫描,使用一套精选的开源 分析工具。

将 GitHub 高级安全代码扫描功能集成到管道中

另一个 可以作为构建阶段安全评估一部分实施的 解决方案是 GitHub 高级安全GHAS)代码扫描,用于检测第一方代码漏洞。 在 GitHub 工作流中实施 GHAS 代码扫描或 GitHub 高级安全用于 Azure DevOpsGHAzDO)代码扫描,步骤相似。 对于这两个平台,我们可以按照以下顺序实施 CodeQL 操作/任务:

  1. github/codeql-action/init 操作。 对于 Azure DevOps,相应的管道任务是 AdvancedSecurity-Codeql-Autobuild。此步骤涉及指定我们希望 CodeQL 分析的编程语言和用于分析的规则集(称为 CodeQL 查询套件)。 可用于分析的语言选项包括 C#、C++、Go、Java、JavaScript、Python、Ruby 和 Swift(注意:Swift 支持在本文撰写时处于 beta 阶段)。 对于 CodeQL 查询套件(规则集),我们可以选择以下选项:

    • code-scanning:这是 CodeQL 代码扫描使用的默认规则集。 此规则集中的查询比其他规则集具有更好的准确性和更少的误报。 它旨在检测严重的安全问题,并尽量减少 不正确的警报。

    • security-extended:此规则集包括来自默认套件的所有查询,以及额外的查询,这些查询的准确性稍差,严重性也较低。 这个规则集可能会检测到更多的安全问题,但也可能导致误报或低严重性检测的增加。 例如,它可能会标记出那些具有轻微安全风险或不太可能构成 重大威胁的代码模式。

    • security-and-quality:此规则集包括来自 security-extended 套件的所有查询,并添加了检测代码质量问题的查询。 该规则集不仅评估安全性,还评估如死代码、重复代码或其他可能使软件更难维护和演化 的编码模式。

    • security-experimental:该规则集包括正在开发中的查询或由社区提供但尚未成为之前描述的主要查询套件一部分的查询。 此规则集中的查询可能不稳定,并可能发生变化或产生不可预测的结果。 不建议将此查询套件用于生产用例(可以在测试/开发中使用)。

    图 6**.30 展示了 GitHub 工作流中的这一步骤(标记为 1)以及 Azure DevOps 流水线(标记为 2*)。

图 6.30 – CodeQL 初始化示例

图 6.30 – CodeQL 初始化示例

  1. github/codeql-action/autobuild 动作。 对于 Azure DevOps,相应的流水线任务是 AdvancedSecurity-Codeql-Autobuild。此步骤以某种方式编译或解释代码,为详细分析做好准备。 它确保 CodeQL 工具能够分析代码库的构建产物。 自动构建过程会根据代码库的编程语言有所不同,针对 C#、C++、Go、Java、JavaScript、Python、Ruby 和 Swift 等语言有特定的构建程序。 此步骤是自动化的,但如果默认的构建过程不适合 项目的需求,可以进行自定义。

  2. github/codeql-action/analyze 动作。 对于 Azure DevOps,相应的任务是 AdvancedSecurity-Codeql-Analysis 流水线任务。 此步骤对代码进行深入分析,以识别潜在的安全漏洞或代码质量问题,分析基于在初始化步骤中选择的规则集(查询套件)。 分析利用在构建过程中生成的 CodeQL 数据库,通过查询代码库,寻找与已知漏洞或不良编码实践匹配的模式。 分析结果将被汇总成报告,突出显示检测到的任何安全问题或代码质量问题。 这使得开发人员能够在 代码 部署之前解决这些问题,从而提高 软件的安全性和质量。

将 GHAS 依赖性扫描功能集成到流水线中

GHAzDO 提供了 可以集成到管道中的依赖项扫描功能。 在 YAML 管道中,我们可以使用 AdvancedSecurity-Dependency-Scanning 任务,如 图 6**.31所示。

图 6.31 – 在 Azure DevOps 管道中实现 GHAzDO 依赖项扫描

图 6.31 – 在 Azure DevOps 管道中实现 GHAzDO 依赖项扫描

让我们看看实际操作 如何进行。 我们 现在将 在 Azure DevOps 上执行这些安全扫描。

实操练习 – 在构建阶段集成安全性

在本次练习中,我们 将在管道的构建阶段集成安全性。 我们将实际集成 SAST、 软件组成分析(SCA) 和秘密扫描,使用一些工具,例如 GitHub 高级安全(GHAS)。我们 还将启用 Microsoft Defender for Cloud 中的 DevOps 安全性。

以下是实操练习:

  • 练习 1 – 将 SAST、SCA 和秘密扫描集成到 构建流程中

  • 练习 2 – 将你的 DevOps 平台接入 Microsoft Defender for Cloud 中的 DevOps 安全性

先决条件

在深入安全任务之前,首先创建一个测试环境和应用程序运行所需的服务连接。

任务 1 – 创建测试环境

  1. 导航至 你的 DevOps 实例(https://dev.azure.com),并选择你在 上一章中使用的组织。

  2. 选择我们在 eShopOnWeb 私有项目中使用的项目, 该项目在上一章中介绍过。

  3. 导航至 管道 ,然后 选择 环境

图 6.32 – 创建一个新环境

图 6.32 – 创建新环境

  1. 选择 创建环境

图 6.33 – 创建环境

图 6.33 – 创建环境

  1. 添加新环境的名称和 描述,然后点击 创建 按钮。

图 6.34 – 创建测试环境

图 6.34 – 创建测试环境

  1. 让我们通过导航到右上角的菜单()并 选择然后 安全性

图 6.35 – 设置测试环境的安全性

图 6.35 – 设置测试环境的安全性

  1. 导航到 管道权限 部分。 点击 : 按钮,然后 打开访问权限。这 将允许项目中的所有管道使用 该资源。

图 6.36 – 设置管道权限

图 6.36 – 设置管道权限

现在让我们创建 服务连接。

任务 2 – 创建 Azure 资源管理器服务连接和 Docker 注册表服务连接。

  1. 导航到 项目设置 然后 服务连接

图 6.37 – 设置服务连接

图 6.37 – 设置服务连接

  1. 选择创建服务连接 并从选项中选择 Azure 资源管理器 ,然后 点击 下一步

图 6.38 – Azure 资源管理器服务连接

图 6.38 – Azure 资源管理器服务连接

  1. 接下来,我们选择 认证类型为 服务主体(自动) 然后 选择 下一步

图 6.39 – 设置认证类型

图 6.39 – 设置认证类型

  1. 接下来,选择订阅并为其命名为服务连接名称 eShopOnWeb,然后 选择 保存

图 6.40 – 设置订阅和服务连接名称

图 6.40 – 设置订阅和服务连接名称

确保正确命名 服务连接,因为这是在 YAML 管道中设置的名称。

  1. 打开 eShopOnWeb 服务连接,选择右上角的菜单图标(),然后点击 安全性

图 6.41 – eShopOnWeb 服务连接安全设置

图 6.41 – eShopOnWeb 服务连接安全设置

  1. 管道权限下,点击 ⋮ 按钮,然后选择 开放访问 选项。 这将允许项目中的所有管道使用 此资源。

图 6.42 – eShopOnWeb 服务连接管道权限

图 6.42 – eShopOnWeb 服务连接管道权限

  1. 要设置正确的权限,首先复制服务主体的显示名称,显示名称可以通过点击 管理服务主体 找到,如 图 6**.41所示。

  2. 然后前往 Azure 门户,打开 Azure Bash CLI 并运行以下命令:

     subscriptionId=$(az account show --query id --output tsv)
    echo $subscriptionId
    spId=$(az ad sp list --display-name <your service principal display name> --query "[].id" --output tsv)
    echo $spId
    roleName=$(az role definition list --name "User Access Administrator" --query "[0].name" --output tsv)
    echo $roleName
    
  3. 接下来输入以下命令:

     az role assignment create --assignee $spId --role $roleName --scope /subscriptions/$subscriptionId/resourceGroups/DevSecOps-Book-RG
    

现在,让我们设置管道 ,进行安全扫描并部署 Azure 资源。

练习 1 – 将 SAST、SCA 和秘密扫描集成到构建过程中

此任务的目的是将 GHAS 集成到 Azure DevOps 中并执行 静态应用程序安全测试 (SAST),使用 GHAS 的代码扫描、使用依赖扫描进行的软件组成分析,以及使用秘密扫描进行的秘密识别。 秘密扫描有两个组件:推送保护(我们在上一章中已经讲解)和 仓库扫描。

在上一章中,我们通过导航到 项目设置 | 仓库 | 高级安全性,启用了高级安全性。在本章中,我们将在管道中配置代码扫描和依赖扫描。

首先,我们需要确保设置了正确的 高级安全 权限。 图 6**.43 显示了需要启用的权限。 导航至 安全 然后 项目管理员 并 设置 高级安全 权限 为 允许

图 6.43 – 设置高级安全权限

图 6.43 – 设置高级安全权限

我们将首先设置依赖扫描,然后是代码扫描。 这两项扫描将在您的管道中设置,不同于机密扫描,它是通过门户设置进行配置的(项目设置 | 代码库 | 仓库 | eShopOnWeb | 设置 | 高级安全(阻止机密 推送时))。

让我们创建一个管道,在其中配置依赖扫描和 代码扫描:

  1. 导航至 管道 | 管道 | 创建管道

图 6.44 – 创建管道

图 6.44 – 创建管道

  1. 选择您的代码位置, azure-pipelines.yml。我们将在这个管道中配置所有的依赖扫描和代码扫描任务。 这些 任务已被添加到 azure-pipelines.yml 文件中。

    任务如下: 如下一项:

  2. 在添加正确的服务连接名称、Azure 订阅 ID、Azure 资源组名称和位置后,继续运行管道,信息应位于 azure-pipelines.yml文件中的 variables 部分。

    构建阶段大约需要 10 分钟完成。 点击各个任务查看 详细信息。 我们可以看到,依赖扫描和 CodeQL 任务 已经成功。

图 6.45 – 构建阶段成功

图 6.45 – 构建阶段成功

我们可以在Repos | 高级安全性下查看依赖扫描和代码扫描的结果。

图 6.46 – 高级安全性

图 6.46 – 高级安全性

现在,高级安全 仪表盘显示了在依赖扫描 和代码扫描任务中发现的漏洞。 浏览 依赖代码扫描机密 标签。

图 6.47 – 高级安全仪表盘

图 6.47 – 高级安全仪表盘

我们现在已成功 完成了 Azure DevOps 上的 SAST、SCA 和机密扫描。

练习 2 – 将你的 DevOps 平台引入 Microsoft Defender for Cloud 中的 DevOps 安全

在本练习中,我们将把我们的 GitHub 企业组织和 Azure DevOps 组织连接到 Microsoft Defender for Cloud。 Microsoft Defender for Cloud – Defender CSPM 计划具有一个 DevOps 安全 功能。

图 6.48 – 练习环境

图 6.48 – 练习环境

要完成这些练习,你需要访问 Azure 订阅,如果你还没有现有订阅,我将指导你如何注册一个。 如果你有可以使用的现有订阅,可以跳过 任务 1 部分。

  • 任务 1 – 启用 Microsoft Defender for Cloud 免费试用 试用

  • 任务 2 – 将你的 GitHub 企业组织连接到 Microsoft Defender for Cloud

  • 任务 3 – 将你的 Azure DevOps 组织连接到 Microsoft Defender for Cloud

任务 1 – 启用 Microsoft Defender for Cloud 免费试用

要设置免费试用订阅,请按照以下步骤操作:

  1. 打开浏览器窗口并访问 到 https://portal.azure.com/

  2. 使用你的凭证登录。

  3. 在顶部的搜索菜单中,搜索 Microsoft Defender for Cloud (1),然后选择 Microsoft Defender for Cloud 服务(2)。

图 6.49 – 搜索 Microsoft Defender for Cloud

图 6.49 – 搜索 Microsoft Defender for Cloud

现在,让我们将 GitHub 环境添加到 Microsoft Defender for Cloud。

任务 2 – 将你的 GitHub 企业组织连接到 Microsoft Defender for Cloud

  1. Microsoft Defender for Cloud 窗口中,选择 环境设置 (在 管理 部分).

  2. Microsoft Defender for Cloud | 环境设置 窗口中,选择 +添加环境,然后 选择 GitHub

图 6.50 – 添加新的 GitHub 环境

图 6.50 – 添加新的 GitHub 环境

  1. GH-Ent-Connector

  2. 订阅: 选择你的 Azure 订阅

  3. 资源组: 创建新 | DevSecOpsRG | 确定

  4. 位置: 选择以下区域之一 – 东美国, 中美国, 西欧洲, 英国南部, 澳大利亚东部, 东亚

  5. 点击 上 下一步:配置 访问 >

图 6.51 – GitHub 连接配置

图 6.51 – GitHub 连接配置

  1. 配置访问 窗口中,在 授权 DevOps 安全下,点击 授权 以授予你的 Azure 订阅访问你的 GitHub 仓库的权限。 将会打开一个新窗口(如果你的浏览器设置为 阻止弹出窗口,你可能需要允许弹出窗口)。

  2. 如果需要,使用具有对你希望保护的仓库访问权限的帐户登录 GitHub。 点击 授权 Microsoft Security DevOps

图 6.52 – 授权 Microsoft Security DevOps

图 6.52 – 授权 Microsoft Security DevOps

  1. 仍在 配置访问 窗口中,在 安装 DevOps 安全应用下,点击 安装 以安装 GitHub 应用程序。 将弹出一个新窗口(如果您的浏览器设置为 阻止弹出窗口,您可能需要允许弹出窗口)。

图 6.53 – 安装 DevOps 安全应用

图 6.53 – 安装 DevOps 安全应用

  1. 安装 Microsoft 安全 DevOps 窗口中,选择您要加入的 GitHub 组织 。

图 6.54 – 选择要加入的 GitHub 组织

图 6.54 – 选择要加入的 GitHub 组织

  1. 选择 所有仓库,审核将授予的权限,然后点击 安装。如果提示完成 MFA 请求,请输入您的 认证码,然后 点击 验证

图 6.55 – 选择所有仓库

图 6.55 – 选择所有仓库

  1. 返回到 GitHub 连接 窗口,点击 下一步:审核并 生成 >

图 6.56 – 点击“审核并生成”

图 6.56 – 点击“审核并生成”

  1. 审核并生成 窗格中,点击 “创建” 。

任务 3 – 将您的 Azure DevOps 组织连接到 Microsoft Defender for Cloud

按照以下步骤操作:

  1. 打开浏览器窗口并访问 至 https://portal.azure.com/

  2. Microsoft Defender for Cloud 窗口中,选择 环境设置 (在 管理 部分)。

  3. Microsoft Defender for Cloud | 环境设置 窗口中,选择 +添加环境,然后选择 Azure DevOps

图 6.57 – 添加 Azure DevOps 环境

图 6.57 – 添加 Azure DevOps 环境

  1. AzDevOps-Connector

  2. 订阅:选择你的 Azure 订阅

  3. 资源 DevSecOpsRG

  4. 位置:选择以下区域之一 – 东部美国中部美国西欧英国南部澳大利亚东部东亚

  5. 点击 下一步:配置 访问 >

图 6.58 – Azure DevOps 连接设置

图 6.58 – Azure DevOps 连接设置

  1. 配置访问 窗口中,点击 授权 DevOps 安全,点击 授权 以 授予你的 Azure 订阅访问 Azure DevOps 组织的权限。 将打开一个新窗口(如果浏览器设置为阻止弹出窗口,你可能需要允许弹出窗口)。

  2. 登录到你的 Azure DevOps 组织(如果提示)。 检查将要授予的权限,然后点击 在 接受

图 6.59 – 审核将要授予的权限

图 6.59 – 审核将要授予的权限

  1. 仍然在 配置访问 窗口中,点击 下一步:审核并 生成 >

图 6.60 – 审核并生成连接

图 6.60 – 审核并生成连接

  1. 审核并生成 窗口中,点击 创建 以创建 连接。

图 6.61 – 创建 Azure DevOps 连接

图 6.61 – 创建 Azure DevOps 连接

附加练习

在将 Azure DevOps 组织添加到 Microsoft Defender for Cloud 后,配置 Microsoft 安全 DevOps Azure DevOps 扩展。 按照 Microsoft DevOps 安全的指南 此处: https://learn.microsoft.com/en-us/azure/defender-for-cloud/azure-devops-extension

配置 此扩展后,您将在 Microsoft Defender for Cloud 中获得更多的安全洞察。 图 6**.62 显示了 Microsoft Defender 中的 DevOps 安全发现 for Cloud。

图 6.62 – Microsoft Defender for Cloud 中的 DevOps 安全发现

图 6.62 – Microsoft Defender for Cloud 中的 DevOps 安全发现

恭喜! 您 已成功完成本章的实践练习。

总结

在本章中,我们探讨了如何强化构建过程以提高安全性,并讨论了如何利用 GitHub 高级安全功能评估和解决构建管道中常见的编码安全问题。 我们讨论了如何保护构建服务和工作节点的访问权限,防止恶意代码对构建环境的威胁,并实施代码和 依赖扫描。

在下一章中,我们将讨论如何在 DevSecOps 的测试和发布阶段实施安全性,以将完整性引入软件发布过程,并确保只有通过关键安全标准的代码才会被发布。 敬请期待! 再见!

第七章:在 DevOps 的测试和发布阶段实现安全性

测试阶段的目标是确保编译后的应用程序提供预期功能,并且不包含在构建阶段未检测到的任何错误。 发布阶段的目标是为将测试过的应用程序准备并交付部署到生产或其他目标环境。 根据项目的发布策略,测试和发布阶段通常是重叠的。 通常,软件会先发布到预生产环境进行自动化运行时测试,使用如 Selenium 等工具,然后再发布到生产环境。 在本章中,我们将讨论 DevSecOps 实践,确保并将安全集成到这些阶段中。 在本章结束时,您将理解以下关键 安全实践:

  • 确保发布构件是从 受保护的分支构建的

  • 实现代码 审查流程

  • 选择一个安全的 构件源

  • 实现验证 构件完整性的过程

  • 在 发布阶段安全地管理机密

  • 使用 发布门禁 来验证并强制执行运行时安全

让我们 开始吧!

技术要求

要跟随本章的说明,您将需要 以下内容:

  • 一台配有 互联网连接的 PC

  • 一个有效的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

了解 DevOps 的持续部署阶段

持续部署(CD) 是 DevOps 实践之一,成功集成并通过自动化测试的代码更改会自动过渡到生产环境。 这一阶段的活动包括将代码打包成可部署的格式,将包存储在构件库中,并在其最终过渡到生产 运行时环境之前,在预生产运行时环境中验证软件。

该过程确保新特性、错误修复和更新能够快速且持续地交付给用户,无需人工干预,从而实现从开发到部署的无缝流转。 成功的持续交付(CD)的关键在于一个强大的自动化测试框架,能够验证更改并确保应用程序在 实际环境中的稳定性和可靠性。

图 7**.1 展示了一个简化的 DevOps CD 过程示例。 在该场景中,一个标记为 APP:V1的应用程序包从构建过程中发布到工件库。 新包的创建启动了一个 CD 流水线,该流水线会自动将其部署到暂存环境中进行测试。 测试成功通过后,包被部署到生产环境中,供 最终用户访问。

图 7.1 – 持续交付示例场景

图 7.1 – 持续交付示例场景

在 CD 阶段实施安全性包括安全存储发布工件,在发布前验证其安全性,确保 运行环境的安全性在软件部署前得到保障,并使用 基础设施即代码 (IaC) 自动配置运行环境的安全性。 让我们回顾一下 这些领域。

在发布阶段保护发布工件

DevOps 过程注重速度和灵活性。 其目标是消除可能减缓 市场速度的障碍。 通常情况下,代码更改会在几分钟内从开发者的工作区移动到生产环境 ,主要依靠自动化,且几乎没有人工检查。 阅读那些在 DevOps 实践上更为成熟的组织的部署数据令人印象深刻。 例如,Netflix 维持着超过 600 个生产环境中的服务,每天进行约 100 次部署;Uber 运营着超过 1,000 个生产环境中的服务,每周进行几千次部署;WeChat 生产环境中的服务超过 3,000 个,每天大约进行 1,000 次 部署!

注意

若要了解如 Netflix、Uber 和微信等公司的部署速度信息,请参阅此文档

为了在发布阶段集成安全性,首先需要审查您的 CI/CD 流程,确保没有任何人(无论是个人还是应用程序)能够在没有严格审查和批准的情况下部署代码更改或新的工件。审查应包括自动化检查和人工审核。遵循零信任原则,您必须假设攻击者最终可能会获得对 CI/CD 流程中某个系统的访问权限(如源代码控制、CI 系统或工件库)。为了解决这个问题,我们需要实施措施,防止任何单一实体独立推送代码更改或通过发布管道发布工件。

确保发布工件是从受保护的分支构建的

实现 DevOps 测试和发布阶段的安全性始于对将要部署的工件的安全性——我们称之为发布工件

注意

发布工件是已打包并准备好部署的软件或软件组件。工件根据技术栈和目标部署平台的不同而有所不同。例如,Java 应用通常打包为.dll.exe文件,它们是编译后的代码工件,部署后在 .NET 运行时上运行。在 JavaScript 或 Node.js 项目中,package.json文件。对于 Python 应用,.whl文件是一种更现代的打包格式,旨在替代 egg 文件。它们促进了 Python 库和应用的分发和安装。对于容器化解决方案,应用被打包为容器镜像。

一个好的起点是保护所有用于创建这些发布工件的分支。在 GitHub Enterprise 中,可以使用分支保护规则来实现,在 Azure DevOps 中,则可以使用分支策略来实现。

要在 GitHub Enterprise 中实现,请导航至 仓库设置,然后 代码与自动化 | 分支 | 分支保护规则,然后点击 添加规则图 7**.2 显示了一个用于保护包含“release”字样的分支的示例分支保护规则。 这需要管理员权限或具有 编辑仓库 规则 权限的自定义角色。

图 7.2 – GitHub Enterprise 中的示例分支保护规则

图 7.2 – GitHub Enterprise 中的示例分支保护规则

要在 Azure DevOps 中实现,请转到 项目设置 | 仓库 | Repositories,选择一个 仓库,选择 策略 | 分支策略,并选择一个 分支 (注意,您可能需要滚动才能看到分支列表)。 图 7**.3 显示了 Azure DevOps 中的分支策略示例。 这需要管理员权限或具有 编辑 策略 权限的自定义角色。

图 7.3 – Azure DevOps 中的示例分支保护规则

图 7.3 – Azure DevOps 中的示例分支保护规则

总体而言,这两个平台提供了类似的分支保护功能。 GitHub Enterprise 可能没有 直接的构建验证和人工审核分支保护设置,但这些功能可以通过其他方法实现(见 图 7**.4)。 一个显著的区别是 Azure DevOps 不支持要求提交签名,而 GitHub Enterprise 支持这一功能。 关于这两个平台之间分支保护功能的详细比较,请参见 图 7**.4

图 7.4 – 分支保护功能比较

图 7.4 – 分支保护功能比较

遵循零信任原则,我们还希望确保对所有人(包括管理员)强制执行分支保护策略。 这一点非常重要,因为管理员帐户通常会成为账户劫持的目标,原因是它们的 特权角色。

采用零信任方法,适用于所有主要发布分支,只有在极少数情况下才允许例外。

在 GitHub Enterprise 中,我们可以激活 不允许绕过上述设置 选项,作为我们的分支保护规则的一部分(参见 图 7**.5)。

图 7.5 – 在 GitHub Enterprise 中强制执行所有人的分支保护设置

图 7.5 – 在 GitHub Enterprise 中强制执行所有人的分支保护设置

在 Azure DevOps 中没有类似的设置,但我们可以限制或审计有权限绕过拉取请求和推送策略的角色/用户。 默认情况下,没有任何角色,包括管理员,拥有这些权限(参见 图 7**.6)。 要在 Azure DevOps 中查看权限,导航至 项目设置 | 代码库 | 仓库,选择一个 仓库,然后选择 安全,并检查 完成拉取请求时绕过策略推送时绕过策略 (图 7**.6)。 该权限也可以在分支级别配置,而不是在 仓库级别。

图 7.6 – 在 Azure DevOps 中查看绕过分支保护策略的权限

图 7.6 – 在 Azure DevOps 中查看绕过分支保护策略的权限

如果 管理员帐户被攻破,分支保护设置可能会被禁用,允许攻击者绕过必需的检查,快速将恶意代码更改推送到生产环境。 因此,跟踪和审计分支保护及敏感权限的更改非常重要,以便发现异常的绕过尝试。 图 7**.7 展示了在 GitHub Enterprise 中修改敏感分支保护设置的审计日志条目的示例。

图 7.7 – 修改敏感分支保护设置的示例日志条目

图 7.7 – 修改敏感分支保护设置的日志示例

有关启用审计的信息,请参考 确保构建环境已记录 部分内容,详见 第六章

实施代码审查流程

另一个好的安全措施是要求对发布分支 和部署工作流/管道配置文件进行人工审查。 这应该作为代码与发布分支合并前强制执行的自动化安全扫描之外的额外措施。 自动化扫描是有用的,但可能会被绕过,因此需要人工检查。 即使实施了必要的控制,也可能会发现新的绕过方法。 包括经验丰富的人工审阅者提供了一层额外的防护,防止潜在的 恶意攻击。

GitHub Enterprise 和 Azure DevOps 平台都支持细粒度的代码审阅实施,我们可以为代码库的不同路径分配不同的审阅者。 在 Azure DevOps 中,这可以通过分支保护控制实现,而在 GitHub Enterprise 中,则可以通过分支保护控制 结合 一种名为 CODEOWNERS的功能来实现。

要在 Azure DevOps 中启用细粒度代码审查,请导航至 项目设置,然后选择 仓库,接着点击 仓库。选择一个仓库,点击 策略,然后滚动到 分支策略 部分,找到你的发布分支。 在 分支策略下,激活 要求最低数量的审阅者 并将其设置为 开启。输入所需的审阅者数量,并从可用选项中选择(图 7**.8)。

图 7.8 – 在 Azure DevOps 中启用人工代码审查

图 7.8 – 在 Azure DevOps 中启用人工代码审查

我们还可以 自动向拉取请求中添加审查者,审查那些更改特定目录和文件中的内容的文件。 例如,我们可能希望将安全团队的成员添加为审查者,以审查任何对管道文件的更改,或者将开发团队中的安全冠军添加为审查者,以审查发布分支的代码更改。 我们可以通过配置选项来实现这一点, 自动添加审查者 (图 7**.9)。

图 7.9 – 在 Azure 仓库分支策略中添加必需的审查者

图 7.9 – 在 Azure 仓库分支策略中添加必需的审查者

如果设置标记为 必需,则每个列为审查者的个人必须批准更改。 如果将小组名称添加为审查者,则每个小组至少需要有一个成员 批准更改。 如果只需要一个小组的批准,那么所需的批准数就是该小组指定的最小数量。 例如,可以为每个开发团队组成一个小组,其中包括该团队的安全冠军,而该小组将作为审查者。 这可以确保至少有一个具有安全经验和培训的人在批准之前审查代码更改。 被批准。

对于 GitHub Enterprise,我们可以启用一个分支保护规则,在合并之前要求拉取请求,通过选择 CODEOWNERS 文件 (图 7**.10)。

图 7.10 – 在 GitHub Enterprise 分支保护策略中启用代码拥有者审查

图 7.10 – 在 GitHub Enterprise 分支保护策略中启用代码拥有者审查

CODEOWNERS

CODEOWNERS 是 GitHub 的一个功能 ,我们可以用它指定负责维护项目特定部分的个人或团队。 当对这些部分进行更改时,指定的代码拥有者会自动被要求审查并批准这些更改,才能合并。 我们可以使用此功能为发布分支和部署 工作流文件实施代码审查。

要使用 CODEOWNERS,我们需要在 CODEOWNERS 文件中创建一个文件,文件路径为 .github/根目录,或 docs/ 仓库目录。 该文件使用一种模式,遵循大多数(但不是所有)在 gitignore 文件中使用的规则。 例如, /workflows/ @dev @security 这一行条目的含义是,任何位于 /workflows 目录中的更改都需要 @dev 或 @security 团队成员的批准,但不需要两个团队都批准。

一行条目 **/releases @securitychampions @teamleaders 的含义是 @securitychampions@teamleaders 团队拥有 /releases 目录中的任何文件。 要 了解有关 CODEOWNERS 文件的更多信息,请参阅以下文档: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax

现在我们了解了确保发布构件仅来自经过验证代码的一些控制措施,接下来让我们探讨这些构件的安全存储。

选择安全的构件源

DevOps 测试和发布阶段的另一个关键安全最佳实践是确保将要部署的构件 的安全性。 这些构件应存储在可信的位置,以维护其完整性 并防止篡改。 GitHub Actions 和 Azure Pipelines 都支持从多种来源部署构件,例如构建环境、软件包仓库、容器仓库、文件共享和源代码控制仓库。 图 7**.11 显示了经典 Azure 发布管道支持的构件源的截图。

DevSecOps 要求我们仅使用支持 不变性可追溯性访问控制的工件源。不变性通过确保 工件的内容从发布、进行安全测试到最终发布到生产环境时不会发生变化,从而保证完整性。 这可以在工件源级别或包级别实现。 在源级别实现意味着我们的工件源一旦发布后,不应允许对包进行任何修改。 要纠正任何问题,应该发布新版本,而不是修改现有版本。 这确保了已进行安全测试的工件内容与实际部署的工件内容相同。 像文件共享、 Azure 容器注册表ACR)和 GitHub 包等来源应谨慎使用,因为它们默认是可变的。 任何拥有正确权限的人都可以更新存储在这些源中的已发布工件的内容。 攻击者可以利用这一点,在部署前将原版本替换为已被篡改的版本。 。

图 7.11 – 经典 Azure 发布管道的支持工件源

图 7.11 – 经典 Azure 发布管道的支持工件源

对于 ACR,我们可以 通过配置镜像锁定,在工件存储级别强制实施不变性。 这是通过使用 az acr repository update 命令来实现的。 图 7**.12 展示了一个使用此命令将新的容器镜像锁定在构建和 发布阶段的 GitHub 工作流示例。

图 7.12 – 带 ACR 镜像锁定的 GitHub 工作流示例

图 7.12 – 带 ACR 镜像锁定的 GitHub 工作流示例

不变性是选择工件源时需要考虑的几个因素之一。 其他重要的因素包括可追溯性和版本控制。 可追溯性使我们能够查看包的来源,并将其与代码更改、测试用例和工作项关联起来。 这使得在发生安全漏洞时,进行法医审计变得更加容易。 版本控制使我们能够在不同版本的工件之间跟踪安全结果,并在面临重大 零日漏洞时,快速回滚到安全版本。

对 可追溯性和版本控制的支持因工件来源而异。 例如,文件共享是基本的存储解决方案,通常缺乏内建的版本控制和源控制的可追溯性。 在文件共享中实现这些功能通常需要额外的工具或 自定义配置。

一般来说,文件共享不推荐作为 DevOps 工作流中的工件来源。 工作流/管道工件本身通常包含这些功能,而 ACR、GitHub Packages 和 Azure Artifacts 可能还需要 额外的配置。

理解工作流/管道工件

GitHub Actions 和 Azure Pipelines 都支持将工件发布到构建平台内部的选项。 对于 GitHub Actions, upload-artifact 操作可以用来将工件上传到 Actions 工件 存储库(图 7**.13)。

图 7.13 – GitHub Actions 上传工件操作

图 7.13 – GitHub Actions 上传工件操作

对于 Azure Pipelines,可以使用 PublishPipelineArtifactPublishBuildArtifact 任务来实现相同的目的(图 7**.14)。

图 7.14 – Azure Pipelines 发布 Pipeline 工件任务

图 7.14 – Azure Pipelines 发布 Pipeline 工件任务

这些选项之所以受欢迎,是因为它们易于使用,但它们会影响不可变性和可追溯性。 因为这些工件存储在构建平台中,并且它们与创建它们的工作流/管道运行或作业有链接,因此在这种情况下,它们提供了内建的可追溯性。 然而,也应考虑保留策略和行为,以了解其整体影响。 例如,GitHub Enterprise 存储操作 工件 90 天,但这一期限可以延长至 400 天。 定制化可以在企业、组织或仓库级别进行(图 7**.15)。

图 7.15 – 配置 GitHub 工作流工件的保留期限

图 7.15 – 配置 GitHub 工作流工件的保留期限

在 GitHub Enterprise 中配置工件保留期

工件 的保留设置可以在以下不同级别进行定制: GitHub Enterprise:

  • 企业:前往 设置 | 策略 | 操作 | 策略 | 工件和 日志保留

  • 组织:前往 设置 | 代码、规划与自动化 | 操作 | 常规 | 工件和 日志保留

  • 仓库:前往 设置 | 代码与自动化 | 操作 | 常规 | 工件和 日志保留

选择的保留期限会影响可追溯性。 如果我们设置了 100 天的保留期,而我们需要下载 120 天前的某个工件以调查最近发现的漏洞,我们将无法做到这一点,除非我们已经将该工件转移到其他存储位置。 在 Azure Pipelines 中,删除管道运行也会删除所有关联的工件。 如果删除的工件稍后需要调查,这也可能会影响可追溯性。

从不变性的角度来看,GitHub upload-artifact 操作如果启用 覆盖 选项,可以覆盖工件(图 7**.16)。

图 7.16 – 实现工件覆盖

图 7.16 – 实现工件覆盖

如果开发人员 没有通过 ID 锁定发布工件,而是使用名称,那么可能会在工件交换攻击中被利用。 Azure Pipelines PublishPipelineArtifact@1 任务的行为与此不同。 它的设计目的是确保给定构建的工件不可变。 一旦发布,不能再发布另一个具有相同名称的工件。

注意

有关操作和任务行为的更多信息,请参阅 以下文档:

现在我们已经讨论了使用工作流/管道工件作为发布源的安全性问题,接下来让我们探讨独立服务的类似安全考虑。

理解 Azure Artifacts 和 GitHub Packages

GitHub Enterprise 和 Azure DevOps 都提供用于存储和管理 发布工件的独立服务。 GitHub Enterprise 提供 GitHub Packages,而 Azure DevOps 提供 Azure Artifacts。 这两项服务 都支持可以处理各种包类型(如 NPM、NuGet、Maven、Python 和 Universal 包)的源。 GitHub Packages 还支持 容器,而 Azure Artifacts 则 不支持。 Azure 提供 ACR 用于存储容器。 从安全性的角度来看,这两项服务是相似的(图 7**.17)。

图 7.17 – GitHub Packages 和 Azure Artifacts 中的安全考虑

图 7.17 – GitHub Packages 和 Azure Artifacts 中的安全考虑

GitHub Packages 和 Azure Artifacts 中的工件默认是不可变的。 一旦发布了某个版本的工件,它就不能被修改。 任何更新或修复必须作为新版本发布,从而确保已部署的工件与经过验证的工件一致。 Azure Artifacts 中的可追溯性主要通过与 Azure DevOps 服务的集成来管理。 每个工件都与特定的管道运行相关联,包含构建编号和关联的提交等详细信息。 这些数据对于重建工件的开发历史至关重要。 GitHub Packages 中的每个包都存储详细的来源信息,包括构建该包的提交 SHA、分支或标签。 这种详细程度对于合规性和 安全审计尤为重要。

实施工件签名以进行完整性检查

确保 DevOps 工作流的安全性涉及确保软件供应链中每个步骤的完整性。 如果攻击者突破了工件存储,他们可能篡改本应用于生产的包并上传未经授权的工件。 例如,在 CodeCov 事件中,攻击者利用泄露的凭证上传了一个有害的工件,导致用户直接下载。 一种缓解策略是强制执行所有发布工件的完整性验证过程。 这包括对包进行签名并在部署之前验证数字签名。 可以使用各种工具 和方法来实现这一点,但两个常见的 方法是 Sigstore 的 CosignNotation。我们来 回顾一下这些。

使用 Sigstore 的 Cosign 实现工件签名

Sigstore 是一套 旨在自动化软件工件的数字签名 和验证的开源工具 。它主要针对容器镜像和二进制文件等软件工件,但也可以用于任何文件类型,包括 ZIP 压缩包。 它结合了几种工具和技术,包括 以下内容:

  • Cosign:用于 签名和验证容器 及工件

  • Fulcio:一个免费的 根证书颁发机构,颁发 临时证书

  • Rekor:它将 签名元数据记录到 防篡改的分类账中

  • OpenID Connect:这是 身份验证

Sigstore

欲了解更多关于 Sigstore 项目的信息,请访问他们的官方网站 https://www.sigstore.dev/ 并探索他们的 GitHub 仓库 地址为 https://github.com/sigstore

Cosign (作为 Sigstore 项目中的工具之一) 通过使签名管理过程不可见,简化了软件工件(如容器镜像)的签名和验证。 它自动签署工件,将签名存储在 OCI 注册表中,并在无需用户干预签名处理的情况下执行验证。 在签署 Docker 镜像时,Cosign 会在 OCI 注册表中创建一个特殊的标签,将镜像的唯一摘要(其不可变标识符)纳入标签名称中。 这使得根据镜像的摘要轻松检索和验证镜像的签名。

要使用 Cosign,我们 首先 必须确保它已安装在用于我们的工作流/管道的 runner/agent 上。 对于 GitHub,可以使用 cosign-installer GitHub 市场任务(图 7**.18)。 对于 Azure DevOps,我们使用命令行步骤配合我们喜欢的操作系统包管理器,详情请参考 在 https://docs.sigstore.dev/system_config/installation/

图 7.18 – cosign-installer GitHub 市场任务

图 7.18 – cosign-installer GitHub 市场任务

步骤 是可选的。 我们可以使用 cosign generate-key-pair 命令生成将用于数字签名的密钥对。 这提供了更多的控制权,但也带来了密钥管理的复杂性。 Cosign 还支持无密钥签名,这种方法使用短暂的密钥并透明地记录签名过程。 这种方法通过消除密钥的直接管理,提高了安全性并简化了操作。 步骤 是使用 cosign sign 命令签名我们的工件。 步骤 是使用 cosign verify 命令验证签名,作为我们 部署前检查的一部分。

使用 Notation 实现工件签名

Notation 是另一个可以用于 对数字构件进行签名并验证其完整性和发布者的工具。 它是 Notary 项目的一部分,该项目是 一个由 云原生计算 基金会 (CNCF)的孵化项目。

Notary 项目

要了解 有关 Notary 项目的更多信息,您可以访问他们的官网 https://notaryproject.dev/ 并浏览他们的 GitHub 仓库 ,网址为 https://github.com/notaryproject

与 Sigstore 类似,它主要面向软件构件,如容器镜像和二进制文件,但也可以用于任何文件类型,包括 ZIP 文件。 数字构件可以在构建过程中进行签名,并在部署时验证其完整性和来源。 图 7**.19 提供了 Notation 如何集成到 DevOps 工作流中的高级概述。

图 7.19 – Notation 如何集成到 DevOps 工作流中

图 7.19 – Notation 如何集成到 DevOps 工作流中

要使用 Notation,我们 首先 必须确保它已安装在用于我们工作流/流水线的运行器/代理上。 对于 GitHub,可以使用 notation-action GitHub 市场动作来完成。 Azure DevOps 也有一个 Notation 市场任务,我们可以用来完成这个操作(图 7**.20)。

图 7.20 – Azure DevOps Notation 市场任务

图 7.20 – Azure DevOps Notation 市场任务

第二 是对我们的构件进行签名。 Azure Pipelines 中的 Notation 任务原生支持 Azure Key Vault 插件,这使得 Notation CLI 能够使用 Azure Key Vault 管理的证书和密钥生成签名(图 7**.21)。

图 7.21 – 在 Azure Pipelines 中实现 Notation

图 7.21 – 在 Azure Pipelines 中实现 Notation

它支持 使用自签名 证书进行签名和 notation sign 命令。 第三个也是最后一步是将签名作为预部署检查的一部分进行验证。 Notation 支持指定一个信任策略文件,定义我们希望强制执行的签名验证级别。 有四个 验证级别:

  • 严格:此设置 强制执行所有验证。 如果任何验证失败,则验证失败。 适用于构建环境或 高安全性部署。

  • 宽松:此设置 执行大部分验证,但记录诸如撤销和过期等问题。 适用于部署或运行时,当完整性和真实性 至关重要时。

  • 审计:仅 确保签名完整性(如果存在);记录其他 验证失败。

  • 跳过:此操作 不执行签名验证。 用于混合签名和未签名的工件,但需要指定确切的注册表 URL 在 registryScopes 中。

图 7**.22 展示了 四种级别(严格、宽松、审计和跳过)及其 各自的验证方式。

图 7.22 – Notation 的验证级别

图 7.22 – Notation 的验证级别

要了解 有关 Notation 信任策略文件的更多信息,请参考以下 文档: https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md

在发布阶段安全地管理密钥

在自动化构建和部署管道中,开发人员可能需要提供访问内部 或外部服务所需的凭证。 例如,从私有仓库下载代码的构建管道任务可能需要提供凭证。 另一个任务可能是从私有注册表下载包,必须提供必要的凭证。 在部署管道中,某个任务可能 需要 凭证以连接到托管的 Kubernetes 集群,部署最新版本的 应用程序。

注意

一个好的安全最佳实践是优先使用工作负载身份进行访问,而不是使用密钥。 例如,实施托管身份来访问 Azure 服务。 密钥应仅在工作负载身份尚未支持的场景中使用。

这些敏感凭证绝不应以明文存储在构建或部署流水线工作流文件中。 一种可行的选择是将凭证存储为加密的环境 变量。 这些在 GitHub Enterprise 中被称为 密钥 ,在 Azure Pipelines 中被称为 密钥变量。 在我们的讨论中,我们将其称为 密钥

在 GitHub 中,密钥可以在组织、仓库或仓库环境级别设置。 在 Azure DevOps 中,它们可以在项目(使用变量组)、流水线、阶段或作业级别设置。 组织/项目级别的密钥允许团队在多个工作流或流水线中共享密钥。 这减少了在多个仓库/流水线中创建重复密钥的需求。 密钥在静止时使用 2048 位 RSA 密钥加密,并可供任务和脚本在代理上使用。 。

在这两个平台上,具有读取权限的用户无法读取密钥,但具有写入权限的用户可以读取所有密钥。 为了减少密钥泄漏的风险,我们需要小心授予谁对我们仓库/项目的写入权限。

遵循零信任原则时,我们需要假设漏洞可能发生,并仅授予执行工作流/流水线所需的最小权限。 这种方法在用户的写入权限被泄露时,能减少潜在的影响。 例如,用于将应用程序部署到 Kubernetes 集群的密钥,应该只拥有该特定权限。 它不应该有权限修改集群中的其他配置。

GitHub Actions 和 Azure Pipelines 都尝试在日志输出中屏蔽秘密(图 7**.23)。 它们会查找在命令行中以纯文本形式打印的秘密,以及日志输出中秘密值的精确匹配。 然而,这个过程并不完美。 开发者仍然需要谨慎,防止 意外暴露。

图 7.23 – Azure Pipeline 日志中的屏蔽秘密

图 7.23 – Azure Pipeline 日志中的屏蔽秘密

例如,不推荐使用 JSON、XML 或 YAML 等结构化数据格式来定义秘密值。 这可能导致屏蔽失败。 一个例子是,如果秘密值被定义为 {"apikey": "secretpass"};如果该精确值以纯文本形式打印到控制台,它可能无法被屏蔽(图 7**.24)。 开发者应为每个敏感值创建单独的普通秘密,而不是将它们映射在结构化数据格式中,以确保它们在日志中能够被正确屏蔽。 在日志中。

图 7.24 – 由于结构化数据格式导致的未屏蔽秘密示例

图 7.24 – 由于结构化数据格式导致的未屏蔽秘密示例

此外,如果在工作流/管道中使用一个秘密来生成敏感值,生成的 值应注册为秘密,以 确保如果它出现在日志中时会被屏蔽。 例如,可能使用一个私钥来生成一个签名的 JSON Web TokenJWT)以访问 Web API。 该 JWT 应该注册为秘密,否则如果它被记录在工作流/管道日志输出中,它将不会被屏蔽。 类似地,如果一个秘密被以某种方式转换,例如被 Base64 编码或 URL 编码,它也应该注册为秘密,以确保如果它出现在 日志输出中时能够被屏蔽。

在你的 DevOps 管道中集成秘密保管库

除了在我们的工作流/管道中实现密钥管理外,我们还可以实现一些流程, 使用如 Azure Key Vault 或 HashiCorp Vault 等密钥管理服务来集中管理密钥。 这是首选方案,因为它具有可扩展性的优势,并且它允许将密钥管理与 DevOps 平台解耦。 正如我们之前提到的,更好的做法是,如果您的场景支持,过渡到使用工作负载身份。

Azure Key Vault 是一个密钥管理服务、证书管理服务和密钥管理服务。 A 密钥 是数据大小不超过 25 KB(对于标准保管库),可以以明文形式存储和检索。 例如,密码、数据库连接字符串和存储账户连接字符串。 密钥 是加密密钥(即使用算法生成的密钥),可以导入或在保管库中生成。 Key Vault 目前支持 RSA 和椭圆曲线密钥。 证书 是自签名的 SSL/TLS 证书,可以在 Key Vault 中生成,或是导入到保管库中的第三方 SSL/TLS 证书。 图 7**.25 展示了这三种对象类型的示例使用案例。

图 7.25 – 示例 Azure Key Vault 使用案例

图 7.25 – 示例 Azure Key Vault 使用案例

要将 Azure Key Vault 集成到我们的 GitHub Action 工作流中,我们可以实现 azure/get-keyvault-secrets 操作,该操作通过工作负载身份或服务主体进行身份验证。 在 Azure DevOps 管道中,此集成可以通过 AzureKeyVault 任务完成,该任务使用受托管身份或服务主体支持的服务连接(图 7**.26)。 对于这两种选项,我们需要确保访问权限仅限于所需的密钥。 这需要最小权限访问设计。

图 7.26 – 示例 Azure DevOps 与 Key Vault 集成

图 7.26 – 示例 Azure DevOps 与 Key Vault 集成

现在,让我们 回顾另一个关于确保构建/发布环境安全的最佳实践—— 实施审计。

为 CI/CD 环境实施审计

CIS 框架还建议在构建/发布环境中启用日志记录。 这对于安全性 监控、威胁检测和在发生事件时的取证分析至关重要。 理想情况下,日志记录应在控制平面启用,以进行管理操作,以及在 数据平面。

启用和配置控制平面日志记录

GitHub Enterprise Cloud (GHEC),我们 不需要 做任何事情来启用控制平面审计 日志。 它们默认已启用。 这些日志可以 在企业级别查看 通过 设置 | 审计日志 | 事件,或者在组织级别通过 组织 | 设置 | 归档 | 日志 | 审计日志 | 事件查看。默认情况下,只有最近三个月的事件可见,但事件会保存长达七个月,之后会被 删除。

这些日志 记录了一系列事件 ,包括分类在 orgworkflow下的工作流控制平面活动。 这包括诸如创建、更新、删除和执行 工作流等操作。 审计事件的完整列表可以在此查看: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/audit-log-events-for-your-organization

为了保护隐私,审计日志省略了事件的源 IP 地址。 要将源 IP 地址添加到审计日志中,可以在企业级别或 组织级别进行调整:

  • 企业级别:导航至 企业 | 设置 | 审计日志 | 设置。启用并保存 启用源 IP 披露 选项。

  • 组织级别:进入 组织 | 设置 | 存档 | 日志 | 审计日志 | 设置。启用并保存 启用源 IP 披露 选项。

图 7.27 – 启用源 IP 记录以进行审计日志

图 7.27 – 启用源 IP 记录以进行审计日志

为了将日志流式传输到外部,可能是为了将其保存超过最大保留期限,我们可以选择直接将日志流式传输到 Amazon S3、Azure Blob Storage、Google Cloud Storage、Splunk 和 Datadog。 我们还可以 通过 Azure Event Hub 将其流式传输到其他第三方服务。 这可以 通过 设置 | 审计日志 | 日志流式传输 | 配置流式传输

图 7.28 – 在企业级配置审计日志流式传输

图 7.28 – 在企业级配置审计日志流式传输

对于 Azure Pipelines,可以在 安全 | 策略 | 安全策略 | 日志 审计事件

图 7.29 – 启用审计日志记录

图 7.29 – 启用审计日志记录

启用此设置后,它会记录多个事件,包括 Azure Pipeline 控制平面事件 ,如管道创建、修改、删除和 执行。 可以在此处找到已审计的完整管道事件列表: https://learn.microsoft.com/en-us/azure/devops/organizations/audit/auditing-events?view=azure-devops#pipelines

启用后,可以在 组织设置 | 常规 | 审计 | 日志中查看事件。这些事件会保存 90 天,之后会 被删除。

它们将日志收集到集中式日志存储中,在这里我们可以保存更长时间,并且可以在 组织设置 | 常规 | 审计 | | 新建流中配置审计流,在这里我们可以选择通过 Azure 事件网格将日志导出到 Azure Monitor、Splunk 或其他第三方解决方案。

图 7.30 – Azure DevOps 审计流选项

图 7.30 – Azure DevOps 审计流选项

启用和配置数据平面日志记录

GHEC 工作流运行日志(构建环境数据平面日志)默认也 已启用并保留 90 天 默认情况下。 保留 设置可以在企业、组织或 仓库级别调整,最大可调为 400 天:

  • 企业级: 导航到 企业 | 设置 | 策略 | 操作 | 工件和日志保留。设置保留天数并 点击 保存

  • 组织级别:前往 组织 | 设置 | 代码、规划与自动化 | 工件和日志保留。设置保留天数后 点击 保存

  • 仓库级别:前往 仓库 | 设置 | 代码与自动化 | 操作 | 常规 | 工件和日志保留。设置保留天数后 点击 保存

图 7.31 – 在 GitHub 中配置工作流日志保留策略

图 7.31 – 在 GitHub 中配置工作流日志保留策略

Azure 流水线的构建日志默认启用,并且会默认保留 30 天。 这些 保留设置 可以通过 项目设置 | 流水线 | 设置 | 保留策略 | 保留运行天数 **。

图 7.32 – 在 Azure DevOps 项目设置中配置保留策略

图 7.32 – 在 Azure DevOps 项目设置中配置保留策略

现在让我们了解一下 安全网关。

在发布流水线中实现安全网关

网关是 软件发布流水线中的重要组成部分。 它们作为质量检查点,在软件进入下一个部署阶段之前,必须通过这些检查。 它们的主要目标是减少部署不合格的软件的可能性,这些软件未能达到商定的性能和 质量标准。

例如,一个开发团队可能会将软件或更新部署到测试环境,使用如 Azure Load Testing 和 Selenium 等工具运行自动化负载和功能测试,并在 Azure Monitor 中查看 结果。

如果 软件符合约定的 服务水平协议 (SLA),则将部署到下一个阶段。 如果不符合 SLA,则部署会停止,并且会收集遥测数据供团队调查并解决问题(图 7**.33)。

图 7.33 – 发布流水线中的示例质量门测试

图 7.33 – 发布流水线中的示例质量门测试

DevSecOps 扩展了门的使用范围,包括安全性验证(安全门) – 见 图 7**.34。安全门的目标是防止最关键的软件风险被部署到生产环境或其他具有更高 利用风险的环境中。

图 7.34 – 发布流水线中的示例安全门测试

图 7.34 – 发布流水线中的示例安全门测试

发布流水线中的安全门 根据项目需求有所不同。 动态应用安全测试 (DAST) 门使用如 OWASP ZAP、Burp Suite 和 Acunetix 等工具,在预生产环境中测试运行中的应用程序。 这些工具检查诸如 API 安全、SSL/TLS 配置和 身份验证等问题。 合规性门 确保符合监管 标准,而 渗透测试门 则模拟网络攻击, 以发现漏洞。

有效的安全门需要在保持开发速度的同时平衡全面的安全检查。 从最关键的检查开始,这些检查提供最大的价值,然后逐步扩展。 要确定最关键的检查,从当前在生产环境中看到的主要问题开始,并实施检查,以防这些问题进入生产环境。 根据反馈和不断发展的 安全威胁持续完善你的过程。

关于保持开发速度,安全门应尽可能自动化,以避免减缓软件发布过程。 如果使用安全门阻止不符合要求的软件部署到生产环境,建议实施一个管理良好的手动覆盖流程。 这应该至少需要两名手动批准者,以防止其被滥用作为安全绕过,并确保只有业务可接受的风险才会 被允许通过。

将 DAST 实施为安全门

与前面章节中涵盖的安全评估不同,DAST 在应用程序运行时识别安全问题。 它是一个很好的 补充, 静态应用程序安全测试 (SAST) 和 SCA 评估,因为它可以检测代码中可能没有明显显示的运行时问题。 它通过模拟攻击正在运行的应用程序来实现这一点。 例如,DAST 工具可能会爬取一个正在运行的 Web 应用程序 并发送格式错误的输入,以识别如 SQL 注入、 跨站脚本攻击 (XSS) 和不安全的直接 对象引用等问题。

将 DAST 集成到遵循 DevOps 流程的项目中,并且不影响用户,需要了解部署策略,并与管道开发团队合作。 部署策略会影响测试类型和实施方式。 例如,传统的应用程序部署策略包括将其发布到 测试 环境中,然后进入 暂存 环境,最后到达 生产环境。测试和暂存部署是集成持续 DAST 过程的理想点。

现在有 一些现代部署策略被 DevOps 团队采纳,这些策略允许更频繁地部署到生产环境,有时甚至在生产环境中进行测试。 如部署环、金丝雀发布、 黑暗发布和 A/B 测试都属于这一类。 在将 DAST 集成到这些策略中时,主要需要注意的是,测试应在类似生产的非生产环境中进行,以确保准确的结果,同时保护生产环境中的数据。

在 DevOps 流程中实施 DAST 的挑战

DAST 工具的有效性与它能够自动执行的测试类型密切相关。 这听起来可能很简单,但其中有很多细微的差别。 例如,针对 Web 应用程序的测试与针对 API 应用程序的测试不同,后者又与针对实现检索增强生成RAG)工作流的生成式 AI 应用程序的测试不同。 如果一个 DAST 工具仅支持针对 Web 和 API 应用程序的攻击,那么它可能对其他类型的应用程序价值不大。 不要仅仅为了集成而集成 DAST。 必须明确定义其价值,因为集成带来一定的速度成本。 确保 DAST 的收益超过对开发速度和效率的影响。 要正确评估应用程序的特定安全需求和潜在漏洞,以确定 DAST 集成是否值得。

大多数现有的 DAST 工具专注于测试 Web 应用程序。 虽然许多组织有基于 Web 的应用程序,但其他类型的应用程序可能未被涵盖。 大多数 DAST 解决方案仅测试 Web 启用应用程序的暴露 HTTP 和 HTML 接口。 然而,某些 解决方案是专门为非 Web 协议和数据畸形设计的,比如 远程过程 调用RPC)。

另一个挑战是,尽管 DAST 已存在一段时间,但大多数工具是为传统流程中的安全团队使用而创建的。 然而,现代 DAST 解决方案是从零开始为开发人员、QA 和 DevOps 专业人员构建的,使得工具及其输出对他们来说更具相关性和可访问性。 现代 DAST 解决方案的一个关键特点是部署的灵活性,包括容器化或基于代理的扫描仪,并提供云端和 自托管报告的选项。

修复是另一个挑战领域。 来自 DAST 工具的修复指导可能缺乏上下文。 例如,DAST 工具可能会识别到运行中的应用程序中的 SQL 注入漏洞,但它可能无法识别开发人员需要 更改的代码行,以修复该问题。 这就是另一个工具类别, 互动式应用程序安全测试 (IAST),可以提供帮助的地方。 IAST 将 SAST 和 DAST 的安全功能合并为一个工具,并为开发人员提供更多可操作的见解。

尽管 IAST 和 DAST 都 关注运行时的应用程序行为,IAST 通过结合内部应用程序流分析、扫描和黑盒测试提供更全面的分析。 这使得 IAST 可以将与 DAST 类似的发现直接链接到源代码。 它通过分析测试中执行的代码,精确定位代码中的漏洞。 然而,作为一种相对较新的应用程序安全方法,IAST 也有其缺点。 它依赖于编程语言,并且可能会减慢 CI 管道的速度。

在 Azure Pipelines 和 GitHub Actions 中实现安全门

在 Azure Pipelines 中,发布策略被设置为 阶段 在发布管道中。 对于经典 管道,质量门是通过使用每个 阶段的预部署 和后部署 条件来定义的。 预部署条件 是在部署阶段开始之前必须满足的检查和验证。 它们作为 守门员,确保在部署开始之前满足质量标准。 后部署条件 是在部署完成后、进入下一阶段之前进行的检查。 它们用于验证部署是否引入了新的问题,并确保应用程序正常运行。 要实现它们,请按照以下步骤操作:

  1. 在 Azure Pipelines 中,导航到 Pipelines | Releases

  2. 选择相关的 发布管道。

  3. 选择发布阶段的部署前或部署后条件(图 7.35)。

  4. 门控下,点击添加来配置你的发布门控设置。

图 7.35 – 配置部署前或部署后条件

图 7.35 – 配置部署前或部署后条件

GitHub Actions 提供了类似的功能,使用环境可以设置保护规则作为发布门控。例如,GitHub 中的一个工作流可以包括一个任务,在部署到下一个环境之前,必须由指定的审核人员手动批准。这在需要部署到多个阶段(如预发布和生产环境)的工作流中尤为有用。每个阶段可以有自己的规则集,这些规则由这些门控进行强制执行。要了解更多有关环境和保护规则的信息,请参阅此文档:docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#custom-deployment-protection-rules

实践操作 – 在构建和测试阶段集成安全性

在本次练习中,我们将在管道的构建和测试阶段中集成安全性。我们将实际实施制品签名以确保完整性,并使用 ZAP 实现 DAST。

以下是本次练习的任务:

  • 任务 1 – 实现制品签名以进行完整性检查

  • 任务 2 – 集成 DAST 工具以发现并修复测试阶段的安全漏洞

前提条件

在开始第一个任务之前,首先在 Azure Key Vault 中创建一个密钥库,然后生成一个自签名密钥和证书。稍后我们将使用这个密钥和证书通过 Notation 签署镜像。

  1. 进入你的 Azure 门户 portal.azure.com

  2. 在搜索栏中搜索 key vaults 并选择 密钥保管库

图 7.36 – 搜索并选择密钥保管库

图 7.36 – 搜索并选择密钥保管库

  1. 点击 创建 并填写所需的详细信息,然后点击 审核 + 创建,然后 点击 创建

图 7.37 – 创建密钥保管库

图 7.37 – 创建密钥保管库

  1. 现在我们已经创建了密钥保管库,接下来我们使用 Azure CLI 创建一个自签名证书。 首先,创建一个证书策略文件,执行该文件后将生成一个 与 Notation 兼容的有效证书。 将以下代码复制到 Azure CLI bash 终端中以创建策略文件。 从 https://github.com/PacktPublishing/eShopOnWeb/blob/main/policy.txt复制此内容。

图 7.38 – 证书策略文件内容

图 7.38 – 证书策略文件内容

  1. 通过将以下命令粘贴到您的 Bash 终端来创建证书:

     az keyvault certificate create -n test-io --vault-name devsecopsKeyVaultTest -p @my_policy.json
    

    记得 将密钥保管库的名称更改为在 步骤 3中创建的名称。 图 7**.39 展示了一个 自签名证书的成功创建。

图 7.39 – 创建自签名证书

图 7.39 – 创建自签名证书

  1. 让我们确认证书已经创建,方法是进入您的密钥保管库,然后导航到 对象 并点击 证书。您将在这里找到刚刚创建的 证书。

图 7.40 – 创建自签名证书(test-io)

图 7.40 – 创建自签名证书(test-io)

第六章,动手操作 练习 1 – 将 SAST、SCA 和密钥扫描集成到构建过程中 部分,我们运行了 azure-pipelines.yml 文件,它构建并部署了 Docker 镜像。 创建了几个资源,其中包括一个 容器注册表。 在配置签名任务之前,需要设置一些访问权限以签署已创建的 镜像。

  1. 让我们首先 授权访问 AcrPullAcrPush。让我们在 Azure CLI Bash 终端上配置 ACR 和 AKV 环境变量 。

     ACR_SUB_ID=myACRSubscriptionId
    ACR_RG=myAcrResourceGroup
    ACR_NAME=myregistry
    AKV_SUB_ID=myAKVSubscriptionId
    AKV_RG=myAkvResourceGroup
    AKV_NAME=myAKV
    
  2. 通过首先设置包含 ACR 资源的订阅来授权访问 ACR。

     az account set --subscription $ACR_SUB_ID
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    

    az role assignment create --role "AcrPull" --role "AcrPush" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    
  3. 现在让我们授权访问 AKV,以下角色是使用 自签名证书进行签名所需的:

    • 密钥保管库证书管理员 用于创建和 读取证书

    • 密钥保管库证书用户 用于读取 现有证书

    • 密钥保管库加密用户 用于 签名操作

    首先使用以下命令设置包含 AKV 资源的订阅: 命令:

     az account set --subscription $AKV_SUB_ID
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    

    az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    
  4. 现在让我们 创建 Docker 注册表服务连接。 为了使用 notation 签署镜像,我们将使用 Azure Pipelines 中的 Docker 任务登录 ACR。 此任务允许你构建、推送和拉取 Docker 镜像。

  5. 导航到 项目设置 然后 服务连接

图 7.41 – 设置服务连接

图 7.41 – 设置服务连接

  1. 选择 新建服务连接 并选择 Docker 注册表

  2. 接下来选择 Azure 容器注册表

  3. 选择 服务主体身份验证类型 字段中,并输入服务 主体详细信息,包括你的 Azure 订阅和 ACR 注册表。

  4. 输入服务连接名称,如以下图示所示:

图 7.42 – 设置 Docker 注册表服务连接

图 7.42 – 设置 Docker 注册表服务连接

  1. 最后,需要的访问权限是将 Azure Key Vault 访问策略授予您的服务主体。

  2. 打开您创建的 Azure 资源管理器服务连接,点击管理服务主体,访问 Azure 服务主体门户。

  3. 复制应用程序(客户端)ID。此 ID 将用于授予权限给服务主体。

  4. 导航到Azure Key Vault门户,进入访问****策略页面。

  5. 创建一个新的访问策略,包含以下权限:密钥签名、秘密获取和证书获取。

  6. 使用您之前复制的应用程序(客户端)ID,将此新访问策略分配给服务主体。

  7. 保存更改以完成设置。

现在我们已满足先决条件,可以开始任务。

任务 1 – 实现工件签名以进行完整性检查

在此任务中,我们将使用 Notation 对工件进行签名,强制执行所有发布工件(包括容器镜像)的真实性和完整性验证,通过添加在部署过程中验证的数字签名。该签名用于验证工件是否来自受信任的发布者,且没有经过修改。这防止了诸如我们之前提到的 CodeCov 事件中出现的生产包和工件的篡改。

我们将使用 Notation 实现工件签名:

  1. 导航到您的 DevOps 实例,访问dev.azure.com,并选择您在前一章中使用的组织。

  2. 选择我们在前一章中使用的eShopOnWeb私有项目。

  3. Azure DevOps 有一个 azure-pipelines.yml。 点击流水线编辑面板并搜索 符号 notation

图 7.43 – Azure DevOps 流水线上的符号市场任务

图 7.43 – Azure DevOps 流水线上的符号市场任务

  1. 点击符号任务并选择安装运行命令下。然后,点击添加按钮。 这将 将安装符号的任务添加到您的流水线中,如下图所示:

图 7.44 – Azure DevOps 流水线中的符号安装任务

图 7.44 - Azure DevOps 流水线中的符号安装任务

  1. 接下来,让我们添加用于签署我们的工件的符号任务。返回流水线编辑面板并再次搜索符号。 这次,我们将选择签署命令 运行下。

  2. crx6xa5yuubr2hm.azurecr.io/eshoponweb/web:latest

  3. Azure Pipelines 中的符号任务原生支持 Azure Key Vault 插件,这使得符号 CLI 可以使用 Azure-Key-Vault 管理的证书和密钥生成签名。选择Azure Key Vault 插件插件下,然后选择之前在第六章实操练习中创建的服务连接。

  4. 对于密钥 ID部分,添加您通过在 Azure Cloud Shell 中运行以下命令获得的结果。添加正确的证书和密钥 保管库名称。

     az keyvault certificate show -n test-io --vault-name <your keyvault name> --query 'kid' -o tsv
    

图 7.45 – 密钥 ID 值

图 7.45 - 密钥 ID 值

在这种情况下,密钥 ID 是 https://devsecopskeyvaulttest.vault.azure.net/keys/test-io/0daaced86b764e37855e02740e4f2d7c

  1. 标记支持使用自签名证书和 CA 颁发的证书进行签名。 对于本任务,我们将使用自签名证书。 向下滚动并检查 自签名证书。然后,点击 添加 以将签名任务添加到 您的流水线。

图 7.46 – Azure DevOps 流水线上的 Sign Notation 市场任务

图 7.46 – Azure DevOps 流水线上的 Sign Notation 市场任务

  1. 运行 该流水线 并检查 已添加的两个任务。 执行成功后,图像将按以下方式签名,如 图 7**.47所示:

图 7.47 – 完成标记任务并签署图像。

图 7.47 – 完成标记任务并签署图像。

现在让我们来看一下如何在 测试环境中运行的应用程序上执行 DAST。

任务 2 – 集成 DAST 工具以在测试阶段查找并修复安全漏洞

该 任务旨在 集成 ZAP 以执行 DAST。 目前有多个其他商业和开源的 DAST 工具,如 Acunetix、Checkmarx DAST、Fortify WebInspect、Rapid7 的 Insight、PortSwigger Burp Suite 和 Veracode 等。 其中许多工具可以在 Azure DevOps 市场上找到(https://marketplace.visualstudio.com/azuredevops)。 进行 DAST 扫描非常重要,因为它涵盖了广泛的漏洞,包括可能使应用程序容易受到 XSS 或 SQL 注入攻击的输入验证。 DAST 是在运行中的应用程序上执行的。 它对您的 Web 应用程序 和 API 执行自动化渗透测试 ,这些应用程序和 API 已经 在运行。 它模拟了现实世界的攻击,涵盖了 OWASP Top 10 (https://owasp.org/www-project-top-ten/)。

在上一个任务中,我们运行了一个构建并部署 eShopOnWeb 应用程序的流水线。

图 7.48 – 已部署的 eShopOnWeb 应用程序

图 7.48 – 已部署的 eShopOnWeb 应用程序

让我们看看如何使用 ZAP 对我们运行中的应用程序进行 DAST 扫描:

  1. OWASP ZAP 可在 Azure Marketplace 上找到。 请访问 Azure Marketplace https://marketplace.visualstudio.com/azuredevops,并搜索 OWASP ZAP Scanner。点击 免费获取,选择正确的组织来安装扩展,然后安装后返回到你的项目 。

图 7.49 – OWASP ZAP 扫描器在 Azure Marketplace

图 7.49 – OWASP ZAP 扫描器在 Azure Marketplace

  1. 我们将 在管道 YAML 文件中添加 OWASP ZAP 扫描器任务。 在这个 实例中,我们将为 OWASP ZAP 创建一个新的管道,但你也可以将相同的任务添加到 现有管道中。

  2. 导航 到 Pipelines 在左侧,选择 Pipelines,然后选择 新建管道

  3. 选择 Azure Repos Git 然后选择 eShopOnWeb。我们将使用 Starter pipeline

  4. 删除启动脚本,然后从 OWASP ZAP 扫描器 任务 Tasks 添加。

图 7.50 – OWASP ZAP 扫描器在 Azure Marketplace

图 7.50 – OWASP ZAP 扫描器在 Azure Marketplace

  1. 设置 1500 并选择 目标扫描 作为你的扫描类型。 输入 测试环境中应用的 URL,然后 点击 添加

图 7.51 – 设置 OWASP Zap 扫描器配置

图 7.51 – 设置 OWASP Zap 扫描器配置

  1. 在添加显示名称后,YAML 文件现在应如下所示。

图 7.52 – OWASP ZAP 扫描器任务

图 7.52 – OWASP ZAP 扫描器任务

  1. 我们 需要发布由 OWASP ZAP 扫描器生成的报告 任务。 从 发布构建工件 . 将发布路径设置为 $(Build.ArtifactStagingDirectory) 并将工件名称设置为 ZAP 报告

图 7.53 – 发布构建工件任务

图 7.53 – 发布构建工件任务

  1. 我们的 YAML 文件 现在看起来像 下面这样:

图 7.54 – OWASP ZAP 和发布任务

图 7.54 – OWASP ZAP 和发布任务

  1. 报告以 JSON 和 HTML 格式生成,这些格式是机器可读的,因此输出结果可以用于进一步处理。 我们还可以通过添加以下代码片段,将扫描结果发布到 测试结果 标签页中: 安装 Handlebars报告生成,以及 发布报告(Nunit 风格) 代码部分 来自 https://marketplace.visualstudio.com/items?itemName=CSE-DevOps.zap-scanner

  2. 添加前面三个代码片段后,更新文件路径参数,从 安装 Handlebars 代码片段更新为 如下:

     <filePath>$(Build.SourcesDirectory)/owaspzap/report.html</filePath>
    
  3. 保存并提交 新管道,然后 运行它。

  4. 几分钟后, 任务完成,扫描结果 已发布。

图 7.55 – OWASP ZAP 和发布任务成功

图 7.55 – OWASP ZAP 和发布任务成功

让我们查看 来自 测试结果 标签页的扫描结果。 导航到成功的管道运行并点击 测试 标签页。

图 7.56 – 测试结果标签页

图 7.56 – 测试结果标签页

浏览扫描结果,熟悉来自 OWASP ZAP 的发现。

总结

本章节中,我们涵盖了发布应用程序到生产环境前应执行的几项检查。 这包括确保发布构件来自受保护的分支,实施代码审查流程,选择安全的构件源,实施验证构件完整性的流程,在发布阶段安全管理秘密,实施基础设施即代码(IaC)安全扫描,并验证并通过发布门限强制运行时安全性。 我们还涵盖了现有的运行时验证工具 包括 DAST。

在下一章节中,我们将探讨 Azure 上的持续安全监控。 既然我们已经部署了资源,我们需要确保它们保持安全。 让我们 深入了解。

第八章:Azure 上的持续安全监控

在前几章中,我们强调了 DevSecOps 的主要目标是将安全性作为软件开发过程每个阶段的常规部分。 其结果是,我们可以在软件部署到生产环境并投入使用之前,捕获并修复大多数安全问题。 那么,软件发布后的安全性如何呢? 一个完整的 DevSecOps 策略应当在开发过程早期实施的安全措施基础上,补充运行时安全。

在本章中,我们将 讨论在 DevOps 的 操作监控 阶段实施安全性的一些关键方面,包括实施运行时漏洞管理、威胁检测和威胁防护。 在本章结束时,你将对以下内容有一个坚实的理解:

  • 理解 DevOps 中的持续监控 概念

  • 实施运行时安全门以防止 关键风险

  • 为 运行时环境实施持续安全监控

  • 现代云环境中运行时保护的挑战 问题

  • 保护在 Azure 中运行的应用 App Service

  • 在 Azure 中保护容器工作负载

让我们 开始吧。

技术要求

要跟随本章中的指引,你将需要 以下资源:

  • 一台具有 互联网连接的 PC

  • 一个有效的 Azure 订阅

  • 一个 Azure DevOps 组织

  • 一个 GitHub 企业组织

理解 DevOps 中的持续监控

我们在本书开篇介绍的 DevOps 第五个实践是 持续监控CM)。CM 涉及两个主要任务—— 收集用户反馈收集实时遥测数据。用户反馈用于设定未来的 优先事项。 遥测数据用于快速检测并解决操作问题,减少停机时间,维护服务的可靠性 和可用性。

为了实现 这一目标,CM 依赖于跨应用、基础设施和网络的数据收集监控工具。 在 Azure 中,应用洞察是 CM 的关键服务。 它具有类似的 应用性能管理 (APM) 功能,类似于 Dynatrace 和 Datadog APM。 它可以用于从运行中的应用收集数据,可以使用无代码或基于代码的方法。 然后可以分析这些数据,以提供有关应用健康、实时指标、事务搜索和用户行为的洞察(图 8**.1)。

图 8.1 – Azure 应用洞察概述

图 8.1 – Azure 应用洞察概述

在此阶段实施安全性涉及扩展数据收集,包含安全日志和指标。 这些日志和指标可以分析以检测未经授权的访问尝试、潜在的安全漏洞和弱点。 这一过程可能很复杂,因为在像 Azure 这样的云平台上运行的现代云原生应用 通常使用托管服务(例如 App Service、Function Apps、Container Instances 和 Container Apps)。 这些 服务可能对安全团队的操作有所限制。 传统方法,如基于代理的运行时监控,往往在这些环境中无效。 另一个挑战是这些应用的分布式特性,这可能使安全团队不确定从哪里开始进行 安全防护。

理解 Azure 和云原生应用的相互关联风险

现代云原生应用是分布式和复杂的,涉及多个技术 堆栈、微服务和外部 API 交互。 在云原生 环境中,通过 CI/CD 管道的代码会作为容器交付运行(尽管一些组织仍然直接在主机上运行代码)。 该容器在节点内部运行,由集群协调器管理,例如 Kubernetes、Service Fabric 或 OpenShift,或由平台服务管理,如 Azure Web Apps、Azure 容器实例或 Azure Functions。 所有这些都运行在 Azure 云平台上(图 8**.2)。

图 8.2 – 云原生应用的风险交集

图 8.2 – 云原生应用的风险交集

保护现代云原生应用程序的复杂性在于,每个部分的安全模型都不同。 例如,容器编排工具如 Kubernetes 和 OpenShift 的安全模型与云服务 (如函数应用和容器应用)的安全模型不同,而后者又与 Windows 和 Linux 节点的安全模型不同。 云的规模和快速发展的步伐使这一复杂性进一步加剧。 Azure 中的运行时云原生应用安全必须考虑其互联性,从而形成一个 风险交集

恶意 用户通过在运行中的容器中获取 shell 访问权限,可能会窃取源代码、密钥、令牌和凭证,进而可能危及云平台中的其他服务。 他们还可能利用容器权限来破坏集群节点并访问其他工作负载。 相反,弱云凭证可能被用来破坏注册表中的容器并访问源代码、加密密钥及用于 工作负载的敏感数据。

为了减轻这些风险,我们的安全工作必须集中在两个关键方面——保护运行时环境和在运行时实现应用安全。 让我们详细探讨这两个方面,从 第一个方面开始。

保护应用程序运行时环境

尽管我们尽最大努力在早期解决安全问题,但在 软件生产中,无法预见的漏洞可能会出现。 此外,现代应用程序的复杂性意味着一些风险可能只在 实际运行时才会显现。

如果我们 采纳 零信任 的思维方式(而我们应该采纳),我们需要接受没有任何系统或过程是完美安全的,并为可能的安全漏洞做好准备。 这被称为“假设入侵”心态。 这也是为什么 DevSecOps 不仅仅停留在部署阶段。 运行时安全应作为最后一道防线整合进来,以便在实时应用程序中发生安全问题时进行管理、识别、保护、检测和响应,并从中恢复。 这一整合的首要点是实施运行时门控和保护措施,以防止在早期检查点被绕过的情况下部署最关键的风险。 。

实施运行时安全门控以阻止关键风险

安全 门在 DevSecOps 中起着重要作用。 它们防止了最严重的 软件风险被部署到我们的生产云环境中。 在 第七章中,我们介绍了如何在发布流水线中设置安全门(流水线安全门)。 然而,也可以在运行时实现安全门(运行时安全门),但它们有一定的局限性。 与流水线安全门相比,运行时安全门适用的场景较少。 以下是在 Azure 中运行时安全门可能有效的一些例子:

  • Azure 策略:在 Azure 云平台上创建资源时

  • Kubernetes 入驻控制器:在将容器化解决方案/应用程序部署到 Kubernetes 集群(自管理或托管) 时

  • 反恶意软件:当将打包应用程序部署到安装了反恶意软件/反漏洞解决方案的 Azure 虚拟机时 解决方案已安装

图 8.3 – 流水线安全门与运行时安全门

图 8.3 – 流水线安全门与运行时安全门

对于 其他 Azure 服务,运行时安全门不原生支持,除非我们部署第三方 安全解决方案或创建自己的自定义方法。 例如,当将 Web 应用程序部署到 Azure App Service,将微服务部署到 Azure Functions 应用,或将容器化服务部署到 Azure 容器实例时,发布流水线安全门是我们防御关键风险部署的主要防线。 所有这些操作都在 Azure 云平台上运行(图 8**.3)。

使用 Azure 策略实现运行时安全门

Azure 策略是 Azure 中的一项配置评估和执行服务。 它可用于 在 API 请求被 Azure 管理平面处理之前审查它们。 它还可以 审查在 Azure 中创建的资源的设置。 对于我们的用例作为运行时安全门,它可以用于执行以下操作:

  • 如果新的 Azure 资源违反我们的 安全策略,请阻止其被创建

  • 如果现有资源违反我们的 安全策略,请阻止其更改

备注

我们的目标不是重复介绍 Azure Policy 或 Microsoft Defender for Cloud 的基础知识。 相反,我们将重点讨论与我们讨论内容相关的具体用例。 如果你想了解更多关于这些服务的信息,可以查看这本书 《Microsoft Azure 安全技术认证与实践》 ,由 Packt Publishing 出版。

我们可以在 Azure 层级的不同级别上应用政策——管理组、订阅和资源组。 为了简化政策的分配,Azure 允许你将政策分组为 倡议。倡议只是一个可以作为一个整体分配的政策组。 微软提供了一个内置的倡议,叫做 微软云安全基准 (图 8**.4),包含了 241 个与安全相关的政策(截至撰写时)。 该倡议中的大部分政策都设置为 审计 效果,这意味着它们会观察并报告违规行为,但不会 阻止操作。

图 8.4 – 微软云安全 Azure Policy 倡议

图 8.4 – 微软云安全 Azure Policy 倡议

首先 回顾此倡议中的政策。 识别出那些带来最大 风险的政策。 然后,评估 通过将这些政策设置为 拒绝 效果来防止这些风险的影响。 将政策更改为 拒绝 意味着它将阻止不符合要求的操作,而不仅仅是 报告这些操作。

使用 Kubernetes 入驻控制器实施运行时安全门控

Admission 控制器是一个 Kubernetes 组件,拦截 对 Kubernetes API 服务器的请求, 在它们被处理之前进行干预。 它通常 用于执行安全性和合规性检查。 为了简化实施 Admission 控制器,CNCF 提供了 Open Policy AgentOPA),一个开源策略引擎。 OPA 使用 Rego 语言来定义规则,从简单的检查(例如确保所有容器都有资源限制)到复杂的多步骤评估。 OPA Gatekeeper 库提供了常见场景的示例模板,例如强制执行容器镜像来源、限制特权容器以及确保正确的标签。 这些模板可以在 OPA 网站上查看 ,网址如下: https://open-policy-agent.github.io/gatekeeper-library/website

Azure Policy 与 OPA 集成,以管理和执行 Azure Kubernetes ServiceAKS)集群中的策略。 这种集成使得在 Azure 层面定义的策略能够在 Kubernetes 环境中强制执行,提供了一种在 Azure 和 Kubernetes 中跨平台管理策略的统一方式。 要使用此功能,我们需要在 Kubernetes 集群中部署 Azure Policy 插件。 可以在订阅级别或单个集群上执行此操作。 要在订阅级别启用它,我们可以将 Azure Kubernetes Service 集群应安装 Azure Policy 插件 Azure Policy 推荐分配给我们的订阅或管理组。 最好在更广泛的层级应用治理 策略,例如管理组或订阅,以确保新集群会自动安装该插件。

截至本文写作时,已经有 79 个内置的 Kubernetes 相关策略,涵盖了 如安全性、身份验证和访问控制、资源管理、配置管理、合规性和治理等领域。 例如, ^[^/]+.azurecr.io/.+$ 确保只有来自 Azure 容器注册表(.azurecr.io/)的镜像可以部署到受覆盖的 Kubernetes 集群中。

图 8.5 – 为限制集群中允许的容器注册表或镜像分配 Azure 策略

图 8.5 – 为限制集群中允许的容器注册表或镜像分配 Azure 策略

对于 我们分配的每个策略,我们可以指定排除的命名空间、镜像和容器。 建议与具有详细 应用程序和 Kubernetes 操作知识的开发和 DevOps 团队合作,以确保 适当的排除。

注意

具有 拒绝 效果的策略不会追溯影响已部署的容器或资源。 现有的容器将继续运行,直到它们被重启、更新 或替换。

除了前述策略之外,以下是建议至少考虑实施的四个额外策略:

  • 策略: Kubernetes 集群中的 Pod FlexVolume 卷应该仅使用 允许的驱动程序

    背景: 在 Kubernetes 中,FlexVolume 是一种插件机制,允许用户使用不同的存储驱动程序为他们的 Pod 添加存储。 这些驱动程序负责 将 Pod 连接到存储后端。 然而,如果 使用不受信任或恶意的驱动程序,可能会带来安全 风险。 例如,恶意驱动程序可能允许攻击者未经授权访问敏感数据,或者利用 系统资源。

    该策略的作用: 如果分配了 拒绝 效果,任何使用未经批准的 FlexVolume 驱动程序的应用程序 Pod 部署将被阻止 部署。

  • 策略: /proc 文件系统为内核提供了一种机制,使其能够向用户空间暴露关于系统和正在运行的进程的信息。 它不是包含“真实”文件, /proc 包含的是运行时系统信息(例如,系统内存、已挂载设备和硬件配置)以及关于系统上每个进程的详细信息。 暴露过多的信息或允许不受限制的访问可能会导致信息泄露并为恶意用户提供潜在的利用机会。 例如,恶意进程可能会更改内核参数以破坏系统稳定性或削弱其 安全性。

    在 Kubernetes 中,在 SecurityContext 定义中,我们可以使用 ProcMount 类型来指定 /proc 文件系统如何在应用容器中挂载(参见以下示例)。 有三种主要的 ProcMount 类型 - Unmasked 选项风险最大,因为它提供了对 /proc 文件系统的完全访问权限,允许容器查看并操作所有进程信息。 这可能被利用来暴露敏感信息 和系统细节,并且在最坏的情况下,操纵 内核参数:

     apiVersion: v1
    kind: Pod
    metadata:
      name: unmasked-procmount
    spec:
      containers:
      - name: mycontainer
        image: myimage
        securityContext:
          procMount: Unmasked
    

    The /proc 文件系统 包含了关于系统上运行的进程的各种信息。 如果容器使用不当的 ProcMount 类型,可能会将敏感信息或系统细节暴露给未经授权的用户。 例如,一个 ProcMount 类型,允许对 /proc 的完全访问,可能导致信息泄漏和潜在的 安全漏洞。

    策略的作用 : 该策略确保容器只能使用指定的 ProcMount 类型,例如 Default ProcMount 类型,该类型限制了访问。 如果容器尝试使用未经批准的 ProcMount 类型,例如 Unmasked (如前面示例所示),则部署将 被阻止。

  • 策略 : runAsUser runAsGroup 字段确保容器以特定的批准用户和组 ID 运行(参见以下示例)。 这种做法限制了攻击者如果获得容器访问权限时可能造成的潜在损害。 例如,使用非 root UID 和 GID 运行容器可以降低特权提升的风险,并保护敏感 系统资源:

     apiVersion: v1
    kind: Pod
    metadata:
      name: non-root-pod
    spec:
      containers:
      - name: mycontainer
        image: myimage
        securityContext:
          runAsUser: 1000
          runAsGroup: 3000
    

    该策略的作用:此策略确保 Kubernetes 中的 Pod 和容器只能使用 批准的用户和组 ID。 它强制使用非 root UID 和 GID,例如 10003000,分别在前面的示例中体现。 如果容器尝试使用未批准的 UID 或 GID,部署将 被阻止。

  • 策略CAP_SYS_ADMIN 权限对系统具有广泛的控制,包括修改系统配置和 挂载文件系统的能力。

    在 Kubernetes 中, securityContext 定义允许你指定容器可以添加或移除的权限(参见以下示例)。 主要有两个操作—— 添加移除。向容器添加权限会增加其特权,这可能被恶意进程利用来危害系统。 相反,移除权限通过限制 容器的特权来减少攻击面:

     apiVersion: v1
    kind: Pod
    metadata:
      name: restricted-capabilities
    spec:
      containers:
      - name: mycontainer
        image: myimage
        securityContext:
          capabilities:
            drop: [«ALL»]
            add: [«NET_BIND_SERVICE»]
    

    在 前面的示例中,所有权限都被移除,且 仅添加了 NET_BIND_SERVICE 权限,允许容器绑定到特权端口(即 低于 1024的端口)。

    授予不必要的权限可能会导致重大的安全风险。 例如,具有 CAP_NET_ADMIN 权限的容器可以操控网络配置,可能会破坏网络流量或窃取敏感数据。 通过控制可以使用的权限,我们可以减轻特权提升和 系统受损的风险。

    该策略的作用:此策略确保容器只能使用指定的权限,从而防止使用危险或不必要的特权。 如果容器尝试添加未批准的权限,部署将 被阻止。

我们强烈 建议您查看 79 个内置策略,识别出对贵组织构成最严重风险的策略,并以 拒绝 效果实施它们。 如果内置策略无法覆盖您的使用场景,还可以创建自定义策略。 现在我们已经了解了 如何实施运行时安全门控,让我们来回顾一下如何实施对我们 运行时环境的持续安全监控。

实施针对运行时环境的持续安全监控

现代 云运行时环境不是静态的;一个简单的 API 调用可能会引入配置错误,导致运行关键应用的资源暴露 并且易受攻击。 为了保护这些资源,必须持续监控运行时资源配置的可见性 并且不依赖代理。 云安全态势管理 (CSPM) 是业内用于描述帮助组织持续监控云资源配置的工具的术语,以检测可能带来 安全风险的变化。

然而,挑战比仅仅识别配置错误更为复杂。 并非所有暴露的资源都是配置错误或易受攻击的。 有效的安全性需要提供上下文,以优先考虑风险,识别可能创建攻击路径的有害组合,并理解更广泛的安全态势。 第一代 CSPM 解决方案主要集中在可见性和配置评估上,这常常导致噪音过大,却没有解决现代云安全的复杂性。 更新的 CSPM 解决方案旨在解决更复杂的挑战,如优先排序、攻击路径检测和上下文 风险评估。

在 Azure 云中实现运行时环境持续安全可见性和监控的核心 是微软的 云原生应用保护平台 (CNAPP) 解决方案 – Microsoft Defender for Cloud (MDC)。

注意

CNAPP 是 一种旨在保护云原生应用程序整个生命周期的安全解决方案。 它将多个安全功能集成到一个平台中,防止工具过载。 CNAPP 的主要使用场景是为云原生应用程序提供安全功能,从开发到部署到云中运行(也称为 代码到云)。

MDC 目前提供 10 种保护计划,客户可以根据自己的 安全需求和预算来启用(图 8**.6)。

图 8.6 – MDC 计划

图 8.6 – MDC 计划

对于运行环境的持续安全监控,MDC 的 Defender CSPM 计划是一个很好的解决方案,能够应对以下 新挑战:

  • 攻击路径管理:单个云资源的配置错误是有风险的,但 相关联的多个配置错误组合可能会创建出关键的攻击路径,从而使整个应用程序面临风险。 MDC 的攻击路径管理功能通过分析我们的云 资源,识别攻击者可能利用的配置错误链条来应对此问题。 例如,MDC 可能会检测到一个数据库的明文凭证,该数据库运行在提供公共 Web 服务的虚拟机上。 这为攻击者提供了一个路径,能够访问关键数据库中的敏感数据。 通过突出显示这些互相关联的风险,MDC 使安全团队能够优先修复能够破坏整个攻击路径的问题,而不仅仅是解决 孤立的配置错误。

  • 风险优先级排序:安全团队在启用 CSPM 解决方案后,通常会面临大量的警报 和建议。 如果没有适当的优先级排序,他们可能会在对少数业务效益不大的小问题上浪费时间,同时忽略关键漏洞。 MDC 的风险优先级排序通过根据建议的潜在影响及其被利用的可能性来排序,帮助解决这一问题。 MDC 使用上下文感知的风险优先级排序引擎来确定每个安全建议的风险等级。 该风险等级取决于资源配置、网络连接和安全态势等因素。 例如,暴露的存储帐户如果存储有敏感数据,其优先级将高于存储有 普通数据的存储帐户。

  • 基础设施即代码 (IaC) 模板映射:安全配置错误 通常起源于 IaC 模板。 如果不解决 根源问题,这些问题可能会在重新部署后再次出现。 MDC 的 IaC 模板映射通过将云资源与其原始 IaC 模板关联来解决这一问题。 当 MDC 检测到已部署资源中的安全问题时,它会识别相应的 IaC 模板,从而让开发人员修复根本原因。 例如,如果 MDC 发现一个过于宽松的网络安全组,它可以指向 Terraform 模板中需要更新的确切行,防止该问题在未来的 部署中再次发生。 它依赖 于流行的开源 IaC 模板扫描工具 Checkov 的能力 来实现这一点。

  • 数据安全态势管理:有效的风险管理要求你 不仅要了解漏洞的存在位置,还要了解风险数据的敏感性。 MDC 的数据安全 态势管理功能通过扫描和分类云环境中的数据来解决这一问题。 然后,它将这些信息与安全评估集成,提供更全面的风险视图。 例如,如果 MDC 检测到两个配置错误的数据库,其中一个包含客户财务数据,而另一个包含非敏感的营销材料,它会优先关注财务数据库进行处理。 这种情境感知的方法确保安全团队将工作重点放在优先保护最关键数据上,从而显著改善整体 安全态势。

MDC 具有 比这些更多的功能,包括最近新增的功能,如 AI 安全态势管理 (AI-SPM)。要了解 更多关于这些功能的信息,请参阅以下文档: https://learn.microsoft.com/en-us/azure/defender-for-cloud/defender-for-cloud-introduction。稍后,在本章的动手操作中,你将实施 MDC 的 Defender CSPM 计划 。

在 Azure 中保护应用程序运行时

确保 应用程序在部署到 Azure 服务后仍然安全,与传统的本地运行时安全不同。 云服务引入了新的挑战,需要转变策略,采用一种与 DevOps 实践相辅相成的方式。

在 Azure 的共享责任模型中,微软负责保护底层基础设施,但开发人员和运维团队必须保护应用程序和数据。 这要求 理解 Azure 的安全功能,并将其与应用层保护措施集成。 在本节中,我们将探讨在 Azure 中保护运行时应用程序的挑战,并讨论如何使用 Azure 原生工具作为 起点。

现代云环境中运行时保护的挑战

Azure 云环境提供了多种计算选项,用于托管应用程序和服务,从传统的虚拟机到无服务器计算功能。 图 8**.7 展示了这一范围 以及客户在这些选项之间的控制差异。 例如,虚拟机提供完全的操作系统控制,而 Azure Functions 提供最小的操作系统交互。 这种多样性使得持续的安全性 措施变得具有挑战性。

一个主要的挑战是支持组织中使用的各种应用程序和服务运行时选项。 当前的解决方案可能能够通过安装的代理来保护虚拟机上的应用程序,但容器中的服务怎么办? 它可能能够保护在 Azure App Service 上运行的 Linux 容器中的应用程序,但它是否支持 Windows 容器? 您的解决方案不需要覆盖所有使用场景,但您需要确保在运行时保护您的关键资产 。

图 8.7 – Azure 计算选项

图 8.7 – Azure 计算选项

随着更多 组织将其应用程序从虚拟机迁移到容器服务和无服务器计算,必须调整其应用程序运行时保护策略,原因在于这些环境的运作方式差异以及它们所带来的独特挑战。 以下是一些需要考虑的额外挑战 :

  • 有限的操作系统访问权限:大多数 Azure 计算服务(虚拟机除外)将底层操作系统从客户面前抽象化。 这使得安装依赖于操作系统级代理的传统安全解决方案变得困难。 这些基于代理的安全解决方案在虚拟机上的应用程序中工作良好,但可能不支持容器化应用程序或无服务器功能。 能够保护在这些环境中运行的应用程序的有效安全解决方案必须能够做到这一点,而不需要 持久化代理。

  • 自动扩展挑战:某些计算服务可以根据需求自动添加新的实例来处理请求。 如 App Service、Function Apps、Container Apps 和 Kubernetes Services 等服务可以自动添加数百个实例,有时在几分钟内就能处理请求。 当负载消失时,这些实例会被终止,以节省成本。 有效的安全解决方案必须能够保护在这种环境中运行的应用程序,并能够处理快速扩展,具备几乎即时启动和 停止的能力。

  • 容器化复杂性:容器因其可移植性和高效性而广受欢迎,但它们也带来了独特的安全挑战。 安全解决方案必须具备容器感知能力,以保护主机和各个容器。 许多传统安全供应商才刚开始将容器感知能力添加到他们的解决方案中。 这些解决方案正在逐步发展。

  • 无服务器挑战:无服务器计算,如 Azure Functions,改变了应用程序的运行方式,从而也改变了我们如何保护它们。 例如,一家金融服务公司可能在 Azure 容器实例上运行其实时欺诈检测微服务。 这些容器可能在毫秒级别内启动以处理事务,然后终止。 假设有长期运行的服务器的传统安全模型在这种环境下面临困难。 这个环境下的安全挑战很大。

这些挑战凸显了为现代云架构设计的新型安全工具的需求。 随着越来越多的公司采用这些技术,安全行业正快速发展,以应对这些 独特的安全问题。

保护运行在 Azure App Service 中的应用程序

Azure App Service 是一种托管服务,用于在 Azure 云中托管 Web 应用程序、API 和移动后端服务。 通过使用 CI/CD 管道,开发人员可以将 Web 或 API 服务作为代码或容器直接部署到服务中。 图 8**.8 展示了在 GitHub Actions(标记为 1)和 Azure Pipelines(标记为 2)中实现 Azure App Service 部署操作/任务的示例。

图 8.8 – GitHub Actions 和 Azure Pipelines 中的 Azure App Service 部署任务

图 8.8 – GitHub Actions 和 Azure Pipelines 中的 Azure App Service 部署任务

对于 在 Azure App Service 部署的 Web 和 API 应用程序的运行时保护,实施 Defender for App Service 的 MDC 计划是一个很好的起点。 该计划提供运行时威胁检测功能,主要通过行为分析技术来实现,涵盖以下五个类别,详见 表 8.1

MITRE 威胁 ATT&CK 战术 描述
攻击前 威胁检测 检测扫描程序扫描我们运行中的应用程序以寻找已知漏洞 – 例如,使用 Nmap、BlindElephant、WPScan、Joomla Scanner 和 Drupal Scanner 等工具进行 Web 指纹识别的尝试。

| 初始访问 威胁检测 | 检测来自已知恶意 IP 地址或可疑端点的恶意网络连接尝试,例如: 例如:

  • 已知恶意 IP 地址连接到我们的 App Service的 FTP 端点。

  • 应用服务解析已知恶意 DNS 主机名。

  • 从不寻常的 IP 地址或 用户代理连接到托管在 App Service 中的敏感网页。

Defender for App Service 通过分析 各种服务日志,例如 DNS 和 FTP 日志,并将其与 Microsoft 威胁情报源中的已知恶意 IP 地址和域名进行比较,从而检测这些尝试。 。 |

| 攻击执行 威胁检测 | 检测攻击者利用漏洞获得访问权限后,在我们应用服务的虚拟机实例上执行恶意或可疑命令和进程的尝试。 这通过分析运行中的进程、文件系统和内存行为来完成。 这可以检测到如下事件: 例如:

  • 可疑的远程文件下载 – 例如,使用 curl 从像 Pastebin 这样的站点下载代码并保存到磁盘。 。

  • 下载可疑文件,如加密矿工可执行文件或 Web Shell。

  • 可疑进程或命令的执行——例如,挖矿程序、反向 Shell 工具、凭证访问工具、已知攻击者工具名称的进程、恶意 PowerShell PowerSploit cmdlets、尝试利用 PHP 进程执行操作系统命令,以及从异常路径执行的 SVCHOST 进程(恶意软件通常利用 SVCHOST 来隐藏 恶意活动)。

  • 滥用内置管理员工具,如 certutil.exe 来解码可执行文件或下载二进制文件,而不是其通常用于管理证书的功能。 攻击者通常滥用合法的管理员工具以达到 恶意目的。

  • 执行 各种无文件攻击技术 和工具包。

  • /upload 文件夹中发现一个 PHP 文件。 该文件夹通常不包含 PHP 文件,这表明可能存在利用任意文件 上传漏洞的攻击。

  • 主机/设备数据分析,检测可能的外部数据 流出情况。

|

悬挂 DNS 检测 当应用服务网站已退役但其自定义域名(DNS 记录) 未被删除时,发出警报。

| 后渗透检测 | 检测我们托管的应用程序是否在实际攻击中被发现,如 以下内容:

  • 我们的应用 URL 曾被用于针对 Microsoft 365 客户的钓鱼攻击,该攻击已被 Microsoft 威胁 情报团队识别。

  • 由于 Microsoft 威胁 情报团队的监测,我们的 Web 应用 URL 被 Windows SmartScreen 标记为恶意。

|

表 8.1 – 应用服务计划的威胁检测类别

尽管应用服务的 Defender 是一个很好的起点,但它也有其局限性。 例如,它侧重于检测威胁,而不是阻止威胁。 部分原因在于 它分析日志而不是使用代理。 当安全解决方案仅检测威胁而不阻止它们时,响应时间会增加。 检测威胁与人工干预之间的延迟使威胁有更多时间造成损害,可能导致数据泄露或系统被攻陷。 这还增加了安全团队的工作量,因为他们需要调查和响应 每个检测到的事件。

另一个 App Service 的 Defender 限制是,它无法识别我们应用程序在运行时已知的漏洞。 这种能力至关重要。 手动追踪哪些正在运行的应用程序受到下一个重大漏洞(如 Log4j)影响并不是最优选择。 为了解决这些问题,我们可以使用定制的开源工具或第三方安全解决方案。 例如,一些第三方解决方案可以作为 RASP 代理与我们的应用程序一起运行,以提供额外的功能,如阻止主动威胁和识别运行中的应用程序中已知的漏洞。 在运行的应用程序中。 您需要解决的挑战是如何大规模地推广这一解决方案。

什么是 RASP?

运行时应用程序安全保护 (RASP) 是一种在应用程序内部运行的安全技术,用于实时检测和防止攻击。 它监控应用程序在运行时的行为,并能对潜在威胁采取即时行动。 RASP 提供了在生产环境中的持续保护,补充了其他部署前的安全措施,如 SAST 和 DAST。 根据安全供应商的实现,RASP 有时可能比较复杂,且可能存在性能影响方面的担忧。

Azure App Service 提供了更简单的方式,通过扩展来推出诸如 Tinfoil Security(现已成为 Synopsys 的一部分)和 Signal Sciences WAF(现已成为 Fastly 的一部分)等安全解决方案。 您可以通过以下步骤进行安装:前往您的 App Service 实例 → 开发工具扩展添加 (*图 8.9**.)

图 8.9 – 向 Azure App Service 添加一些安全扩展

图 8.9 – 向 Azure App Service 添加一些安全扩展

Tinfoil Security 提供漏洞管理功能,而 Signal Sciences WAF 提供针对 Web 应用程序攻击的威胁预防和检测。

保护 Azure 中的无服务器工作负载在运行时的安全性

无服务器 工作负载,如 Azure Functions,以及运行在 容器即服务(CaaS) 资源上的容器化 应用程序,例如 Azure 容器应用 (ACA),由于其短暂的特性,面临独特的运行时安全挑战。 例如,Azure Functions 的消费计划没有预留实例;相反,实例会根据请求按需动态分配。 对于 HTTP 触发的函数,Azure 的规模控制器每秒可以分配一个实例,并且实例在处理完成后会被移除。 这种瞬态特性使得传统的安全措施效果较差,因此需要专门的安全方法来保护 无服务器环境。

目前,Azure 没有为无服务器工作负载提供专门的运行时漏洞评估、威胁检测和防护的原生解决方案。 然而,第三方 安全供应商通过提供类似 RASP 的解决方案填补了这些空白。 这些解决方案允许组织将安全直接嵌入到其无服务器函数代码或容器中。 这样,运行时安全跟随应用程序,无论它被部署到哪个环境。 这种方法通常需要代码更改或定制化的容器 构建过程。

例如,Palo Alto Networks 的 Prisma Cloud 提供了 Serverless Defender,可以嵌入到函数代码中,以便在运行时监控和保护该函数。 以下代码示例展示了如何将 Serverless Defender 库添加到 C# 函数代码中,创建一个新的受保护处理程序,该处理程序包装了原始处理程序。 当函数在云端运行时被调用时,受保护的处理程序会被调用,进而调用函数代码。 受保护的处理程序将提供运行时漏洞评估、威胁检测以及 威胁防护等功能:

 using Twistlock;
public class Function
{
    // Original handler
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log, ExecutionContext context)
    {
        Twistlock.Serverless.Init(log, context);
        // Function logic
    }
}

对于 无服务器容器化工作负载,工作流可以自动化,使得运行时安全处理程序可以直接嵌入容器镜像中,从而建立控制点。 为了让这一过程更容易被采用,一些服务提供商可能会提供将 此过程自动化 持续部署 (CD)流水线的能力。 图 8**.10 展示了一个在 Azure DevOps 流水线中自动化此类安全嵌入的 Palo Alto Prisma Cloud 任务示例。

图 8.10 – Prisma Cloud Serverless Defender 嵌入任务示例

图 8.10 – Prisma Cloud Serverless Defender 嵌入任务示例

任务将接受一个用于容器化应用程序的 Dockerfile 输入 并重新构建它,将 Prisma Cloud 的运行时安全性嵌入容器镜像中。 当容器启动时,Prisma Cloud 应用内嵌的 Defender 会作为父进程在容器中启动,并立即调用程序作为 它的子进程。

保护 Azure 中的容器工作负载

Azure 云提供 多种服务来运行容器化应用程序 和服务。 其中一些是容器专用的,意味着 它们仅运行 容器工作负载:

  • Azure 容器 实例 (ACI)

  • Azure 容器 应用 (ACA)

  • Azure Kubernetes 服务 (AKS)

  • Azure Red Hat OpenShift (ARO)

其他 是兼容容器的,这意味着它们可以运行代码和 容器应用程序:

  • Azure 应用服务

  • Azure 函数

  • Azure 服务网格

  • Azure 批处理

  • Azure Spring 应用

开发人员可以通过 CI/CD 管道将容器化应用程序部署到这些服务中。 图 8**.11 展示了在 GitHub Actions(标记为 1)和 Azure Pipelines(标记为 2)中实现 Kubernetes 工作负载部署操作/任务的示例。

图 8.11 – GitHub Actions 和 Azure Pipelines 中的 Kubernetes 工作负载部署任务

图 8.11 – GitHub Actions 和 Azure Pipelines 中的 Kubernetes 工作负载部署任务

对于 工作负载的漏洞管理和运行时保护,我们可以从实施 MDC 的容器防护计划开始。 该计划结合了无代理和基于代理的方法,以检测容器工作负载的漏洞和威胁。 然而,这些功能目前仅限于部署在 AKS 上的工作负载。 对于 Kubernetes 工作负载中的威胁检测,容器防护会收集并分析以下数据(图 8**.12):

  • 来自 API 服务器的审计日志和安全事件

  • 来自 工作节点的安全信号和事件

  • 来自 控制平面的集群配置信息

  • 来自 Azure 策略的工作负载配置(我们在 本章中已讨论过这一点)

图 8.12 – 容器防护架构

图 8.12 – 容器防护架构

表 8.2 详细描述了该计划的功能 :

功能 描述
漏洞评估 对存储在 Azure 容器注册表 (ACR) 中的镜像进行漏洞评估, 以及对 AKS 集群中运行的镜像进行评估。对于 ACR,评估可以通过无代理的方式进行。 对于 AKS 中运行的镜像,我们也可以通过配置 Kubernetes 的无代理发现来实现此功能,或者我们 也可以安装 Defender 传感器 代理。此功能由 Microsoft Defender 漏洞管理解决方案提供支持。 它支持 Linux 和 Windows 容器(这很少见),并支持扫描特定语言的包,包括 Python、Node.js、.NET、Java、 和 Go。漏洞扫描每天至少运行一次,适用于过去 90 天内推送或过去 30 天内拉取的镜像。Defender for Containers 还支持保护 AWS 和 GCP 上的容器工作负载,但这超出了 本主题的范围。
运行时 保护(Kubernetes 控制平面 威胁检测) 基于 Kubernetes 审计 日志分析,检测 Kubernetes 中的可疑活动。
运行时保护(Kubernetes 工作负载 威胁检测) 在集群、节点和 工作负载级别检测可疑活动。这需要部署 Defender 传感器代理。 这可以在订阅级别或单个集群级别启用。

表 8.2 – Defender for Containers 功能

如在 表 8.2中强调的那样,计划中的某些功能需要在 Kubernetes 集群上安装 Defender 传感器代理,而其他功能则不需要(这些称为无代理模式)。 例如,存储在 ACR 中的镜像的漏洞评估不需要传感器。 然而,要映射 AKS 集群中运行的容器的漏洞评估,我们 需要部署传感器或启用 Kubernetes 的无代理发现 功能。

备注

在 AKS 中对运行中的容器进行漏洞评估时传感器不会直接扫描运行中的容器。 相反,它们会收集 Kubernetes 集群中容器工作负载的清单。 然后,Defender for Containers 会将此清单与 ACR 中镜像的漏洞评估报告进行匹配。 因此,报告只会显示来自已扫描 ACR 的运行容器的漏洞。 如果运行的镜像来自未扫描的注册表,Defender for Containers 将无法显示其漏洞,从而可能产生一个安全漏洞,您需要 考虑此问题。

了解 Defender for Containers 的 Kubernetes 控制平面威胁检测能力

Defender for Containers 提供运行时威胁检测 覆盖两个主要领域 – 在警报中带有K8S_前缀,并详细列出在 表 8.3

威胁检测类别 – 暴露服务
在 Kubernetes 中暴露的带信任身份验证配置的 Postgres 服务 检测到(K8S_ExposedPostgresTrustAuth
Kubernetes 中暴露的 Postgres 服务,配置存在风险 检测到(K8S_ExposedPostgresBroadIPRange
暴露的 Kubeflow 仪表盘 检测到(K8S_ExposedKubeflow
暴露的 Kubernetes 仪表盘 检测到(K8S_ExposedDashboard
暴露的 Kubernetes 服务 检测到(K8S_ExposedService
在 AKS 中暴露的 Redis 服务 检测到(K8S_ExposedRedis
威胁检测类别 – 异常活动
与 Kubernetes 关联的托管身份的 异常活动(预览)(K8S_AbnormalMiActivity
异常的 Kubernetes 服务账户操作 检测到(K8S_ServiceAccountRareOperation
来自代理 IP 地址的 K8S API 请求 检测到(K8S_TI_Proxy
向 Kubernetes API 发出的可疑请求(K8S.NODE_KubernetesAPI
对 Kubernetes 仪表盘的可疑请求(K8S.NODE_KubernetesDashboard
检测到 Kubernetes 渗透测试工具(K8S_PenTestToolsKubeHunter
威胁检测类别 – 特权提升 和访问
检测到带有敏感卷挂载的容器(K8S_SensitiveMount
检测到新高 特权角色 (K8S_HighPrivilegesRole
检测到特权容器(K8S_PrivilegedContainer
检测到对 cluster-admin 角色的角色绑定(K8S_ClusterAdminBinding
检测到 创建了一个 Admission Webhooks 配置(K8S_AdmissionController
威胁检测类别 – 配置和 资源修改
Kubernetes 中的 CoreDNS 修改 检测到(K8S_CoreDnsModification
删除了 Kubernetes 事件(K8S_DeleteEvents
kube-system 命名空间 检测到新容器(K8S_KubeSystemContainer
威胁检测类别 – 恶意活动
检测到数字货币挖掘容器(K8S_MaliciousContainerImage

表 8.3 – 容器防护(Kubernetes 控制平面威胁检测)

理解 Defender for Containers 的 Kubernetes 工作负载威胁检测能力

工作负载威胁检测使用在工作节点上的 Defender Sensor 代理收集安全 事件进行分析。 在撰写时,它可以检测 34 种威胁,范围包括对敏感数据的访问和可疑工具检测。 这些检测的警报前缀为 K8S.NODE_ ,并列在 表 8.4中。

威胁检测类别 – 特权提升和 高特权
从容器中尝试创建新的 Linux 命名空间 检测到(K8S.NODE_NamespaceCreation
容器内部运行具有高 特权的命令(K8S.NODE_PrivilegedExecutionInContainer
在特权容器中运行 模式(K8S.NODE_PrivilegedContainerArtifacts`)
威胁检测类别 - 异常行为和 可疑活动
清除了历史文件 (K8S.NODE_HistoryFileCleared
检测到不常见的连接尝试 (K8S.NODE_SuspectConnection
尝试停止 apt-daily-upgrade.timer 服务 检测到(K8S.NODE_TimerServiceDisabled
检测到可疑使用 nohup 命令(K8S.NODE_SuspectNohup
检测到可疑使用 useradd 命令(K8S.NODE_SuspectUserAddition
检测到可疑文件下载 (K8S.NODE_SuspectDownloadArtifacts
从已知恶意来源下载文件 (K8S.NODE_SuspectDownload
检测到可疑文件时间戳 修改(K8S.NODE_TimestampTampering
检测到可疑下载后运行 活动(K8S.NODE_DownloadAndRunCombo
使用 crypt-method 可能的密码更改检测到(K8S.NODE_SuspectPasswordChange
潜在的端口转发到外部 IP 地址(K8S.NODE_SuspectPortForwarding
检测到潜在的反向 Shell (K8S.NODE_ReverseShell
检测到与安全相关的进程终止 (K8S.NODE_SuspectProcessTermination
向 Kubernetes API 发出可疑请求 (K8S.NODE_KubernetesAPI
检测到对 Kubernetes 仪表盘的可疑请求 (K8S.NODE_KubernetesDashboard
在 Kubernetes 节点上检测到 Docker 构建操作 (K8S.NODE_ImageBuildOnNode
威胁检测类别 – 恶意活动和 已知威胁
检测到类似常见 Linux 机器人行为(预览)(K8S.NODE_CommonBot
检测到与数字货币挖掘相关的行为 (K8S.NODE_DigitalCurrencyMining
检测到与数字货币挖掘相关的进程 (K8S.NODE_CryptoCoinMinerArtifacts
检测到可能的加密货币矿工下载 (K8S.NODE_CryptoCoinMinerDownload
检测到可能的后门 (K8S.NODE_LinuxBackdoorArtifact
检测到可能的命令行利用尝试 (K8S.NODE_ExploitAttempt
检测到以异常方式访问 SSH 授权密钥文件的进程 (K8S.NODE_SshKeyAccess
检测到可能的日志篡改活动 (K8S.NODE_SystemLogRemoval
威胁检测类别 – 可疑 工具检测
检测到一个可能的恶意 Web Shell (K8S.NODE_Webshell
检测到可能的攻击工具 (K8S.NODE_KnownLinuxAttackTool
检测到与 DDOS 工具包相关的指标 (K8S.NODE_KnownLinuxDDoSToolkit
检测到一个 MITRE Caldera 代理 (K8S.NODE_MitreCalderaTools
检测到一个 可能的凭证访问工具 (K8S.NODE_KnownLinuxCredentialAccessTool
威胁检测类别 – 访问 敏感数据
检测到对 kubelet kubeconfig 文件的访问 (K8S.NODE_KubeConfigAccess
访问云元数据服务已检测到(K8S.NODE_ImdsCall

表 8.4 – Defender for Containers(Kubernetes 工作负载威胁检测)

在大规模实施 Defender for Containers 计划

实施 Defender for Containers 是一个两步过程。

首先,我们需要在 MDC 环境设置中启用计划,方法是转到Microsoft Defender for Cloud管理环境设置 → 选择您的管理组或订阅 → 设置Defender 计划云工作负载保护(CWP),然后切换容器开启图 8.13)。

图 8.13 – 启用 Defender for Containers 计划

图 8.13 – 启用 Defender for Containers 计划

启用计划后,我们需要启用漏洞管理并将 Defender Sensor 代理部署到我们的 Kubernetes 集群中。可以在订阅或管理组级别启用,使用自动配置选项,或者为单个集群启用。 在订阅级别启用它可以让我们大规模强制实施保护——启用后,所有现有的和新的 AKS 集群将自动受到保护

要配置无代理漏洞评估和自动配置,请按照以下步骤操作:

  1. 转到Microsoft Defender for Cloud

  2. 导航到管理环境设置

  3. 选择您的管理组或订阅。

  4. 转到设置Defender 计划云工作负载保护(CWP)容器

  5. 监控****覆盖栏目下选择设置

  6. 设置Azure 中的 Defender 传感器开启图 8.14)。

  7. 设置 无代理容器漏洞评估开启 (图 8**.14)。

图 8.14 – 启用无代理漏洞管理和 Defender 传感器自动配置

图 8.14 – 启用无代理漏洞管理和 Defender 传感器自动配置

启用 此功能将为 Azure 策略分配 应启用 Azure Kubernetes Service 集群的 Defender 配置文件 建议,并应用于 所选范围。

如前所述,实施此计划是一个很好的起点,但请牢记其局限性。 例如,该计划不涵盖其他 Azure 服务(如应用服务、容器实例、容器应用或函数应用)中运行的容器的漏洞管理或运行时安全性。 此外,针对 AKS 集群的漏洞评估不会针对运行时检测到的容器映像执行单独的扫描。 相反,它将已识别的运行时容器映像与从扫描的 Azure 容器注册表中获取的漏洞报告进行匹配。 如果您的团队从公共或其他未经扫描的注册表部署映像,则需要使用 其他方法解决这些问题。

容器的 Defender 的 Kubernetes 工作负载威胁检测能力主要集中于检测而不是阻止威胁。 它主要依赖于基于行为的技术,专注于监视系统活动并将其与已知攻击模式进行比较。 这种方法在识别已知的攻击指标方面非常有效,但面对新的和以前未见的攻击模式时可能无效,因为它严重依赖预定义的行为。 基于行为的技术如果基线不能准确反映 合法行为,也可能触发误报。

其他第三方安全解决方案提供商支持基于工作负载的基于 AI 的检测,有更好的机会检测不匹配任何已知模式的新和不断发展的威胁,提供了行为基础系统所缺乏的适应性水平。 例如,Palo Alto Network 的 Prisma Cloud 使用此技术来学习部署容器的预期行为,并自动警报或阻止任何超出 预期操作的行为。

另一个 需要考虑的限制是 Windows 容器工作负载。 在 34 项工作负载威胁检测中,仅有三项支持 Windows 节点。 如果您的组织有大量 Windows 容器,您需要使用 其他方法来解决运行时安全问题。

理论部分完成后,让我们进入 Azure 门户进行 一些实现。

动手练习 – 在 Azure 上进行持续安全监控

在本 练习中,我们将完成以下任务:

  • 任务 1 – 实现和 操作化 CSPM

  • 任务 2 – 实现和操作化持续容器 工作负载保护

任务 1 – 实现和操作化 CSPM

在本 任务中,我们将涵盖 MDC,其中一个主要支柱是 CSPM。 MDC 是一个 云原生应用保护平台 (CNAPP),它通过以下功能 从端到端保护您的云应用 : 使用 以下能力:

  • DevSecOps:在代码层面统一多云和多管道环境中的安全管理。

  • CSPM:识别并共享云基础设施中的风险修复。

  • 云工作负载姿态平台 (CWPP):为服务器、容器、存储及 其他工作负载提供保护功能。

Defender for Cloud 提供以下 CSPM 服务:

  • 基础 CSPM:对于已加入 Defender for Cloud 的订阅和帐户,默认启用此功能。 此 CSPM 功能是免费的。 包括安全建议、资产清单、安全评分、使用 Azure 工作簿的数据可视化和报告、数据导出、工作流自动化、修复工具以及 Microsoft 云 安全基准等功能。

  • Defender CSPM:在现有的基础 CSPM 功能之上提供更先进的安全姿态功能。 此计划需要付费,并且 是可选的。

让我们 在 Microsoft Azure 上启用 CSPM 功能:

  1. 首先,登录 到 Azure 门户。

  2. 确认 你的订阅至少有以下其中一个角色 – 所有者、贡献者, 或阅读者。

  3. 在 Microsoft Azure 搜索栏上搜索 Microsoft Defender for Cloud 然后 选择它。

  4. Defender for Cloud 概述页面将会打开,并且已经启用在你的订阅中具备基础功能,包括基础 CSPM、建议、资产清单、Workbooks、安全评分以及符合微软云安全基准的法规合规性。

  5. 浏览各种功能,强调风险和建议 每个资产。

  6. 要启用 Defender CSPM,请导航到 管理下的环境设置 左侧。

图 8.15 – 在 MDC 上选择环境设置

图 8.15 – 在 MDC 上选择环境设置

  1. 选择 你想要保护的订阅。 这将带你进入 Defender 计划。

  2. 云安全姿势管理 (CSPM)下,切换 Defender CSPM 状态到 开启

图 8.16 – 启用 Defender CSPM

图 8.16 – 启用 Defender CSPM

  1. 点击 设置Defender CSPM 监控覆盖下 并启用所有的扩展,如下面的屏幕截图所示。 花些时间去浏览所有组件、描述和 Defender 计划。

图 8.17 – 启用 Defender CSPM 扩展

图 8.17 – 启用 Defender CSPM 扩展

  1. 选择 保存

我们已经 看到如何 启用 CSPM。 花些时间去检查启用后的额外 发现 Defender CSPM。

任务 2 – 实施和运营持续的容器工作负载保护

在这个 任务中,我们希望 利用 Defender CSPM 来启用 无代理容器安全,并识别容器注册表和 Kubernetes 中的风险。 在上一个任务中,我们启用了 Kubernetes 的无代理发现无代理容器漏洞评估 扩展。 这就是启用 Defender CSPM 中的无代理容器安全所需要的全部步骤。

让我们在 Microsoft Azure 上启用 CSPM 功能:

  1. 首先,让我们通过使用云命令行在 AKS 集群中集成我们的 Azure 容器注册表 命令:

    az aks update -n <AKSCluster> -g <ResourceGroup> --attach-acr <your-acr-name>
    
  2. 导航 到 Azure 门户中的 Kubernetes 服务,并在 Kubernetes 资源 | 命名空间 下确认命名空间是否存在。

  3. 返回 到 MDC,查看所有安全发现,位于 推荐下,然后查看在 Cloud Security Explorer中的查询。

  4. 最后,让我们 点击 工作负载保护Cloud Security下;然后我们可以看到 Defender for Cloud 的所有覆盖范围。

图 8.18 – 审查 Defender for Cloud 覆盖范围

图 8.18 – 审查 Defender for Cloud 覆盖范围

  1. 高级保护下,点击 容器镜像扫描。容器 镜像漏洞评估 会扫描你的注册表,查找 常见已知漏洞CVE)并为 每个镜像提供详细的漏洞报告。

图 8.19 – 审查容器镜像扫描

图 8.19 – 审查容器镜像扫描

  1. 向下滚动,查看受影响的资源并探索 发现的漏洞。

在 练习中,我们已经 学习了如何利用 Defender for Cloud 的各种功能来保护我们的资源,使用 Defender CSPM。

总结

恭喜! 你已经成功地完成了本书的学习。 在本章中,我们讨论了如何使用 Azure 策略实现运行时安全门控,并介绍了与 Kubernetes 准入控制器集成的 Azure 策略。 我们还讨论了保护现代云应用的挑战,以及 Azure 所提供的一些本地能力。

展望未来,以下是我们认为将塑造 DevSecOps 未来的一些趋势:

  • 自动化:自动化结合 AI 将推动操作效率。 安全团队将专注于战略性任务,而自动化系统将处理操作性职能。 “从设计开始就确保安全”这一概念将会得到广泛推行,确保安全从 一开始就被纳入设计。

  • 工具整合:组织将整合安全工具,以简化流程并降低成本。 将可观察性和监控功能合并到一个平台中,将提供一个全面的安全态势视图。

  • 基础设施即代码(IaC):IaC 将在其中扮演至关重要的角色,传统的手动 IT 基础设施管理将让位于更高效、基于代码的方式,尤其是随着 云计算的增长。

  • 修复:迅速解决漏洞和安全问题将成为重点,防止风险在 升级之前蔓延。

  • 软件材料清单(SBOMs):SBOM 的演进将通过提供关于软件组件 和依赖关系的详细信息,增强透明度。

这些趋势已经被一些前沿组织采纳,但我们认为它们将会被更广泛地应用。 保持领先于这些趋势将帮助组织为应对不断变化的网络安全挑战做好准备。 特别是在 DevOps 领域。

进一步阅读

想了解更多关于本章讨论的主题,请查看以下内容:

posted @ 2025-06-26 15:33  绝不原创的飞龙  阅读(20)  评论(0)    收藏  举报