从管道对 Azure Repos 的安全访问

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

存储库对于业务成功至关重要,因为它们提供支持运营的代码。 应仔细控制对存储库的访问。 本文介绍如何在访问 Azure Repos 时增强 生成管道经典发布管道 安全性,以降低未经授权的访问风险。

若要确保对 Azure 存储库的安全访问,请启用以下切换:

  • 将作业授权范围限制为非发布管道的当前项目
  • 将作业授权范围限制为当前项目的发布管道
  • 保护对 YAML 管道中存储库的访问权限

基本流程

用于保护管道的以下步骤在所有管道中都类似:

  1. 确定管道需要访问同一组织中但跨不同项目访问的 Azure Repos 存储库。
    为此,请检查管道或为(非)发布管道启用限制作业授权范围,并记下管道无法签出哪些存储库。子模块存储库可能不会显示在第一次失败的运行中。
  2. 为包含管道需要访问的存储库的每个项目 授予管道的生成标识访问权限。
  3. 为管道的生成标识授予管道签出的每个存储库的“读取”访问权限。
  4. 为管道的生成标识 授予对该存储库的读取 访问权限,该存储库 由管道签出并位于同一项目中的存储库中,该存储库用作子模块。
  5. 为非发布管道启用将作业授权范围限制为当前项目、将作业授权范围限制为当前项目的发布管道,以及保护对 YAML 管道中存储库的访问。

生成管道

为了说明在管道访问 Azure Repos 时提高管道安全性所要采取的步骤,请使用以下示例。

  • 假设你正在 SpaceGameWeb Azure Repos 存储库中处理 fabrikam-tailspin/SpaceGameWeb 项目中托管的 SpaceGameWeb 管道。
  • 管道SpaceGameWeb签出SpaceGameWebReact同一项目中的存储库,以及项目中的FabrikamFiberfabrikam-tailspin/FabrikamFiber存储库和FabrikamChat存储库。
  • 存储库 FabrikamFiber 使用 FabrikamFiberLib 存储库作为子模块,托管在同一项目中。
  • SpaceGameWeb 项目的存储库结构如以下屏幕截图所示。 SpaceGameWeb 存储库结构的屏幕截图。
  • FabrikamFiber 项目的存储库结构如以下屏幕截图所示。 FabrikamFiber 存储库结构的屏幕截图。
  • 假设你的项目未设为使用基于项目的生成标识或保护针对 YAML 管道中存储库的访问。 此外,假设你已成功运行管道。

对生成管道使用基于项目的生成标识

在管道执行期间,标识用于访问资源,例如存储库、服务连接和变量组。 管道可以利用两种类型的标识:项目级和集合级别。 前者优先考虑安全性,而后者强调易于使用。 有关详细信息,请参阅 作用域内生成标识作业授权范围

为了增强安全性,请在运行管道时使用项目级标识。 这些标识只能访问其关联项目中的资源,最大限度地减少恶意参与者未经授权访问的风险。

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

在我们的正在运行的示例中,关闭此开关时,SpaceGameWeb 管道可以访问所有项目中的所有存储库。 打开此开关时,SpaceGameWeb 只能访问 fabrikam-tailspin/SpaceGameWeb 项目中的资源,因此只能访问 SpaceGameWebSpaceGameWebReact 存储库。

如果运行示例管道,则打开开关时,管道会失败,错误日志会告知你 remote: TF401019: The Git repository with name or identifier FabrikamChat does not exist or you do not have permissions for the operation you are attempting.remote: TF401019: The Git repository with name or identifier FabrikamFiber does not exist or you do not have permissions for the operation you are attempting.

若要解决结帐问题,请按照本文“基本流程”部分中介绍的步骤进行操作。

此外,在使用这些存储库的存储库之前,显式签出子模块存储库。 在我们的示例中,即为 FabrikamFiberLib 存储库。

如果运行示例管道,它将成功。

进一步配置

若要在访问 Azure Repos 时进一步提高安全性,请考虑启用对 YAML 管道中存储库的访问。

假设 SpaceGameWeb 管道是 YAML 管道,其 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: 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 管道中存储库的访问权限

