在流水线中使用服务账号的最佳做法

借助部署流水线,您可以自动获取代码或预构建工件并将其部署到 Google Cloud 环境,并且您可以使用这些流水线来代替 Google Cloud 控制台或 Google Cloud CLI 等交互式工具。

部署流水线与 Google Cloud 控制台或 gcloud CLI 等交互式工具的不同之处在于,它们会与 Identity and Access Management 进行交互,您在保护 Google Cloud 资源时必须考虑这些差异。

Google Cloud 在允许您访问资源之前会执行访问权限检查。为了执行此项检查,IAM 通常会考虑以下因素:

  • 您的身份
  • 您尝试访问的资源及其 IAM 允许和拒绝政策
  • 请求的上下文(可能包括时间和位置)

在部署流水线中,您很少会直接调用 Google Cloud API。相反,您会使用工具来访问 Google Cloud 资源。Google Cloud 控制台或 gcloud CLI 等工具会要求您首先授权该工具代表您访问资源。提供此授权即表示您授予该工具在进行 API 调用时使用您的身份。

与 Google Cloud 控制台或 gcloud CLI 一样,部署流水线可代表您执行操作:获取您的更改(以源代码表示)并将其部署到 Google Cloud。但与 Google Cloud 控制台或 gcloud CLI 不同的是,部署流水线通常不会使用您的身份来执行部署:

  1. 用户通常不会直接与部署流水线交互;而是通过将代码更改推送到源代码库或批准代码审核来与源代码控制系统 (SCM) 进行交互。

  2. 部署流水线会从 SCM 系统读取已提交的代码更改,并将其部署到 Google Cloud。

    在执行部署时,部署流水线通常无法使用您的身份,原因如下:

    1. 源代码及其元数据可能不会表明您是作者,或者作者信息不是防篡改的(就如同未签名的 Git 提交一样)
    2. 您用于提交源代码的身份可能与您的 Google 身份不同,并且这两个身份间无法进行映射

    因此,大多数部署流水线都会使用服务账号以自己的身份执行部署。

  3. 当部署流水线访问 Google Cloud 时,IAM 仅根据流水线使用的服务账号的身份(而不是用户账号的身份)来允许或拒绝访问。

部署流水线

部署流水线使用服务账号访问 Google Cloud 具有以下优势:

  • 服务账号的生命周期与用户账号的生命周期不会相互关联。通过将流水线配置为使用服务账号,您可以确保即使代码作者不再属于您的组织,也可以部署代码。
  • 使用部署流水线管理资源时,您无需授予用户资源的任何访问权限,或者您也可以只为其授予只读权限。这种方法可让您更轻松地管理 IAM 政策,并强制用户使用部署流水线来执行所有修改。

但是,使用服务账号也会带来新的威胁。其中包括:

  • 仿冒:不法分子可能试图仿冒部署流水线的身份,或窃取其凭据以获得对资源的访问权限。
  • 提升权限:流水线可能被诱骗执行它不应执行的操作,从而有效地成为混淆代理
  • 不可否认性:流水线执行操作后,可能难以重建其执行操作的原因,并且无法确定是哪个开发者或哪项代码更改触发了操作。
  • 篡改:流水线可能会被滥用,从而破坏云环境的完整性或安全控制。
  • 信息泄露:不法分子可能会试图使用部署流水线来泄露机密数据。

防范仿冒威胁

如需向部署流水线授予对 Google Cloud 的访问权限,您通常要执行以下操作:

  1. 创建服务账号
  2. 授予服务账号访问所需资源的权限
  3. 将部署流水线配置为使用服务账号

从 IAM 的角度来看,服务账号代表部署流水线,但部署流水线和服务账号实际是两个单独的实体。如果保护不当,不法分子可能会使用同一服务账号,从而“仿冒”部署流水线的身份。

以下部分介绍了可帮助您降低此类威胁风险的最佳做法。

避免将服务账号关联到 CI/CD 系统使用的虚拟机实例

对于部署在 Compute Engine 上且需要访问 Google Cloud 资源的应用,通常最好将服务账号关联到底层虚拟机实例。对于使用 Compute Engine 虚拟机运行不同部署流水线的 CI/CD 系统,如果同一虚拟机实例可能用于运行需要访问不同资源的不同部署流水线,则这种做法可能会出现问题。

