设计安全的部署流水线

Last reviewed 2023-09-28 UTC

部署流水线是一种自动化流程,它接受代码或预构建工件并将其部署到测试环境或生产环境。部署流水线通常用于部署应用、配置或云基础架构(基础架构即代码),它们在云部署的整体安全状况中可以发挥重要作用。

本指南面向 DevOps 和安全工程师,介绍了根据您的机密性、完整性和可用性要求设计安全部署流水线的最佳做法。

架构

下图显示了部署流水线中的数据流。它说明了如何将工件转换为资源。

工件流入部署流水线并发出资源。

部署流水线通常是较大的持续集成/持续部署 (CI/CD) 工作流的一部分,通常使用以下模型之一实现:

  • 推送模型:在此模型中,您可以使用中央 CI/CD 系统(如 JenkinsGitLab)实现部署流水线。此 CI/CD 系统可以在 Google Cloud、本地环境或其他云环境中运行。通常,同一 CI/CD 系统用于管理多个部署流水线。

    推送模型指向一个具有几个 CI/CD 系统的集中式架构,这些系统用于管理大量资源或应用。例如,您可以使用单个 Jenkins 或 GitLab 实例来管理整个生产环境,包括其所有项目和应用。

  • 拉取模型:在此模型中,部署过程由与资源一起部署的代理实现,例如,在同一个 Kubernetes 集群中。代理会从一个集中位置拉取工件或源代码,并在本地部署它们。每个代理管理一个或两个资源。

    拉取模型通向更加分散的架构,其中可能存在大量单用途代理。

与手动部署相比,一致地使用部署流水线具有以下优势:

  • 效率更高,因为无需手动操作。
  • 提高可靠性,因为此过程完全自动化且可重复。
  • 可追溯性更强,因为您可以跟踪所有对代码更改或输入工件更改的部署。

要执行部署流水线,需要访问其管理的资源:

  • 使用 Terraform 等工具部署基础架构的流水线可能需要创建、修改甚至删除资源,例如虚拟机实例、子网或 Cloud Storage 存储桶。
  • 部署应用的流水线可能需要将新的容器映像上传到 Artifact Registry,并将新应用版本部署到 App EngineCloud RunGoogle Kubernetes Engine (GKE)
  • 管理设置或部署配置文件的流水线可能需要修改虚拟机实例元数据、Kubernetes 配置或修改 Cloud Storage 中的数据。

如果部署流水线未得到妥善保护,则它们对 Google Cloud 资源的访问权限可能会成为安全状况的弱点。安全性降低可能会导致多种类型的攻击,包括:

  • 流水线投毒攻击:不法分子可能会试图破解部署流水线、其配置或其底层基础架构,而不是直接攻击资源。利用流水线对 Google Cloud 的访问权限,不法分子可能会使流水线对 Cloud 资源执行恶意操作,如下图所示:

    不法分子可能会使用代码攻击不安全的部署流水线。

  • 供应链攻击:不法分子可能会破解或替换流水线输入(包括源代码、库或容器映像),而不是攻击部署流水线,如下图所示:

    不法分子可能会攻击馈入部署流水线的供应链。

为了确定您的部署流水线是否受到妥善保护,仅查看 Google Cloud 资源的允许政策和拒绝政策是不够的。您必须考虑直接或间接授予对资源的访问权限的整个系统图。此图包含以下信息:

  • 部署流水线、其底层 CI/CD 系统及其底层基础架构
  • 源代码库、其底层服务器及其底层基础架构
  • 输入工件、其存储位置及其底层基础架构
  • 生成输入工件的系统及其底层基础架构

复杂的输入图使得很难识别用户对资源的访问权限以及系统漏洞。

以下部分介绍了设计部署流水线的最佳做法,可帮助您管理图的大小,并降低横向移动和供应链攻击的风险。

评估安全目标

您在 Google Cloud 上的资源在敏感程度上可能会有所不同。某些资源可能具有高度敏感性,因为它们是关键业务或机密资源。其他资源可能不太敏感,因为它们是临时资源或仅用于测试目的。

要设计安全的部署流水线,您必须先了解流水线需要访问的资源以及这些资源的敏感性。您的资源越敏感,就越应该专注于保护流水线的安全。

部署流水线访问的资源可能包括:

  • 应用,例如 Cloud Run 或 App Engine
  • 云资源,例如虚拟机实例或 Cloud Storage 存储桶
  • 数据,例如 Cloud Storage 对象、BigQuery 记录或文件

