秘密作为vstest中的环境变量
Secrets as environmental variables in vstest
在我的测试中,我使用了环境变量。出于安全原因,在 azure devops 管道中设置它时,我需要将其标记为机密。是否可以在 vstest 任务中将其作为参数传递?
我经历过这个。无法在命令行上将变量传递给 VSTest,这意味着您必须跳过几个环节。
您有几个选择:
使用带有 TestRunParameters
部分的 runsettings 文件,然后在测试本身中通过 TestContext.Properties["variableName"]
访问它。您可以使用标准标记替换模式来转换 XML 文件。
使用 app.config 或 appsettings.json(取决于您的平台)。这与上面的工作方式几乎相同,当然,除了您使用标准配置 类 来检索值。
向您的管道添加一个步骤以设置适当的环境变量。出于安全目的,秘密不会自动映射到环境变量,但没有什么可以阻止您自己做。
将秘密值移动到密钥库或某种其他类型的外部秘密存储中,并配置测试以在运行时提取秘密。
显然缺乏足够的声誉来评论@daniel-mann 的回答,我需要自己跟进一个回答。
关于运行设置文件的使用;
是的,我相信您可以这样做,但还有一种更简单的方法。在任务定义中,您可以选择覆盖测试 运行 参数。
对于非 YAML 管道,您可以在“覆盖测试 运行 参数”选项中执行此操作(工具提示显示“覆盖 [=101= 的 TestRunParameters 部分中定义的参数]settings 文件或 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
上对自己问题的解决方案
在我的测试中,我使用了环境变量。出于安全原因,在 azure devops 管道中设置它时,我需要将其标记为机密。是否可以在 vstest 任务中将其作为参数传递?
我经历过这个。无法在命令行上将变量传递给 VSTest,这意味着您必须跳过几个环节。
您有几个选择:
使用带有
TestRunParameters
部分的 runsettings 文件,然后在测试本身中通过TestContext.Properties["variableName"]
访问它。您可以使用标准标记替换模式来转换 XML 文件。使用 app.config 或 appsettings.json(取决于您的平台)。这与上面的工作方式几乎相同,当然,除了您使用标准配置 类 来检索值。
向您的管道添加一个步骤以设置适当的环境变量。出于安全目的,秘密不会自动映射到环境变量,但没有什么可以阻止您自己做。
将秘密值移动到密钥库或某种其他类型的外部秘密存储中,并配置测试以在运行时提取秘密。
显然缺乏足够的声誉来评论@daniel-mann 的回答,我需要自己跟进一个回答。
关于运行设置文件的使用;
是的,我相信您可以这样做,但还有一种更简单的方法。在任务定义中,您可以选择覆盖测试 运行 参数。
对于非 YAML 管道,您可以在“覆盖测试 运行 参数”选项中执行此操作(工具提示显示“覆盖 [=101= 的 TestRunParameters 部分中定义的参数]settings 文件或 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
上对自己问题的解决方案