如何在管道中安全地使用变量和参数

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

本文讨论如何安全地使用变量和参数从管道用户收集输入。 若要详细了解如何使用变量和参数,请参阅:

请谨慎使用密码变量。 设置机密变量的建议方法包括 UI、变量组和 Azure 密钥保管库中的变量组。 有关详细信息,请参阅设置密码变量

变量

使用变量,可以很方便地预先从用户那里收集信息。 还可以使用变量将数据从步骤传递到管道中的单步。

但请谨慎使用变量。 默认情况下,新创建的变量(无论是在 YAML 中定义还是由脚本编写)都是可读写的。 下游步骤可以采用你不期望的方式更改变量的值。

例如,脚本显示:

msbuild.exe myproj.proj -property:Configuration=$(MyConfig)

前面的步骤可将 MyConfig 设置为 Debug & deltree /y c:。 尽管此示例只会删除生成代理的内容,但你可以想象此设置很容易让危险加剧。

可以将变量设置为只读。 系统变量(如 Build.SourcesDirectory、任务输出变量和队列时间变量)始终是只读的。 在 YAML 中创建或在运行时由脚本创建的变量可以指定为只读。 当脚本或任务创建新变量时,它可以在其日志记录命令中传递 isReadonly=true 标志,从而将变量设为只读。

在 YAML 中,可以使用特定键指定只读变量:

variables:
- name: myReadOnlyVar
  value: myValue
  readonly: true

队列时间变量

在管道 UI 编辑器中定义变量时,可以选择让用户在运行管道时重写其值。 我们将此类变量称为队列时间变量。 始终在 Pipelines UI 编辑器中定义队列时间变量。

定义队列时间变量的屏幕截图。

当最终用户手动运行管道时,队列时间变量会向它们公开,他们可以更改其值。 更新队列时变量值的屏幕截图。

用户需要对管道具有编辑队列生成配置权限,才能指定在队列时间设置的变量。

限制可在排队时设置的变量

用于运行管道的 UI 和 REST API 为用户提供了在队列时定义新变量的方法。

在运行管道之前添加队列时间变量的屏幕截图。

在 Azure Pipelines 的早期,此功能存在一些问题:

  • 此 API 允许用户定义新变量,也就是管道作者未在定义中明确定义变量。
  • 此 API 允许用户重写系统变量。

为了更正这些问题,我们定义了一个设置来限制可在排队时设置的变量。 启用此设置后,只能设置显式标记为“排队时可设置”的变量。 换句话说,除非启用此设置,否则可以在排队时设置任何变量。

此设置设计为在组织级别和项目级别工作。

  1. 组织级别。 当设置处于打开状态时,它会强制组织中所有项目内的所有管道,只能设置那些显式标记为“在排队时可设置”的变量。 当设置关闭时,每个项目都可以选择是否限制在排队时设置的变量。 该设置是“组织设置”->“管道”->“设置”下的切换开关。 只有项目集合管理员可以启用或禁用它。 限制可在排队时在组织级别设置的变量的屏幕截图。
  2. 项目级别。 当设置处于打开状态时,它会强制项目中的所有管道,只能设置那些显式标记为“在排队时可设置”的变量。 如果设置在组织级别处于打开状态,则它对于所有项目都处于打开状态,并且无法关闭。 该设置是“项目设置”->“管道”->“设置”下的切换开关。 只有项目管理员才能启用或禁用它。 可在项目级别的队列时间设置的限制变量的屏幕截图。

我们来看一个示例。 假设已打开此设置,并且管道定义了一个名为 my_variable 的变量,该变量在队列时不可设置。 在经典管道中定义变量的屏幕截图。

接下来,假设要运行管道。 “变量”面板不显示任何变量,并且缺少“添加变量”按钮。

变量面板的屏幕截图,其中的设置已开启。

使用“生成 - 队列”和“运行 - 运行管道”REST API 调用来对管道运行进行排队,并设置 my_variable 或新变量的值将失败,并显示如下错误。

{
  "$id": "1",
  "innerException": null,
  "message": "You can't set the following variables (my_variable). If you want to be able to set these variables, then edit the pipeline and select Settable at queue time on the variables tab of the pipeline editor.",
  "typeName": "Microsoft.Azure.Pipelines.WebApi.PipelineValidationException, Microsoft.Azure.Pipelines.WebApi",
  "typeKey": "PipelineValidationException",
  "errorCode": 0,
  "eventId": 3000
}

参数

与变量不同,管道在运行时无法更改管道参数。 参数具有 numberstring 等数据类型,可以限制为值的子集。 当用户可配置的管道部分仅应从受约束列表中获取值时,限制参数十分有用。 设置可确保管道不会获取任意数据。

启用 shell 任务实参验证

管道可以引用在管道中执行的任务。 Azure DevOps 中包含的多个任务都有实参,可让你为任务指定更多选项。

启用“启用 shell 任务实参验证”设置时,将检查实参,了解 shell 可能无法正确执行的任意字符。 示例字符包括分号、引号和括号。

与“限制可在排队时设置的变量”选项类似,“启用 shell 任务实参验证”可以在组织级别的“设置”>“管道”>“设置”或在项目级别的“设置”>“管道”>“设置”中进行配置。

启用后,将检测到验证问题,并记录如下所示的错误消息: Detected characters in arguments that may not be executed correctly by the shell. Please escape special characters using backtick (`).

要解决该问题,请通过转义错误消息中指示的特殊字符来调整参数。

启用“启用 shell 任务实参验证”后,验证将应用于以下任务中的实参。

  • PowerShell
  • BatchScript
  • Bash
  • Ssh
  • AzureFileCopy
  • WindowsMachineFileCopy

后续步骤

保护输入后,还需要保护共享基础结构