从管道对 Azure Repos 的安全访问

存储库是业务成功的关键资源,因为存储库中包含支持业务的代码。 不应轻易授予对存储库的访问权限。

本文介绍如何提高访问 Azure Repos 的管道的安全性,以免源代码落入别有用心的人手中。

可安全访问 Azure 存储库的管道设置是启用“将作业授权范围限制为非发布管道的当前项目”、“将作业授权范围限制为发布管道的当前项目”和“保护对 YAML 管道中存储库的访问”切换开关其中之一。

我们将介绍生成管道和经典发布管道:

基本流程

这些步骤在所有管道中都差不多:

  1. 确定管道需要访问的 Azure Repos 存储库列表,这些存储库属于同一组织,但位于不同的项目中。

    可以通过检查管道来编译存储库列表。 或者,可以打开对于(非)发布管道,将作业授权范围限制为当前项目开关,并注意管道签出失败的存储库。子模块存储库可能不会显示在第一次失败的运行中。

  2. 对于包含管道需要访问的存储库的每个 Azure DevOps 项目,请按照向管道的生成标识授予对该项目的访问权限中的步骤进行操作。

  3. 对于管道签出的每个 Azure Repos 存储库,请按照授予管道的生成标识对该存储库的读取访问权限中的步骤进行操作。

  4. 对于被管道签出的存储库用作子模块且位于同一个项目中的每个存储库,请遵循授予管道的生成标识对该存储库的读取访问权限

  5. 开启对于非发布管道,将作业授权范围限制为当前项目对于发布管道,将作业授权范围限制为当前项目保护对 YAML 管道中存储库的访问切换开关。

生成管道

为了说明在管道访问 Azure Repos 时提高管道安全性的步骤,我们将使用一个正在运行的示例。

假设你正在 SpaceGameWeb Azure Repos 存储库中处理 fabrikam-tailspin/SpaceGameWeb 项目中托管的 SpaceGameWeb 管道。 此外,假设 SpaceGameWeb 管道签出同一项目中的 SpaceGameWebReact 存储库,以及 fabrikam-tailspin/FabrikamFiber 项目中的 FabrikamFiberFabrikamChat 存储库。

最后,假设 FabrikamFiber 存储库将 FabrikamFiberLib 存储库用作托管在同一项目中的子模块。 详细了解如何检查子模块

SpaceGameWeb 项目的存储库结构如以下屏幕截图所示。

Screenshot of the SpaceGameWeb repository structure.

FabrikamFiber 项目的存储库结构如以下屏幕截图所示。

Screenshot of the FabrikamFiber repository structure.

假设你的项目未设为使用基于项目的生成标识或保护针对 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 管道将请求访问 fabrikam-tailspin/SpaceGameWeb 项目中的 SpaceGameWebReact 存储库以及 fabrikam-tailspin/FabrikamFiber 项目中的 FabrikamFiberFabrikamChat 存储库的权限。

运行示例管道时,会看到类似于以下屏幕截图的生成。 Screenshot of running the SpaceGameWeb pipeline the first time after turning on the Protect access to repositories in YAML pipelines toggle.

对于你的管道已经签出的存储库或者已经定义为资源的存储库,系统将要求你授予对此类存储库的权限。 Screenshot of being asked to grant permission to the SpaceGameWeb pipeline to access three repositories.

执行此操作后,管道将运行,但会失败,因为管道无法作为 FabrikamFiber 的子模块来签出 FabrikamFiberLib 存储库。 要解决此问题,请显式签出 FabrikamFiberLib,,例如,在 -checkout: FabrikamFiber 步骤之前添加一个 - checkout: git://FabrikamFiber/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 命令签出 OtherRepo 存储库,例如 - checkout: git://FabrikamFiber/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.

要解决这些问题,请按照基本流程中的步骤操作。

如果现在运行示例管道,则会成功。

另请参阅