其中一些资源可能依赖于其他资源,例如:

  • 应用可能会访问数据、云端资源和其他应用。
  • 云资源(例如虚拟机实例或 Cloud Storage 存储桶)可能包含应用或数据。

    一种资源对另一种资源的依赖性可能会影响两者的敏感度。

如上图所示,依赖项会影响资源的敏感性。例如,如果您使用的应用会访问高度敏感数据,那么通常您应该将该应用视为高度敏感。同样,如果 Cloud Storage 存储桶等云资源包含敏感数据,则通常应将该存储桶视为敏感数据。

由于这些依赖关系,最好先评估数据的敏感度。评估数据后,您可以检查依赖项链,评估 Cloud 资源和应用的敏感性。

对数据的敏感度进行分类

要了解部署流水线中数据的敏感性,请考虑以下三个目标:

  • 机密性:您必须保护数据免遭未经授权的访问。
  • 完整性:您必须保护数据免遭未经授权的修改或删除。
  • 可用性:您必须确保已获授权的人员和系统可以访问部署流水线中的数据。

对于每个目标,请考虑流水线被破解时会发生什么情况:

  • 机密性:如果数据被泄露给不法分子,或者泄露给公众,会有多危害?
  • 完整性:如果不法分子修改或删除数据,危害程度如何?
  • 可用性:如果不法分子中断了您的数据访问,会造成多大的危害?

为了使结果在资源之间可比较,引入安全类别会很有用。安全分类标准 (FIPS-199) 建议使用以下四类:

  • :损坏情况为严重或灾难性
  • 中度:损坏情况严重
  • :损坏程度有限
  • 不适用:标准不适用

根据您的环境和上下文,不同的类别集可能更合适。

根据刚刚讨论的安全类别,流水线数据的机密性和完整性存在于各种范围内。以下各小节包含具有不同机密性和完整性测量结果的资源示例:

机密性低,完整性低、中、高的资源

以下资源示例的机密性都较低:

  • 低完整性:测试数据
  • 中等完整性:组织的公共 Web 服务器内容、政策限制
  • 高完整性:容器映像、磁盘映像、应用配置、访问政策(允许和拒绝列表)、安全锁、访问权限级别数据

机密性中,完整性低、中、高的资源

以下资源示例都具有中等机密性:

  • 低完整性:内部 Web 服务器内容
  • 中等完整性:审核日志
  • 高完整性:应用配置文件

机密性高,完整性低、中、高的资源

以下资源示例都具有高机密性:

  • 低完整性:使用情况数据和个人身份信息
  • 中等完整性:Secret
  • 高完整性:财务数据、KMS 密钥

根据应用访问的数据对应用进行分类

当应用访问敏感数据时,该应用和管理该应用的部署流水线也可能会变得敏感。为符合这种敏感性,请查看应用和流水线需要访问的数据。

在确定应用访问的所有数据并对其进行分类后,您可以在设计安全部署流水线之前,使用以下类别对应用进行初始分类:

  • 机密性:所访问的任何数据的最高类别
  • 完整性:所访问的任何数据的最高类别
  • 可用性:所访问的任何数据的最高类别

此初始评估可提供指导,但您可能还需要考虑其他因素,例如:

  • 两组数据可能具有独立的低机密性。但结合起来,它们可以揭示新的数据洞见。如果应用可以访问这两组数据,您可能需要将其归类为中等或高机密性。
  • 如果应用可以访问高完整性数据,您通常应将应用分类为高完整性。但如果该访问是只读的,则高完整性的分类可能过于严格。

如需详细了解规范化的应用分类方法,请参阅将信息和信息系统映射到安全类别的指南 (NIST SP 800-60 Vol. 2 Rev1)

根据云资源托管的数据和应用对云资源进行分类

您在 Google Cloud 上部署的任何数据或应用都由 Google Cloud 资源托管:

  • 应用可能由 App Engine 服务、虚拟机实例或 GKE 集群托管。
  • 您的数据可能由永久性磁盘、Cloud Storage 存储桶或 BigQuery 数据集托管。

当云资源托管敏感数据或应用时,该资源以及管理该资源的部署流水线也可能变得敏感。例如,您应该将 Cloud Run 服务及其部署流水线视为与其托管的应用一样敏感。

对数据应用进行分类后,为该应用创建初始安全类别。为此,请根据以下类别确定级别:

  • 机密性:托管的任何数据或应用的最高类别
  • 完整性:托管的任何数据或应用的最高类别
  • 可用性:托管的任何数据或应用的最高类别

