Использование секретов хранилища ключей Azure для модульных тестов в Azure Pipelines

У меня есть решение в .NET 5 с некоторыми модульными тестами в NUnit, которые требуют некоторых секретов для правильной работы. Тестирование в Visual Studio с использованием секретов локального пользователя работает нормально, но теперь я хочу попытаться выполнить интеграцию с помощью Azure Key Vault и запустить модульные тесты внутри конвейера.

Я добавил задачу, и, согласно журналу, секреты загружаются нормально, но на следующих шагах модульные тесты терпят неудачу, потому что они не находят некоторые ключи при попытке доступа из 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 @ 1, используя пустой appsettings.jsonно я не мог заставить его работать. Есть ли правильный метод для этого?

2 ответа

Наконец-то я заставил это работать. Решил пойти по маршруту. с задачей преобразования файлов. Я отвечу сам на всякий случай, если кому-то это пригодится.

Вам необходимо иметь в своем проекте модульного теста и добавить все необходимые ключи, которые вам понадобятся в модульных тестах, но без значений, только "", например

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

Если вы хотите протестировать локально, вы можете использовать опцию local user-secrets в Visual Studio и добавить все ключи, как в вашем appsettings.json файл, но с фактическими значениями (вы все равно будете видеть значения)

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

Затем в вашем SetUp метод, вы можете инициализировать IConfigurationкласс следующим образом. (Вы можете легко преобразовать это в статический метод, если у вас есть несколько классов модульных тестов)

      [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]);
   }
}

Наконец, в azure-pipelines.yml вы добавляете задачу после 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

И все, после этого в журнале конвейера вы увидите что-то подобное в FileTransform@1 задача

      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: ***

Используйте приведенную ниже задачу Keyvault в конвейере, чтобы получить секреты в вашем хранилище ключей:

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

Теперь в задаче DotNetCoreCLI@2 добавьте переменные среды для определения секретов хранилища ключей, чтобы вы могли использовать эти переменные среды внутри своего проекта:

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

Внутри вашего проекта вы можете определить секрет keyvault следующим образом:

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

Ссылка: конвейер YAML Azure DevOps: использование секрета Azure KeyVault в качестве переменной среды - сообщество разработчиков

Другие вопросы по тегам