从管道安全访问存储库

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

若要保护运行其作的代码,组织必须仔细控制对其源代码存储库的访问。 本文介绍了 Azure Pipelines 如何生成和发布管道安全地访问存储库,以最大程度地降低未经授权的访问风险。

本文是一系列教程的一部分,可帮助实现 Azure Pipelines 的安全措施。 有关更多信息,请参阅 Azure Pipelines 安全指南

先决条件

类别 要求
Azure DevOps - 在使 Azure DevOps 安全和保护 Azure Pipelines 中实施建议。
- 对 YAML 和 Azure Pipelines 的基本知识。 有关详细信息,请参阅 创建第一个管道
权限 - 修改管道权限: 项目管理员组的成员
- 要修改组织权限,您需要成为 项目集合管理员组 的成员。

管道的基于项目的标识

管道使用标识在执行期间访问存储库、服务连接和变量组等资源。 管道可以利用两种类型的标识:集合级别或项目级。

集合级标识易于设置和使用,但项目级标识优先考虑安全性。 若要增强安全性,请使用项目级标识来运行管道。 项目级标识只能在其项目中访问资源,最大限度地减少恶意参与者的任何未经授权的访问的影响。 有关详细信息,请参阅 作用域内生成标识作业授权范围

若要将管道配置为使用项目级标识,请在管道项目的项目设置下的管道设置中,启用非发布管道的作业授权范围限制为当前项目或>。

提高存储库访问安全性的步骤

项目管理员项目集合管理员可以执行以下步骤,以提高从管道访问 Git 存储库的安全性。

  1. 检查管道以识别其他项目中所需的任何存储库。 如果您为非发布管道启用了将作业授权范围限于当前项目,那么管道只能从当前项目的存储库中签出代码。

  2. 授予管道项目对所需的任何其他项目的访问权限。 有关详细信息,请参阅 为项目配置权限以访问同一项目集合中的另一个项目

  3. 授予管道生成标识对他们签出的每个存储库的 读取 访问权限。此外,向管道标识授予对用作所需存储库子模块的任何存储库的 读取 访问权限。 有关详细信息,请参阅 配置权限以访问同一项目集合中的另一个存储库

  4. 为管道项目启用以下组织或项目设置:

    • 将作业授权范围仅限于当前项目,适用于非发布管道
    • 如果您的项目具有发布管道,请将作业授权范围限制为当前项目以用于发布管道。
    • 如果项目具有 Azure Repos YAML 管道,请保护对 YAML 管道中存储库的访问

    通过在“组织设置”“项目设置”、>、>、>中将开关调至来启用这些设置。

    如果在 组织设置中启用这些设置,则无法在 项目设置中重写这些设置。 如果未在 组织设置中启用这些设置,则可以在项目级别启用这些设置。

将存储库用作子模块

如果在项目中将另一个存储库用作子模块,则即便授予管道对两个存储库的读取访问权限,签出的过程在签出子模块时仍可能会失败。 若要解决此问题,请显式签出子模块存储库,然后再签出使用它们的其它存储库。 有关详细信息,请参阅 “查看子模块”。

GitHub 存储库

以下安全注意事项适用于对 GitHub 存储库的管道访问。 有关详细信息,请参阅访问 GitHub 存储库

GitHub 服务连接

若要使用 GitHub 存储库,Azure Pipelines 需要 GitHub 服务连接。 加强服务连接安全性:

  • 仅允许访问管道需要运行的存储库。
  • 不要选择 “向服务连接的所有管道授予访问权限 ”。 为每个使用它的管道显式授权服务连接。

向 GitHub 存储库进行身份验证

若要触发生成和在生成期间提取代码,必须向 Azure Pipelines 授予对 GitHub 存储库的访问权限。 此访问可以使用 GitHub 个人访问令牌(PAT)、OAuth 或 GitHub Azure Pipelines 应用身份验证。 有关详细信息,请参阅访问 GitHub 存储库

GitHub Azure Pipelines 应用是持续集成(CI)管道的建议身份验证类型。 GitHub 状态更新和生成将使用 Azure Pipelines 的身份,而不是使用你个人的 GitHub 身份。 安装应用时,可以限制应用可以访问哪些存储库以提高安全性。

