部署流水线是一种自动化流程,用于获取代码或预构建工件并将其部署到测试环境或生产环境。部署流水线通常用于部署应用、配置或云基础架构(基础架构即代码),在云部署的整体安全状况中发挥着重要作用。
本指南面向 DevOps 和安全工程师,介绍了根据机密性、完整性和可用性要求设计安全部署流水线的最佳实践。
架构
下图显示了部署流水线中的数据流。它说明了如何将工件转换为资源。
部署流水线通常是更大规模的持续集成/持续交付 (CI/CD) 工作流的一部分,通常使用以下某种模型实现:
推送模型:在此模型中,您可以使用中央 CI/CD 系统(如 Jenkins 或 GitLab)实现部署流水线。此 CI/CD 系统可以运行在 Google Cloud、本地环境或其他云环境中。通常,同一 CI/CD 系统用于管理多个部署流水线。
推送模型会导致采用集中式架构,其中包含少数 CI/CD 系统,用于管理可能数量众多的资源或应用。例如,您可以使用单个 Jenkins 或 GitLab 实例来管理整个生产环境,包括其中的所有项目和应用。
拉取模型:在此模型中,部署过程由与资源一起部署的代理实现,例如,在同一个 Kubernetes 集群中。该代理会从集中位置拉取工件或源代码,并将其部署到本地。每个代理都管理一个或两个资源。
拉取模型会带来更分散的架构,其中可能包含大量单用途径代理。
与手动部署相比,始终使用部署流水线可以带来以下好处:
- 提高效率,因为无需人工操作。
- 可靠性更高,因为该过程是完全自动化且可重复的。
- 可提高可追溯性,因为您可以将所有部署追溯到代码更改或输入工件。
为了正常运行,部署流水线需要对其管理的资源拥有访问权限:
- 使用 Terraform 等工具部署基础架构的流水线可能需要创建、修改甚至删除资源,例如虚拟机实例、子网或 Cloud Storage 存储分区。
- 部署应用的流水线可能需要将新的容器映像上传到 Artifact Registry,并将新应用版本部署到 App Engine、Cloud Run 或 Google 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 服务器内容
- 中等完整性:审核日志
- 高完整性:应用配置文件
机密性高,完整性低、中、高的资源
以下资源示例都具有较高的机密性:
- 完整性较低:使用数据和个人身份信息
- 中等完整性:密钥
- 高完整性:财务数据、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环境中窃取数据。
您可以通过尽可能减少对机密资源的访问来降低机密性风险。不过,移除对机密资源的所有访问权限可能并不可行。因此,您必须设计部署流水线,使其满足其管理的资源的机密性要求。如需确定这些需求,您可以使用以下方法:
- 确定部署流水线需要访问的数据、应用和资源,并对其进行分类。
- 找到机密性类别最高的资源,并将其用作部署流水线的初始类别。
与应用和云资源的分类流程类似,此初始评估并不总是适用。例如,您可以使用部署流水线创建最终将包含高度机密信息的资源。如果您限制部署流水线,使其只能创建但无法读取这些资源,那么较低的机密性类别可能就足够了。
为了保持机密性,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 环境的安全,您必须保护其完整性。其中包括:
- 防止未经授权修改或删除数据或配置
- 防止部署不可信的代码或配置
- 确保所有更改都会留下明确的审核跟踪记录
部署流水线可帮助您保持环境的完整性,具体方法如下:
- 实现审批流程,例如以代码审核的形式
- 对所有配置或代码变更强制执行一致的流程
- 在每次部署之前运行自动化测试或快速检查
为了保证有效性,您必须确保不法分子无法破坏或规避这些措施。为防止此类活动,您必须保护以下各项的完整性:
- 部署流水线及其配置
- 底层基础架构
- 部署流水线使用的所有输入
为防止部署流水线变得易受攻击,请尽量确保部署流水线的完整性标准与其管理的资源的完整性要求一致或高于其要求。如需确定这些需求,您可以采用以下方法:
- 确定部署流水线需要访问的数据、应用和资源,并对其进行分类。
- 找到完整性类别最高的资源,并将其用作部署流水线的类别。
为确保部署流水线的完整性,Biba 模型建议:
- 部署流水线不得使用完整性较低的输入工件。
- 部署流水线不得将数据写入完整性更高的资源。
根据 Biba 模型,上图展示了数据应如何在流水线中流动,以帮助确保数据完整性。
验证输入工件是否真实
许多部署流水线都会使用来自第三方来源的工件。此类工件可能包括:
- Docker 基础映像
.rpm
或.deb
软件包- Maven、
.npm
或 NuGet 库
不法分子可能会通过以下方式尝试修改您的部署流水线,使其使用已泄露版本的第三方工件:
- 破解存储工件的代码库
- 修改部署流水线的配置以使用其他源代码库
- 上传名称相似或包含拼写错误的恶意软件包
许多软件包管理器都支持代码签名,可让您验证软件包的真实性。例如,您可以使用 PGP 对 RPM 和 Maven 软件包进行签名。您可以使用 Authenticode 为 NuGet 软件包签名。
您可以通过以下方式使用代码签名来降低成为被破解的第三方软件包的受害者风险:
- 要求所有第三方工件均已签名
- 维护受信任的发布方证书或公钥的精选列表
- 让部署流水线根据受信任的发布方列表验证第三方工件的签名
或者,您也可以验证工件的哈希值。对于不支持代码签名且不经常更改的工件,您可以使用此方法。
确保底层基础架构符合您的完整性要求
不法分子可能试图破解部署流水线的基础架构(而不是破解部署流水线本身),包括:
- 运行部署流水线的 CI/CD 软件
- 流水线使用的工具,例如 Terraform、kubectl 或 Docker
- 操作系统及其所有组件
由于部署流水线的基础架构通常很复杂,并且可能包含来自不同供应商或来源的组件,因此很难检测到此类安全漏洞。
您可以通过以下方式降低基础架构遭到入侵的风险:
- 确保基础架构及其所有组件符合与部署流水线及其管理的资源相同的完整性标准 Google Cloud
- 确保工具来自可信来源并验证其真实性
- 定期从头开始重新构建基础架构
- 在屏蔽虚拟机上运行部署流水线
在流水线中应用完整性控制措施
虽然恶意攻击者是威胁,但他们并不是可能破坏Google Cloud 环境完整性的唯一软件或配置更改来源。此类更改也可能由开发者启动,只是由于疏忽大意或拼写错误和其他错误所致。
通过配置部署流水线以应用额外的完整性控制措施,您可以降低无意中应用风险更高的更改的风险。此类控制措施可能包括:
- 对代码和配置执行静态分析
- 要求所有更改都符合一组规则(政策即代码)
- 限制同时可以进行的更改数量
后续步骤
- 了解在部署流水线中使用服务账号的最佳实践。
- 查看保护服务账号的最佳实践。
- 详细了解如何调查和应对威胁。
- 如需查看更多参考架构、图表和最佳实践,请浏览云架构中心。