在这种情况下,可以让每个部署流水线使用单独的服务账号,而不是让部署流水线使用关联的服务账号来访问资源。请避免将服务账号关联到 CI/CD 系统使用的虚拟机实例,或者关联仅限访问关键服务(如 Cloud Logging)的服务账号。

为每个部署流水线使用专用服务账号

如果您允许多个部署流水线使用相同的服务账号,则 IAM 将无法区分这些流水线:这些流水线可以访问相同的资源,并且审核日志可能没有足够的信息来确定是哪个部署流水线触发了资源被访问或更改。

为避免混淆,请在部署流水线和服务账号之间保持一对一的关系。为每个部署流水线创建一个专用服务账号,并确保:

  • 将部署流水线的名称或 ID 合并到服务账号的电子邮件地址中。遵循一致的命名方案可帮助您根据服务账号的名称确定部署流水线,反之亦然。
  • 仅向服务账号授予对特定部署流水线所需的资源的访问权限。

尽可能使用工作负载身份联合

GitHub Actions 或 GitLab 等 CI/CD 系统允许部署流水线获取 OpenID Connect 令牌来声明部署流水线的身份。您可以通过使用工作负载身份联合,让部署流水线使用这些令牌来模拟服务账号。

使用工作负载身份联合可以帮助您避免使用服务账号密钥的风险

使用 VPC Service Controls 来减小泄露凭据造成的影响

如果不法分子成功地从其中一个部署流水线中窃取了访问令牌或服务账号密钥,那么他们可能会试图使用此凭据从他们控制的其他机器访问更多资源。

默认情况下,IAM 在做出访问权限决策时不会考虑地理位置、来源 IP 地址或来源 Google Cloud 项目。因此,被盗凭据可用于任何位置。

您可以通过将项目放置在 VPC 服务边界内并使用入站规则,对可访问 Google Cloud 资源的来源位置施加限制:

  • 如果部署流水线在 Google Cloud 上运行,则可以将入站规则配置为仅允许从包含 CI/CD 系统的项目进行访问。
  • 如果部署流水线在 Google Cloud 外部运行,则可以创建访问权限级别来仅允许从特定地理位置或 IP 范围进行访问。然后您可以创建入站规则,允许满足此访问权限级别的客户端进行访问。

防范篡改威胁

对于存储在 Google Cloud 上的某些数据,您可能会发现防范未经授权的修改或删除尤为重要。如果您尤其要注意防范未经授权的修改或删除,那么这些数据便可以被定性为高度完整性数据。

为保持数据完整性,您必须确保用于存储和管理这些数据的 Google Cloud 资源已安全地进行配置并且必须保持其完整性。

部署流水线可以帮助您保持数据和资源的完整性,但也可能带来风险:如果某个组件的流水线不符合其管理的资源的完整性要求,则该部署流水线便会成为一个潜在威胁,可能会导致不法分子篡改您的数据或资源。

以下部分介绍了可帮助您降低篡改威胁风险的最佳做法。

限制对安全控制措施的访问权限

为确保 Google Cloud 上数据和资源的安全性和完整性,您可以使用如下安全控制措施:

  • 允许政策和拒绝政策
  • 组织政策限制条件
  • VPC Service Controls 边界、访问权限级别和入站政策

这些安全控制措施本身也是资源。如果安全控制措施被篡改,则会损害安全控制措施所适用的资源的完整性。因此,安全控制措施的完整性与其所适用资源的完整性一样重要。

如果让部署流水线管理安全控制措施,那么部署流水线应负责维护安全控制措施的完整性。因此,部署流水线本身的完整性与其管理的安全控制措施以及这些控制措施所适用的资源的完整性一样重要。

您可以通过以下方式限制部署流水线对资源完整性的影响:

  • 不向部署流水线授予对允许政策、拒绝政策和其他安全控制措施的访问权限,并且限制其对其他资源的访问权限
  • 仅授予对所选安全控制措施的访问权限(例如特定资源或项目的允许政策和拒绝政策),而不授予对影响多个资源或项目的更广泛控制措施的访问权限

如果您的部署流水线、其组件和底层基础架构无法满足某些安全控制措施的完整性要求,最好避免让部署流水线管理这些安全控制措施。