OAuth 和 PAT 身份验证使用个人 GitHub 标识,必须获得管道访问的授权。 出于安全问题,不建议使用 PAT。 如果必须使用 PAT 身份验证,请选择细粒度的 PAT,并将范围限制为某些用户、存储库和权限。 有关详细信息,请参阅 管理个人访问令牌

注释

如果为 GitHub 组织中的所有存储库安装 GitHub 应用,则应用使用的令牌可以访问组织中的所有专用和公共存储库。 为了提高安全性,可将专用存储库分开到单独的组织,或显式选择应用可以访问的存储库。

派生 GitHub 存储库

分叉存储库会增加管道中恶意代码执行或敏感信息发布的风险。 源自组织外部的分支构成特定风险。

为了最大程度地减少来自分叉存储库的风险,在项目设置组织设置管道和>中,默认启用限制从分叉的 GitHub 存储库生成拉取请求和>。

若要允许从分叉 GitHub 存储库进行生成,同时降低风险,请选择 从分叉存储库安全地生成拉取请求。 此设置禁止使机密可用或使用与正常生成相同的权限,并且需要团队成员的 PR 注释来触发管道。

或者,可以选择“ 自定义规则”以从分叉存储库生成拉取请求 ,以进一步自定义这些设置。

用于限制分叉存储库生成的项目设置的屏幕截图。

提高分叉安全性的其他方法包括:

  • 如果使用拉取请求验证来触发生成,请在管道定义的“触发器”部分中取消选择从该存储库的派生仓库建立的拉取请求,或确保取消选择使机密对派生仓库的生成可用使派生仓库的生成具有与常规生成相同的权限。 还可以在 生成拉取请求之前选择“要求团队成员的注释”。

  • 使用Microsoft托管代理从分支生成。 然后在构建完成后立即从代理中删除资源。 如果使用自承载代理,请定期清理并且更新代理,或者对不同的分支或分支代码库使用单独的代理。

Azure Repos 存储库

保护对 YAML 管道中存储库的访问权限

保护对存储库访问的 YAML 管道 项目或组织设置中,为 YAML 管道提供精细权限。 此设置使 YAML 管道显式请求访问任何存储库的权限,而不考虑项目。 有关详细信息,请参阅 保护对 YAML 管道中存储库的访问

注释

YAML 管道设置中的“保护对存储库的访问”不适用于 GitHub 存储库。

启用此设置后,Azure Repos YAML 管道始终在首次运行时请求访问存储库的权限。 会看到权限请求,如以下屏幕截图:

启用“保护对 YAML 管道中存储库的访问权限”开关后首次运行 SpaceGameWeb 管道的屏幕截图。

选择 “允许 ”以授予对管道存储库或资源的权限。 流水线运行成功。

允许访问 YAML 管道中的存储库的屏幕截图。

使用 git 命令行访问或切换到其他存储库

启用git clone https://github/fabrikam-tailspin/FabrikamFiber/_git/OtherRepo/时,命令行脚本可能会git clone https://github/fabrikam-tailspin/FabrikamFiber/_git/OtherRepo/失败。 若要解决此问题,请使用OtherRepo命令显式检出checkout存储库,例如checkout: git://FabrikamFiber/OtherRepo

Azure Repos 示例

以下示例演示了提高管道中 Azure Repos 访问的安全性的过程。

组织 https://dev.azure.com/fabrikam-tailspin 包含 SpaceGameWebFabrikamFiber 项目。

  • SpaceGameWeb 项目包含 SpaceGameWebSpaceGameWebReact 存储库。

    SpaceGameWeb 存储库结构的屏幕截图。

  • FabrikamFiber 项目包含 FabrikamFiberFabrikamChatFabrikamFiberLib 存储库。 FabrikamFiber 存储库使用 FabrikamFiberLib 存储库作为子模块。

    FabrikamFiber 存储库结构的屏幕截图。