在进行初步评估时,请勿过于严格,例如:

  • 如果对高度机密的数据进行加密,请将加密密钥视为高度机密。但是,您可以对包含数据的资源使用较低的安全类别。
  • 如果您存储了数据的冗余副本,或者跨多个资源运行同一应用的冗余实例,则可以将资源的类别设置为低于其托管的数据或应用的类别。

限制部署流水线的使用

如果您的部署流水线需要访问敏感的 Google Cloud 资源,则必须考虑其安全状况。资源越敏感,您就越需要尽力保护流水线。但是,您可能会遇到以下实际限制:

  • 使用现有基础架构或现有 CI/CD 系统时,该基础架构可能会限制您可以实际实现的安全级别。例如,CI/CD 系统可能仅支持一组有限的安全控制,或者可能在您认为低于某些生产环境的基础架构上运行。
  • 在设置新的基础架构和系统以运行部署流水线时,以符合最严格的安全要求的方式保护所有组件可能不够经济实惠。

为了应对这些限制,在哪些情况下应该或不应该使用部署流水线以及特定的 CI/CD 系统时,设置限制条件会很有用。例如,最敏感的部署通常在部署流水线之外更好地得到处理。这些部署可以是手动的,使用特权会话管理系统、特权访问管理系统或其他工具(如工具代理)。

如需设置限制条件,请根据资源类别定义要强制执行的访问权限控制。请参考下表中提供的指南:

资源的类别 访问权限控制
无需批准
适中 团队负责人必须批准
多个负责人必须批准,且必须记录操作

通过提出以下问题和其他问题,对比这些要求与源代码管理 (SCM) 和 CI/CD 系统的功能:

  • 您的 SCM 或 CI/CD 系统是否支持必要的访问权限控制和批准机制?
  • 如果不法分子攻击底层基础架构,这些控制措施是否不会被破坏?
  • 定义控制措施的配置是否受到妥善保护?

根据您的 SCM 或 CI/CD 系统的功能和限制,您可以为部署流水线定义数据和应用限制条件。请考虑下表中提供的指导:

资源的类别 限制条件
您可以使用部署流水线,开发者可以自行批准部署。
适中 可以使用部署流水线,但团队负责人必须批准每个提交和部署。
请勿使用部署流水线。管理员必须使用特权访问管理系统和会话记录。

保持资源可用性

使用部署流水线管理资源可能会影响这些资源的可用性,并可能带来新风险:

  • 导致中断:部署流水线可能会推送有故障的代码或配置文件,导致之前正常工作的系统中断或数据不可用。
  • 延长中断时间:如需修复中断,您可能需要重新运行部署流水线。如果部署流水线因其他原因而中断或不可用,则可能会延长中断时间。

可能导致或延长中断的流水线会导致拒绝服务攻击:不法分子可能会使用部署流水线有意导致中断。

创建紧急访问过程

如果部署流水线是部署或配置应用或资源的唯一方式,则流水线可用性可能会至关重要。在极端情况下,部署流水线是管理业务关键型应用的唯一方法,您可能还需要考虑部署流水线关键业务。

由于部署流水线通常由多个系统和工具组成,因此保持高可用性通常很困难或不经济。

您可以通过创建紧急访问过程来降低部署流水线对可用性的影响。例如,创建一个可在部署流水线无法运行时使用的备用访问路径。

创建紧急访问过程通常需要以下大多数过程:

  • 维护一个或多个具有相关 Google Cloud 资源特权的用户账号。
  • 将紧急访问用户账号的凭据存储在安全的位置,或使用特权访问管理系统来代理访问。
  • 建立授权员工可以用来访问凭据的过程。
  • 审核并查看紧急访问用户账号的使用情况。

确保输入工件满足您的可用性需求

部署流水线通常需要从中央源代码库下载源代码,然后才能执行部署。如果源代码库不可用,运行部署流水线可能会失败。

许多部署流水线还依赖于第三方工件。此类工件可能包括来自 npm、Maven Central 或 NuGet Gallery 等来源的库,以及容器基础映像、.deb.rpm 软件包。如果其中一个第三方来源不可用,则运行部署流水线可能会失败。

要保持一定级别的可用性,您必须确保部署流水线的输入工件都满足相同或更高的可用性要求。以下列表可帮助您确保输入工件的可用性:

  • 限制输入工件的来源数量,尤其是第三方来源
  • 维护输入工件的缓存,以便在源系统不可用时部署流水线可以使用这些缓存

