从管道对 Azure Repos 的安全访问
存储库是业务成功的关键资源,因为存储库中包含支持业务的代码。 不应轻易授予对存储库的访问权限。
本文介绍如何提高访问 Azure Repos 的管道的安全性,以免源代码落入别有用心的人手中。
可安全访问 Azure 存储库的管道设置是启用“将作业授权范围限制为非发布管道的当前项目”、“将作业授权范围限制为发布管道的当前项目”和“保护对 YAML 管道中存储库的访问”切换开关其中之一。
我们将介绍生成管道和经典发布管道:
基本流程
这些步骤在所有管道中都差不多:
确定管道需要访问的 Azure Repos 存储库列表,这些存储库属于同一组织,但位于不同的项目中。
可以通过检查管道来编译存储库列表。 或者,可以打开对于(非)发布管道,将作业授权范围限制为当前项目开关,并注意管道签出失败的存储库。子模块存储库可能不会显示在第一次失败的运行中。
对于包含管道需要访问的存储库的每个 Azure DevOps 项目,请按照向管道的生成标识授予对该项目的访问权限中的步骤进行操作。
对于管道签出的每个 Azure Repos 存储库,请按照授予管道的生成标识对该存储库的读取访问权限中的步骤进行操作。
对于被管道签出的存储库用作子模块且位于同一个项目中的每个存储库,请遵循授予管道的生成标识对该存储库的读取访问权限。
开启对于非发布管道,将作业授权范围限制为当前项目、对于发布管道,将作业授权范围限制为当前项目和保护对 YAML 管道中存储库的访问切换开关。
生成管道
为了说明在管道访问 Azure Repos 时提高管道安全性的步骤,我们将使用一个正在运行的示例。
假设你正在 SpaceGameWeb
Azure Repos 存储库中处理 fabrikam-tailspin/SpaceGameWeb
项目中托管的 SpaceGameWeb
管道。 此外,假设 SpaceGameWeb
管道签出同一项目中的 SpaceGameWebReact
存储库,以及 fabrikam-tailspin/FabrikamFiber
项目中的 FabrikamFiber
和 FabrikamChat
存储库。
最后,假设 FabrikamFiber
存储库将 FabrikamFiberLib
存储库用作托管在同一项目中的子模块。 详细了解如何检查子模块。
SpaceGameWeb
项目的存储库结构如以下屏幕截图所示。
FabrikamFiber
项目的存储库结构如以下屏幕截图所示。
假设你的项目未设为使用基于项目的生成标识或保护针对 YAML 管道中存储库的访问。 此外,假设你已成功运行管道。
将基于项目的生成标识用于生成管道
管道执行时,它使用标识访问各种资源,例如存储库、服务连接、变量组。 管道可以使用两种类型的标识:一个是项目级别,一个是集合级别。 前者的安全性更好,后者的易用性更好。 阅读有关限定作用域的生成标识和作业授权作用域的详细信息。
建议使用项目级标识来运行管道。 默认情况下,项目级标识只能访问其所属项目中的资源。 使用此标识可以提高安全性,因为可以减少恶意人员在劫持管道时获得的访问权限。
要让管道使用项目级标识,请打开对于非发布管道,将作业授权范围限制为当前项目设置。
在我们的正在运行的示例中,关闭此开关时,SpaceGameWeb
管道可以访问所有项目中的所有存储库。 打开此开关时,SpaceGameWeb
只能访问 fabrikam-tailspin/SpaceGameWeb
项目中的资源,因此只能访问 SpaceGameWeb
和 SpaceGameWebReact
存储库。
如果运行示例管道,在打开此开关时,管道将失败,错误日志将记录: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
项目中的 FabrikamFiber
和 FabrikamChat
存储库的权限。
运行示例管道时,会看到类似于以下屏幕截图的生成。
对于你的管道已经签出的存储库或者已经定义为资源的存储库,系统将要求你授予对此类存储库的权限。
执行此操作后,管道将运行,但会失败,因为管道无法作为 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
。
存储库使用另一个存储库作为子模块
假设管道签出的其中一个存储库使用另一个存储库(在同一项目中)作为子模块,正在在我们的示例中,FabrikamFiber
和 FabrikamFiberLib
存储库就是这种情况。 详细了解如何检查子模块。
此外,假设你向 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.
要解决这些问题,请按照基本流程中的步骤操作。
如果现在运行示例管道,则会成功。