如何在Azure Pipelines中使用Azure Key Vault密钥运行.NET单元测试
问题原因
你遇到的核心问题是:AzureKeyVault@2任务拉取的密钥默认不会自动传递给后续DotNetCoreCLI@2测试任务的运行环境。
Azure DevOps会将从Key Vault获取的密钥标记为秘密变量,出于安全规则限制,秘密变量不会默认注入到任务的子进程环境变量中,而Host.CreateDefaultBuilder()默认加载的环境变量是当前测试进程的运行环境变量,所以自然读不到对应密钥。
解决方案
下面给两种常用的可落地实现方式:
方案1:手动映射密钥到测试任务环境变量(最简便)
直接在测试任务的env字段中显式声明你需要用到的密钥,将流水线变量映射为测试进程的环境变量,Host.CreateDefaultBuilder()会自动读取这些环境变量作为配置源。
修改后的azure-pipelines.yml测试任务配置示例:
- task: DotNetCoreCLI@2 displayName: 'Run Unit Tests' inputs: command: 'test' projects: '$(unitTestsProject)' arguments: '-c $(buildConfiguration) --collect:"XPlat Code Coverage"' publishTestResults: true env: # 按实际需要的配置键名列出所有密钥,键名和你代码中读取的IConfiguration键名保持一致 secret-key-1: $(secret-key-1) # 若为分层配置(比如Config:Db:Password),用双下划线代替冒号作为环境变量名 Config__Db__Password: $(Config--Db--Password)
注意:如果你的Key Vault中密钥名包含分层结构,建议用--代替冒号命名(Key Vault不支持冒号作为密钥名称),拉取到流水线后对应替换为双下划线即可匹配分层配置。
方案2:通过FileTransform任务写入appsettings.json
如果你偏好使用配置文件的方式,按以下步骤操作:
- 在单元测试项目中新增
appsettings.json文件,设置文件属性为如果较新则复制到输出目录,文件内预留对应密钥的占位:
{ "secret-key-1": "", "Config": { "Db": { "Password": "" } } }
- 在流水线的
AzureKeyVault@2任务之后、Run Unit Tests任务之前,新增FileTransform@1任务,自动用流水线变量替换appsettings.json中的对应键值:
- task: FileTransform@1 displayName: '填充配置文件密钥' inputs: # 替换为你的单元测试项目编译输出路径,注意匹配你的.NET版本 folderPath: '$(System.DefaultWorkingDirectory)/UnitTests/bin/$(buildConfiguration)/net5.0' fileType: 'json' targetFiles: 'appsettings.json'
该任务会自动匹配流水线中所有变量(包括Key Vault拉取的秘密变量),替换json文件中同名键的值,测试运行时Host.CreateDefaultBuilder()会自动读取该配置文件的内容。
本地运行兼容注意事项
Host.CreateDefaultBuilder()默认会读取入口程序集的用户机密,单元测试运行时入口程序集不是你的测试项目,建议手动指定测试项目的程序集加载用户机密,保证本地运行正常:
var host = Host.CreateDefaultBuilder() .ConfigureAppConfiguration((ctx, config) => { // 替换为你测试项目中的任意类来指定程序集 var testAssembly = typeof(UnitTestBase).Assembly; config.AddUserSecrets(testAssembly, optional: true); }) .Build(); _config = host.Services.GetRequiredService<IConfiguration>();
内容的提问来源于stack exchange,提问作者NioZero
相关产品推荐
相关产品推荐

