【问题标题】:Secrets as environmental variables in vstest秘密作为 vstest 中的环境变量
【发布时间】:2020-08-19 00:07:39
【问题描述】:

在我的测试中,我使用了环境变量。由于安全原因,在 azure devops 管道中设置时,我需要将其标记为机密。是否可以在 vstest 任务中将其作为参数传递?

【问题讨论】:

  • 你能说明你在测试中是如何使用这个变量的吗?

标签: azure-devops vstest


【解决方案1】:

我经历过。无法在命令行上将变量传递给 VSTest,这意味着您必须跳过几个环节。

你有几个选择:

  • 使用带有TestRunParameters 部分的运行设置文件,然后在测试本身中通过TestContext.Properties["variableName"] 访问它。您可以使用标准令牌替换模式来转换 XML 文件。

  • 使用 app.config 或 appsettings.json(取决于您的平台)。这与上面的工作方式几乎相同,当然,除了您使用标准配置类来检索值。

  • 在您的管道中添加一个设置适当环境变量的步骤。出于安全目的,机密不会自动映射到环境变量,但没有什么能阻止你自己做。

  • 将秘密值移动到密钥库或某种其他类型的外部秘密存储中,并配置测试以在运行时提取秘密。

【讨论】:

【解决方案2】:

显然缺乏足够的声誉来评论@daniel-mann 的答案,我需要自己跟进答案。

关于运行设置文件的使用;

是的,我相信你可以这样做,但有一个更简单的方法。在任务定义中,您可以选择覆盖测试运行参数。

对于非 YAML 管道,您可以在“覆盖测试运行参数”选项中执行此操作(工具提示显示“覆盖在 runsettings 文件的 TestRunParameters 部分或 testsettings 文件的 Properties 部分中定义的参数。例如: -key1 value1 -key2 value2."),那么像这样:

-SomeSecret $(SomeSecret)

对于 YAML 管道,您可以这样做:

overrideTestrunParameters: '-SomeSecret $(SomeSecret)'

好消息是您想要覆盖的测试运行参数不需要存在于您的运行设置文件中。事实上,根本不需要运行设置文件!

一般而言,这种方法的坏处是您必须通过“TestContext.Properties”集合(对于 NUnit)访问您的秘密,如果您想要一个对本地同样适用的透明解决方案,这真的很糟糕开发(使用“用户机密”)并在 Azure 管道中。

另一个潜在的坏事是这些“被覆盖”的测试运行参数就是 - 仅用于测试运行的参数。如果您碰巧混合了 .NET Framework 和 .NET Core 测试,您可能希望在两个不同的测试运行中执行这些测试(让它完全工作......),然后您需要复制这些覆盖(假设需要一些相同的秘密)。

关于在管道中添加额外任务以设置适当的环境变量;

当然。使用“批处理脚本”任务非常适合这种情况,您只需将基于秘密的变量作为参数传递给脚本,然后在脚本文件中提取它们。

不过,要使其按预期工作,您需要允许任务修改环境。

对于非 YAML 管道,这是通过勾选“修改环境”复选框来完成的。

对于 YAML 管道,您可以这样做:

- task: BatchScript@1
  displayName: 'Export key vault vars as env. vars (for tests)'
  inputs:
    filename: 'ExportKeyVaultEnvironmentVariables.cmd'
    arguments: '$(SomeSecret)'
    modifyEnvironment: true

在“ExportKeyVaultEnvironmentVariables.cmd”脚本中,您只需这样做:

set SomeSecret=%1

注意:如果您的秘密偶然有一些有趣的字符,尤其是尾随的“=”字符,您可能会遇到在脚本中收集参数时得到的不是您发送的在。

您可以通过将参数括在双引号中来避免此问题,如下所示:

arguments: '"$(SomeSecret)"'

然后通过使用“~”参数修饰符删除周围的引号来收集参数,如下所示:

set SomeSecret=%~1

这种方法的一个很好的额外效果是,您闪亮的全新成熟环境变量会在管道的其余部分持续存在。回到我的“坏事”,即必须可能复制测试运行参数覆盖,这里不需要。

关于OP提到的附加选项;

当然,在这种情况下,您不需要“批处理脚本”任务(需要调用脚本文件),而只需要一个“命令行”任务。

但是,请注意可能的问题!是的,这将为您的测试代码创建一个环境变量,如果您通过“Environment.GetEnvironmentVariable”访问它。

就我而言,我正在构建一个“IConfigurationRoot”实例,如下所示:

/// <summary>
/// Gets a configuration instance, based on user secrets (for local test execution) and environment variables (for Azure pipeline execution).
/// </summary>
/// <typeparam name="T">The type of the class that represents the "runtime" (and thus is able to get hold of any configuration).</typeparam>
/// <returns>An <see cref="IConfigurationRoot"/> instance.</returns>
public static IConfigurationRoot GetConfigurationRoot<T>()
    where T : class =>
    new ConfigurationBuilder()
        //// Note: The "AddUserSecrets" method requires the "Microsoft.Extensions.Configuration.UserSecrets" package
        .AddUserSecrets<T>()
        //// Note: The "AddEnvironmentVariables" method requires the "Microsoft.Extensions.Configuration.EnvironmentVariables" package
        .AddEnvironmentVariables()
        .Build();

这是通过添加各种“配置提供程序”来实现的,最终允许您通过“configuration["SomeSecret"]”无缝访问它们。

不过,如果我没记错的话,我发现“SomeSecret”在添加的“EnvironmentVariablesConfigurationProvider”中仍然不可用,尽管我可以完全使用上述方法直接访问它.想想看(但我可能弄错了……)。

可能的替代方法(但仅适用于 YAML 管道?);

似乎对于 YAML 管道,您可以为任务显式设置环境变量,如下所示:

- task: VSTest@2
  env:
    SomeSecret: $(SomeSecret)
[...]

我自己没有对此进行测试,但看到一位同事这样做(我自己,我目前没有 YAML 管道)。至少这个变量可以用“Environment.GetEnvironmentVariable”拾取,但我不知道这是否可以通过“IConfigurationRoot”实例拾取。

我还没有看到在非 YAML 管道中实现相同目标的任何选项。

但同样,这也遭受了同样可能的“必须在多个测试运行中复制环境变量”的问题。

在Azure DevOps guys上查看我对自己问题的解决方案

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 2023-01-22
    • 2018-06-14
    • 2021-10-09
    • 2019-03-09
    • 2021-12-06
    • 2021-10-29
    • 1970-01-01
    相关资源
    最近更新 更多