将部署流水线及其基础架构视为生产系统

部署流水线通常用作开发、预演和生产环境之间的连接组织。根据环境,它们可能会实现多个阶段:

  • 在第一阶段,部署流水线会更新开发环境。
  • 在下一阶段,部署流水线将更新预演环境。
  • 在最终阶段,部署流水线会更新生产环境。

跨多个环境使用部署流水线时,请确保该流水线满足每个环境的可用性需求。由于生产环境通常具有最高的可用性需求,因此您应该将部署流水线及其底层基础架构视为生产系统。换句话说,对运行部署流水线的基础架构应用与生产系统相同的访问权限控制、安全和质量标准。

限制部署流水线的范围

部署流水线可以访问的资源越多,它被破解时可能导致的损害就越多。在最坏的情况下,可以访问多个项目甚至整个组织的被破解部署流水线可能会对 Google Cloud 上的所有数据和应用造成持久损害。

为了帮助避免这种最坏的情况,请限制部署流水线的范围。定义每个部署流水线的范围,使其只需要访问 Google Cloud 上相对较少的资源:

  • 您只需向部署流水线授予对各个资源的访问权限,而不是授予项目级层的访问权限。
  • 避免授予对多个 Google Cloud 项目中的资源的访问权限。
  • 将部署流水线拆分为多个阶段(如果它们需要访问多个项目或环境)。然后,分别保护这些阶段。

保持机密性

部署流水线必须保持其管理的数据的机密性。与机密性相关的主要风险之一是数据渗漏。

不法分子可能会试图通过多种方式来使用部署流水线,以便泄露 Google Cloud 资源中的数据。这些方式包括:

  • 直接:不法分子可能会修改部署流水线或其配置,以便从 Google Cloud 资源中提取数据,然后将其复制到其他位置。
  • 间接:不法分子可能会使用部署流水线来部署被破解的代码,然后从 Google Cloud 环境中窃取数据。

您可以通过最大限度地减少机密资源的访问权限来降低机密风险。但是,移除对机密资源的所有访问权限可能并不实际。因此,您必须设计部署流水线以满足其管理的资源的机密性要求。如需确定这些需求,您可以使用以下方法:

  1. 确定部署流水线需要访问的数据、应用和资源并对其进行分类。
  2. 查找具有最高机密性类别的资源,并将其用作部署流水线的初始类别。

与应用和云资源的分类过程类似,这种初始评估并不总是合适的。例如,您可以使用部署流水线来创建最终包含高度机密信息的资源。如果您限制部署流水线,使其可以创建但无法读取这些资源,则较低的机密类别可能就足够了。

为了确保机密性,Bell-LaPadula 模型建议部署流水线不得:

  • 使用机密性更高的输入工件
  • 将数据写入机密性较低的资源

Bell-LaPadula 模型。

根据 Bell-LaPadula 模型,上图显示了数据在流水线中的流动方式,以帮助确保数据机密性。

不允许部署流水线读取不需要的数据

部署流水线通常不需要访问数据,但它们可能仍然有权访问数据。这种过度授予访问权限的情况可能是因为:

  • 授予不正确的访问权限。例如,可能在项目级层授予部署流水线对 Cloud Storage 的访问权限。因此,部署流水线可以访问项目中的所有 Cloud Storage 存储桶,但其实访问单个存储桶可能就足够了。
  • 使用过于宽松的角色。例如,部署流水线可能会被授予提供 Cloud Storage 完整访问权限的角色。但是,拥有创建新存储桶的权限就足够了。

流水线可以访问的数据越多,数据被窃取的风险就越高。为了帮助最大限度地降低此风险,请避免向部署流水线授予对不需要的数据的访问权限。许多部署流水线根本不需要数据访问权限,因为它们的唯一目的是管理配置或软件部署。

不允许部署流水线向它们不需要的位置写入数据

为移除数据,不法分子需要具备访问权限,并将数据移出您的环境。部署流水线可以向其发送数据的存储和网络位置越多,不法分子使用其中一个位置渗漏数据的可能性就越大。

通过限制流水线可以发送数据的网络和存储位置的数量,您可以帮助降低风险:

  • 撤消对流水线不需要的资源的写入权限,即使资源不包含任何机密数据也是如此。
  • 阻止互联网访问或限制与一组列入许可名单的网络位置的连接。