SpaceGameWeb 项目中,SpaceGameWeb 管道会签出 SpaceGameWeb 项目中的 SpaceGameWebReact 仓库,以及 FabrikamFiber 项目中的 FabrikamFiberFabrikamChat 仓库。

如果未将项目设置为使用基于项目的生成标识或保护对 YAML 管道中存储库的访问, SpaceGameWeb 管道可以访问组织中的所有项目中的所有存储库并成功运行。

使用项目级标识

若要提高安全性,请使用项目级标识来运行管道。 在“项目设置”“组织设置”中,启用“将作业授权范围限制为当前项目(适用于非发布管道)”切换。

如果启用此设置,管道只能访问 SpaceGameWeb 项目中的资源,该项目仅包含 SpaceGameWebSpaceGameWebReact 存储库。 管道失败,因为它无法签出 FabrikamFiber 项目中的存储库。

你会看到错误 remote: TF401019: The Git repository with name or identifier FabrikamChat does not exist or you do not have permissions for the operation you are attemptingremote: TF401019: The Git repository with name or identifier FabrikamFiber does not exist or you do not have permissions for the operation you are attempting

若要解决此问题,请授予管道项目对 FabrikamFiber 项目的访问权限,并授予管道标识对 FabrikamFiberFabrikamChatFabrikamFiberLib 存储库的读取访问权限。

显式签出子模块

FabrikamFiber 存储库使用 FabrikamFiberLib 存储库作为子模块。 即使授予管道对这两个存储库的访问权限,在签出 FabrikamFiberLib 子模块时,FabrikamFiber 存储库的签出仍然会失败。

若要解决此问题,请在签出 FabrikamFiber 存储库之前显式签出 FabrikamFiberLib 存储库。 在步骤checkout: git://FabrikamFiber/FabrikamFiberLib之前添加步骤checkout: FabrikamFiber。 示例管道现在成功。

保护对 YAML 管道的访问

如果示例 SpaceGameWeb 管道是 YAML 管道,并且启用了 保护 YAML 管道中对存储库的访问,那么该管道在首次运行时必须拥有权限以访问 SpaceGameWebReactFabrikamFiberFabrikamChat 存储库。

以下代码显示了完整的 YAML 管道。

trigger:
- main

pool:
  vmImage: ubuntu-latest

resources:
  repositories:
    - repository: SpaceGameWebReact
      name: SpaceGameWeb/SpaceGameWebReact
      type: git
    - repository: FabrikamFiber
      name: FabrikamFiber/FabrikamFiber
      type: git
    - repository: FabrikamChat
      name: FabrikamFiber/FabrikamChat
      type: git

steps:
  - script: echo "Building SpaceGameWeb"
  - checkout: SpaceGameWebReact
  - checkout: FabrikamChat
    condition: always()  
  - checkout: git://FabrikamFiber/FabrikamFiberLib
  - checkout: FabrikamFiber
    submodules: true
    condition: always()
  - script: |
      cd FabrikamFiber
      git -c http.extraheader="AUTHORIZATION: bearer $(System.AccessToken)" submodule update --recursive --remote
  - script: cat $(Build.Repository.LocalPath)/FabrikamFiber/FabrikamFiberLib/README.md

更多存储库安全措施

  • 为降低 YAML 和经典管道共享资源的安全风险,在项目设置组织设置中启用“禁用创建经典生成管道”和“禁用创建经典发布管道”切换,以禁用创建经典管道。 默认情况下,新建组织禁用经典构建和发布管道的创建。

  • 使用管道模板定义管道 结构,并帮助防止恶意代码渗透。 模板还可以自动执行凭据扫描或强制检查受保护资源等任务。

  • 每次管道请求存储库时,都需要 手动批准 。 有关详细信息,请参阅审批和检查

  • 使用 受保护的分支检查 来防止流水线在未经授权的分支上自动运行。

  • 设置仅在指定的 YAML 管道中使用的存储库。 有关详细信息,请参阅 向存储库资源添加管道权限

  • 通过仅为管道 resources 部分中列出的存储库提供令牌来限制 Azure Pipelines 访问令牌的范围。 有关详细信息,请参阅 存储库保护