防范不可否认性威胁

有时,您可能会注意到有可疑活动影响到 Google Cloud 上的某项资源。在这种情况下,您必须能够详细了解该活动,并且最好能够重建导致该活动的事件链。

借助 Cloud Audit Logs,您可以了解访问或修改资源的时间以及涉及的用户。虽然 Cloud Audit Logs 提供了基本的信息来帮助您分析可疑活动,但这些日志提供的信息可能仍然不够:如果您使用部署流水线,则还必须能够将 Cloud Audit Logs 与您的部署流水线生成的日志关联起来。

本部分包含的最佳做法可帮助您在 Google Cloud 和部署流水线中维护审核跟踪记录。

确保您可以将部署流水线日志与 Cloud Audit Logs 关联起来

Cloud Audit Logs 中包含发起活动的用户的时间戳和相关信息。如果您为每个部署流水线使用专用服务账号,则此信息可帮助您识别发起活动的部署流水线,还可以帮助您缩小所涉及代码更改和流水线运行的范围。但是,如果没有足够的信息可用来将 Cloud Audit Logs 与部署流水线日志关联起来,则很难确定导致活动的确切流水线运行和代码更改。

您可以通过多种方式丰富 Cloud Audit Logs 以包含更多信息,这包括:

  • 使用 Terraform 时,指定请求原因来指示 CI/CD 流水线运行。
  • 向 API 请求添加 X-Goog-Request-Reason HTTP 标头,并传递部署流水线运行的 ID。
  • 使用嵌入部署流水线运行 ID 的自定义 User-Agent

您还可以丰富部署流水线发出的日志:

  • 记录 CI/CD 流水线每次运行时执行的 API 请求。
  • 每当 API 返回操作 ID 时,在 CI/CD 系统日志中记录该 ID。

使部署流水线日志和 Cloud Audit Logs 的保留期限保持一致

要分析与部署流水线相关的可疑活动,通常需要分析多种类型的日志,包括管理员活动审核日志数据访问审核日志以及部署流水线日志。

Cloud Logging 仅将日志保留一段时间。默认情况下,数据访问审核日志的保留期限比管理员活动审核日志要短。运行部署流水线的系统也可能会在一段时间后舍弃其日志。根据部署流水线的性质以及部署流水线所管理资源的重要性,这些默认保留期限可能不够长或不一致。

要保证日志在需要时可用,请确保不同系统使用的日志保留期限一致且足够长。

如有必要,请自定义数据访问审核日志的保留期限,或设置自定义接收器来将日志路由到自定义存储位置。

防范信息泄露威胁

如果部署流水线的服务账号有权访问机密数据,不法分子可能会试图使用部署流水线来泄露该数据。部署流水线对数据的访问可以是直接的,也可以是间接的:

  • 直接:部署流水线的服务账号可能具有从 Cloud Storage、BigQuery 或其他位置读取机密数据的权限。此访问权限可能是有意授予的,但也有可能是因授予过多访问权限而造成的意外。

    如果不法分子获得对能够直接访问机密数据的部署流水线的访问权限,那么他们可能会试图使用服务账号的访问令牌来访问和渗漏数据。

  • 间接:为了部署配置或新的软件版本,部署流水线的服务账号可能有权创建或重新部署虚拟机实例、Cloud Run 应用或其他计算资源。其中一些计算资源可能具有关联的服务账号,并且该账号有权访问机密数据。

    在这种情况下,不法分子可能会试图破解部署流水线,以将恶意代码部署到其中一个计算资源,并通过此代码渗漏机密数据。

本部分介绍的最佳做法可帮助您限制机密数据泄露的风险。

避免直接授予对机密数据的访问权限

在部署基础架构、配置或新的软件版本时,部署流水线通常不需要访问现有数据。相反,您可以将其访问权限限制在不包含任何数据的资源或至少不包含任何机密数据的资源即可。

以下方法可帮助您尽可能减少对现有潜在机密数据的访问权限:

  • 您只需向部署流水线的服务账号授予对特定资源的访问权限,而不是授予整个项目的访问权限。
  • 授予创建权限,但不授予读取权限。例如,通过授予 Storage Object Creator 角色 (roles/storage.objectCreator),您可以允许服务账号将新对象上传到 Cloud Storage 存储桶,同时不授予读取现有数据的权限。
  • 仅限基础架构即代码 (IaC) 系统访问不太机密的资源 - 例如,使用 IaC 来管理虚拟机实例或网络,但不用来管理机密的 BigQuery 数据集。