Azure DevOps 以保护对 YAML 管道环境中的存储库的访问的形式为 Azure Repos 存储库提供精细粒度权限机制。 此设置使 YAML 管道显式请求访问所有 Azure Repos 存储库的权限,无论它们属于哪个项目。 有关详细信息,请参阅 访问存储库。 此设置不会影响签出其他类型的存储库,例如 GitHub 托管的存储库。

在我们的正在运行的示例中,当此设置打开时,SpaceGameWeb管道会请求访问项目中的SpaceGameWebReactfabrikam-tailspin/SpaceGameWeb存储库以及项目中的FabrikamFiber存储库和FabrikamChat存储库fabrikam-tailspin/FabrikamFiber的权限。

运行示例管道时,它将生成类似于以下示例。

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

向管道存储库或资源授予权限。

要求授予 SpaceGameWeb 管道访问三个存储库的权限的屏幕截图。

管道运行,但失败,因为它无法以子模块的形式FabrikamFiber签出FabrikamFiberLib存储库。 若要解决此问题,请在步骤之前-checkout: FabrikamFiber通过添加一个步骤- checkout: git://FabrikamFiber/FabrikamFiberLib显式签出FabrikamFiberLib

示例管道成功。

最终的 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

故障排除

对于出现的任何问题,请使用以下解决方案。

在命令行中使用 git 签出同一组织中的存储库

例如,使用的是 - script: git clone https://$(System.AccessToken)@dev.azure.com/fabrikam-tailspin/FabrikamFiber/_git/OtherRepo/。 打开 YAML 管道设置中的“保护对存储库的访问权限”时,该命令将失败

若要解决此问题,请使用checkout命令(例如- checkout: git://FabrikamFiber/OtherRepo)签出OtherRepo存储库。

存储库使用另一个存储库作为子模块

假设管道签出的其中一个存储库使用另一个存储库(在同一项目中)作为子模块,正在在我们的示例中,FabrikamFiberFabrikamFiberLib 存储库就是这种情况。 详细了解如何检查子模块

此外,假设你向 SpaceGame 生成标识授予了对此存储库的读取访问权限,但在签出 FabrikamFiberLib 子模块时,签出 FabrikamFiber 存储库仍然会失败。

若要解决此问题,请显式查看FabrikamFiberLib,方法是在步骤之前-checkout: FabrikamFiber添加一个步骤- checkout: git://FabrikamFiber/FabrikamFiberLib

经典发布管道

保护对发布管道存储库的访问的过程类似于生成管道的过程。

为了说明需要执行的步骤,我们使用正在运行的示例。 在我们的示例中,fabrikam-tailspin/FabrikamFiberDocRelease 项目中有一个名为 FabrikamFiberDocRelease 的发布管道。 假设管道签出 fabrikam-tailspin/FabrikamFiber 项目中的 FabrikamFiber 存储库,运行命令以生成公共文档,然后将其发布到网站。 此外,假设 FabrikamFiber 存储库使用 FabrikamFiberLib 存储库(在同一项目中)作为子模块。

对经典发布管道使用基于项目的生成标识

管道执行时,它使用标识访问各种资源,例如存储库、服务连接、变量组。 管道可以使用两种类型的标识:一个是项目级别,一个是集合级别。 前者提供更好的安全性。 后者提供易用性。 阅读有关限定作用域的生成标识作业授权作用域的详细信息。

建议使用项目级标识来运行管道。 默认情况下,项目级标识只能访问其所属项目中的资源。 使用此标识可以提高安全性,因为可以减少恶意人员在劫持管道时获得的访问权限。

要让管道使用项目级标识,请打开对于发布管道,将作业授权范围限制为当前项目设置。

在我们的正在运行的示例中,关闭此开关时,FabrikamFiberDocRelease 发布管道可以访问所有项目中的所有存储库,包括 FabrikamFiber 存储库。 打开此开关时,FabrikamFiberDocRelease 只能访问 fabrikam-tailspin/FabrikamFiberDocRelease 项目中的资源,因此 FabrikamFiber 存储库变为无法访问。

如果运行示例管道,则打开开关时,管道会失败,日志会告诉你 remote: TF401019: The Git repository with name or identifier FabrikamFiber does not exist or you do not have permissions for the operation you are attempting.

若要解决这些问题,请按照本文“基本过程”部分中的步骤进行操作

示例管道成功。