1

我在 .NET 5 中有一个解决方案,在 NUnit 中有一些单元测试需要一些秘密才能正常工作。使用本地用户机密在 Visual Studio 中进行测试工作正常,但现在我想尝试使用 Azure Key Vault 进行集成并在管道内运行单元测试。

我添加了任务AzureKeyVault@2,根据日志,秘密下载得很好,但在接下来的步骤中,单元测试失败,因为它在尝试从IConfiguration.

这是我的azure-pipelines.yml(仅相关部分)。

- job: Init
  displayName: Unit Testing
  variables:
    solutionToBuild: 'Solution.sln'
    unitTestsProject: 'UnitTests\UnitTests.csproj'
    buildConfiguration: 'Release'
  steps:
  - task: DotNetCoreCLI@2
    displayName: 'Restore Packages'
    inputs:
      command: 'restore'
      projects: '$(solutionToBuild)'
      verbosityRestore: minimal
      feedsToUse: 'select'

  - task: DotNetCoreCLI@2
    displayName: 'Build Solution'
    inputs:
      command: 'build'
      projects: '$(solutionToBuild)'
      arguments: '-c $(buildConfiguration)'

  - task: AzureKeyVault@2
    displayName: 'Configure Key Vault'
    inputs:
      azureSubscription: '**-etc-**'
      KeyVaultName: '**key-vault-name**'

  - task: DotNetCoreCLI@2
    displayName: 'Run Unit Tests'
    inputs:
      command: 'test'
      projects: '$(unitTestsProject)'
      arguments: '-c $(buildConfiguration) --collect:"XPlat Code Coverage"'
      publishTestResults: true

我创建了这个当前在管道中失败的基本测试。我正在使用该Host.CreateDefaultBuilder()方法来初始化所有单元测试。

[Test]
[TestCase("secret-key-1")]
[TestCase("secret-key-1")]
public void TestSecrets(string key)
{
    Assert.NotNull(_config[key]);
    Assert.IsNotEmpty(_config[key]);
}

AzureKeyVault@2传递任务的密钥和值DotNetCoreCLI@2还是我需要额外的步骤?我读到您可以使用空的FileTransform@1appsettings.json步骤进行操作,但我无法使其工作。有没有正确的方法来实现这一目标?

4

2 回答 2

0

在管道中使用以下 Keyvault 任务来获取您的 keyvault 中的机密:

- task: AzureKeyVault@2
    displayName: 'Configure Key Vault'
    inputs:
      azureSubscription: '**-etc-**'
      KeyVaultName: '**key-vault-name**'
      SecretsFilter: '*'
      RunAsPreJob: false

现在,在 DotNetCoreCLI@2 任务中,添加环境变量以定义 keyvault 机密,以便您可以在项目中使用这些环境变量:

- task: DotNetCoreCLI@2 
  displayName: ''
  env:
    MySecret: $(key-vault-secret-name)
  inputs:
    command: ''
    projects: 'project-name'

在您的项目中,您可以按如下方式定义 keyvault 机密:

var mySecret = Environment.GetEnvironmentVariable("MySecret");

参考:Azure DevOps YAML 管道:使用 Azure KeyVault 机密作为环境变量 - DEV Community

于 2021-10-26T08:03:15.740 回答
0

I finally made it work. I decided to go to the route of the appsettings.json. with File Transformation Task. I will answer myself just in case anyone else find this useful.

You need to have a appsettings.json in your Unit Test project, and add all the required keys you'll need in your Unit Tests, but without values, only "", e.g.

{
  "secret-key-1": "",
  "secret-key-2": "",
  "secret-key-3": "",
}

If you want to test locally you can use the local user-secrets option in Visual Studio and add all the keys like in your appsettings.json file but with actual values (you'll be the only one to view the values anyways)

Manage user secrets

{
  "secret-key-1": "some-secret-value",
  "secret-key-2": "some-secret-value",
  "secret-key-3": "some-secret-value",
}

Then, in your SetUp method you can initialize the IConfiguration class as follow. (You can easily transform this into a static method if you have multiple Unit Tests classes)

[TestFixture]
public class MyUnitTest

   private IConfiguration Config;

   [SetUp]
   public void Setup()
   {
       Config = new ConfigurationBuilder()
                .SetBasePath(AppContext.BaseDirectory)
                .AddJsonFile("appsettings.json", optional: true)
                .AddUserSecrets(Assembly.GetExecutingAssembly())
                .Build();
   }

   [Test]
   [TestCase("secret-key-1")
   [TestCase("secret-key-2")
   public void TestKeys(string key)
   {
      Assert.NotNull(config[key]);
      Assert.IsNotEmpty(config[key]);
   }
}

Finally, in the azure-pipelines.yml you add the FileTransform@1 Task after the AzureKeyVault@2.

  - task: AzureKeyVault@2
    displayName: 'Configure Key Vault'
    inputs:
      azureSubscription: '**-etc-**'
      KeyVaultName: '**key-vault-name**'

  - task: FileTransform@1
    displayName: 'Set Unit Tests Settings'
    inputs:
      folderPath: '$(projectsDirectory)'
      fileType: 'json'
      targetFiles: '**/appsettings.json'

  - task: DotNetCoreCLI@2
    displayName: 'Run Unit Tests'
    inputs:
      command: 'test'
      projects: '$(unitTestsProject)'
      arguments: '-c $(buildConfiguration) --collect:"XPlat Code Coverage"'
      publishTestResults: true

And that's it, after that in the pipeline log you'll see something like this in the FileTransform@1 task

Applying JSON variable substitution for **/appsettings.json
Applying JSON variable substitution for D:\a\1\s\UnitTests\appsettings.json
Substituting value on key secret-key-1 with (string) value: ***
Substituting value on key secret-key-2 with (string) value: ***
Substituting value on key secret-key-3 with (string) value: ***
于 2021-10-26T23:48:35.957 回答