对于被归类为中等机密或高度机密的流水线,限制出站访问尤为重要,因为它们可以访问机密数据或加密密钥材料。

使用 VPC Service Controls 帮助防止被破解的部署盗取数据

不法分子可能会试图使用部署流水线来部署被破解的代码,而不是让部署流水线执行数据渗漏。然后,被破解的代码可以从 Google Cloud 环境中窃取数据。

您可以使用 VPC Service Controls 来帮助降低此类数据盗用威胁的风险。借助 VPC Service Controls,您可以限制可从某些 Google Cloud 项目访问的资源和 API 集。

保持完整性

为了确保 Google Cloud 环境安全,您必须保护其完整性。包括:

  • 防止未经授权修改或删除数据或配置
  • 防止部署不受信任的代码或配置
  • 确保所有更改都留下清晰的审核跟踪记录

部署流水线可让您执行以下操作,帮助您保持环境的完整性:

  • 实施审核流程,例如以代码审核的形式
  • 对所有配置或代码更改实施一致的流程
  • 每次部署之前运行自动测试或快速检查

为了保证有效性,您必须确保不法分子无法破坏或规避这些措施。为防止此类活动,您必须保护以下各项的完整性:

  • 部署流水线及其配置
  • 底层基础架构
  • 部署流水线使用的所有输入

为了防止部署流水线易受攻击,请尝试确保部署流水线的完整性标准符合或超出其管理的资源的完整性需求。如需确定这些需求,您可以使用以下方法:

  1. 确定部署流水线需要访问的数据、应用和资源并对其进行分类。
  2. 查找完整性类别最高的资源,并将其用作部署流水线的类别。

为了保持部署流水线的完整性,Biba 模型建议:

  • 部署流水线不得使用较低完整性的输入工件。
  • 部署流水线不得将数据写入完整性更高的资源。

Biba 完整性模型。

根据 Biba 模型,上图显示了数据在流水线中的流动方式,以帮助确保数据完整性。

验证输入工件的真实性

许多部署流水线都会使用来自第三方来源的工件。此类工件可能包括:

  • Docker 基础映像
  • .rpm.deb 软件包
  • Maven、.npm 或 NuGet 库

不法分子可能会试图修改您的部署流水线,使其通过以下方式使用第三方工件的被破解版本:

  • 破解存储工件的代码库
  • 修改部署流水线的配置以使用其他源代码库
  • 上传名称相似或包含拼写错误的名称的恶意软件包

许多软件包管理器都允许您通过支持代码签名来验证软件包的真实性。例如,您可以使用 PGP 为 RPM 和 Maven 软件包签名。您可以使用 Authenticode 为 NuGet 软件包签名。

您可以通过以下方式使用代码签名来降低成为被破解的第三方软件包的受害者风险:

  • 要求所有第三方工件都经过签名
  • 维护受信任的发布方证书或公钥的精选列表
  • 让部署流水线根据受信任的发布方列表验证第三方工件的签名

或者,您可以验证工件的哈希值。对于不支持代码签名且不经常更改的工件,您可以使用此方法。

确保底层基础架构满足完整性需求

不法分子可能试图破解部署流水线的基础架构(而不是破解部署流水线本身),包括:

  • 运行部署流水线的 CI/CD 软件
  • 流水线使用的工具,例如 Terraform、kubectl 或 Docker
  • 操作系统及其所有组件

由于支持部署流水线的基础架构通常很复杂,并且可能包含来自不同供应商或来源的组件,因此此类安全漏洞可能难以检测。

您可以通过以下方式帮助降低基础架构被破解的风险:

  • 确保基础架构及其所有组件符合与部署流水线及其管理的 Google Cloud 资源相同的完整性标准
  • 确保工具来自可信来源并验证其真实性
  • 定期从头开始重新构建基础架构
  • 安全强化型虚拟机上运行部署流水线

在流水线中应用完整性控制

虽然不法分子是威胁,但它们并不是唯一可能破坏 Google Cloud 环境完整性的软件或配置更改来源。此类更改也可能由开发者启动,只是由于疏忽大意或拼写错误和其他错误所致。

您可以配置部署流水线来应用其他完整性控制,以帮助降低无意中应用有风险的更改的风险。此类控制措施可以包括:

  • 对代码和配置进行静态分析
  • 要求所有更改都符合一组规则(政策即代码)
  • 限制可以同时完成的更改数量

后续步骤