使用 VPC Service Controls 帮助防范数据渗漏

您可以在 VPC Service Controls 边界中部署 Google Cloud 资源,以降低间接数据渗漏的风险。

如果部署流水线在 Google Cloud 外部运行,或者属于其他边界的一部分,则可以通过配置入站规则向流水线的服务账号授予对边界的访问权限。如果可能,请将入站规则配置为仅允许从部署流水线使用的 IP 地址进行访问,并且仅允许访问部署流水线真正需要的服务。

防范提权威胁

当部署流水线使用服务账号访问 Google Cloud 资源时,无论编写代码或进行配置更改的开发者或用户是何状态,都会发生提权。由于流水线服务账号与开发者的身份之间没有关联,因此这会导致部署流水线容易遭到混淆代理攻击,在这种情况下,不法分子会诱骗流水线执行他们自己无法执行且流水线本不该执行的操作。

本部分包含的最佳做法可帮助您降低部署流水线被滥用导致提权的风险。

限制对部署流水线及所有输入的访问权限

大多数部署流水线使用源代码库作为其主要输入来源,并且可能会在检测到某些分支(例如 main 分支)中的代码更改时立即自动触发。部署流水线通常无法验证其在源代码库中找到的代码和配置是否真实可信。因此,此架构的安全性取决于:

  • 控制谁可以将代码和配置提交到部署流水线使用的代码库和分支。
  • 强制执行提交更改前必须满足的条件(例如成功的代码审核、静态分析或自动化测试)。

为使这些控制措施生效,您还必须确保不法分子无法通过以下方式绕开这些限制条件:

  • 修改源代码库或部署流水线的配置。
  • 篡改支持部署流水线的基础架构(例如虚拟机和存储空间)。
  • 修改或替换源代码库外部的输入,例如软件包、容器映像或库。

由部署流水线管理时,您在 Google Cloud 上的资源只能与部署流水线、其配置、基础架构和输入具有同等安全性。因此,若要保护您的 Google Cloud 资源,您必须同样地保护好这些组件。

避免让部署流水线修改政策

对于大多数资源类型,IAM 会定义 RESOURCE_TYPE.setIamPolicy 权限。借助此权限,用户可以修改资源的 IAM 允许政策,以向其他用户授予访问权限或者修改和扩展自己的访问权限。除非通过拒绝政策进行限制,否则如果为用户或服务账号授予 *.setIamPolicy 权限,那么也会授予他们对资源的完整访问权限。

请尽可能避免让部署流水线修改对资源的访问权限。在向流水线的服务账号授予对 Google Cloud 资源的访问权限时,请使用不包含任何 *.setIamPolicy 权限的角色,并避免使用 EditorOwner 等基本角色。

对于某些部署流水线,可能不可避免地需要授予修改允许政策或拒绝政策的权限:例如,部署流水线的用途可能是创建新资源或管理对现有资源的访问权限。在这些情况下,您仍然可以通过以下方式限制部署可以修改访问权限的程度:

  • 仅授予特定资源的 *.setIamPolicy 权限,而不是授予整个项目的权限。
  • 使用 IAM 拒绝政策来限制可授予的权限集,或限制可向其授予权限的主账号。
  • 使用 IAM Conditions 来限制可以向流水线授予哪些角色,并且仅允许授予不包含 *.setIamPolicy 权限的角色。

不要在日志中显示服务账号凭据

许多用户(包括无权修改流水线配置的用户)通常都可以访问部署流水线生成的日志。这些日志可能会意外通过回显以下信息显示凭据:

  • 环境变量的内容
  • 命令行参数
  • 诊断输出

如果日志意外显示访问令牌等凭据,那么不法分子可能会滥用这些凭据来提升其权限。防止日志泄露凭据的方法包括:

  • 避免将访问令牌或其他凭据作为命令行参数传递
  • 避免将凭据存储在环境变量中
  • 将 CI/CD 系统配置为自动检测和遮盖令牌和其他凭据(如果可能)

后续步骤