Я пытаюсь использовать VSTS (теперь Azure DevOps) для создания конвейера CI/CD. Для моего конвейера сборки у меня есть очень простая настройка, включающая выполнение шагов восстановления, сборки, тестирования и публикации.
Для моего тестового шага у меня есть настройка для запуска двух тестовых проектов - одного модульного тестового проекта и одного интеграционного тестового проекта. У меня есть настройка политики доступа к ключам Key для обеспечения доступа как к себе, так и к Azure Devops. Когда я запускаю свои тесты локально с помощью visual studio, так как я зашел в ту же учетную запись, которая имеет доступ к хранилищу ключей azure, я могу запускать тесты без каких-либо ошибок.
Мое приложение настроено на доступ к ключевому хранилищу, используя следующую настройку:
 public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((ctx, builder) =>
            {
                var keyVaultEndpoint = GetKeyVaultEndpoint();
                if (!string.IsNullOrEmpty(keyVaultEndpoint))
                {
                    var azureServiceTokenProvider = new AzureServiceTokenProvider();
                    var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                    builder.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
                }
            }
        )
            .UseStartup<Startup>();
Когда я запускаю конвейер сборки, я использую экземпляр Hosted VS2017 для создания моего проекта. Все работает, за исключением тестов интеграции, которые пытаются получить доступ к отказу ключей. Я использую следующие пакеты:
- Microsoft.Azure.Services.AppAuthentication - позволяет легко извлекать токены доступа для сценариев аутентификации Service-to-Azure-Service.
- Microsoft.Azure.KeyVault - содержит методы взаимодействия с Key Vault.
-  Microsoft.Extensions.Configuration.AzureKeyVault - содержит 
 Расширения IConfiguration для хранилища ключей Azure
Я выполнил этот учебник https://docs.microsoft.com/en-us/azure/key-vault/tutorial-web-application-keyvault, чтобы настроить хранилище ключей и интегрировать его в мое приложение.
Я просто пытаюсь заставить свою сборку работать, убедившись, что пройдут тестирование модуля и интеграции. Я пока не развертываю его в службе приложений. Модульные тесты запускаются без каких-либо проблем, поскольку я издеваюсь над различными службами. Мой тест интеграции не работает с сообщениями об ошибках ниже. Как получить доступ к тестовому доступу к хранилищу ключей? Нужно ли добавлять какие-либо специальные политики доступа в мое хранилище ключей для размещенной сборки VS2017? Не уверен, что делать, поскольку я не вижу ничего, что выделяется.
Ниже приведена трассировка стека для ошибки:
    2018-10-16T00:37:04.6202055Z Test run for D:\a\1\s\SGIntegrationTests\bin\Release\netcoreapp2.1\SGIntegrationTests.dll(.NETCoreApp,Version=v2.1)
    2018-10-16T00:37:05.3640674Z Microsoft (R) Test Execution Command Line Tool Version 15.8.0
    2018-10-16T00:37:05.3641588Z Copyright (c) Microsoft Corporation.  All rights reserved.
    2018-10-16T00:37:05.3641723Z 
    2018-10-16T00:37:06.8873531Z Starting test execution, please wait...
    2018-10-16T00:37:51.9955035Z [xUnit.net 00:00:40.80]     SGIntegrationTests.HomeControllerShould.IndexContentTypeIsTextHtml [FAIL]
    2018-10-16T00:37:52.0883568Z Failed   SGIntegrationTests.HomeControllerShould.IndexContentTypeIsTextHtml
    2018-10-16T00:37:52.0884088Z Error Message:
    2018-10-16T00:37:52.0884378Z  Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException : Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/63cd8468-5bc3-4c0a-a6f8-1e314d696937. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
    2018-10-16T00:37:52.0884737Z Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/63cd8468-5bc3-4c0a-a6f8-1e314d696937. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"}
    2018-10-16T00:37:52.0884899Z Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/63cd8468-5bc3-4c0a-a6f8-1e314d696937. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at "C:\Users\VssAdministrator\AppData\Local\.IdentityService\AzureServiceAuth\tokenprovider.json"
    2018-10-16T00:37:52.0885142Z Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/63cd8468-5bc3-4c0a-a6f8-1e314d696937. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. Process took too long to return the token.
    2018-10-16T00:37:52.0885221Z 
    2018-10-16T00:37:52.0885284Z Stack Trace:
    2018-10-16T00:37:52.0885349Z    at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsyncImpl(String authority, String resource, String scope)
    2018-10-16T00:37:52.0885428Z    at Microsoft.Azure.KeyVault.KeyVaultCredential.PostAuthenticate(HttpResponseMessage response)
    2018-10-16T00:37:52.0885502Z    at Microsoft.Azure.KeyVault.KeyVaultCredential.ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    2018-10-16T00:37:52.0886831Z    at Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretsWithHttpMessagesAsync(String vaultBaseUrl, Nullable'1 maxresults, Dictionary'2 customHeaders, CancellationToken cancellationToken)
    2018-10-16T00:37:52.0886887Z    at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretsAsync(IKeyVaultClient operations, String vaultBaseUrl, Nullable'1 maxresults, CancellationToken cancellationToken)
    2018-10-16T00:37:52.0886935Z    at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.LoadAsync()
    2018-10-16T00:37:52.0887000Z    at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.Load()
    2018-10-16T00:37:52.0887045Z    at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList'1 providers)
    2018-10-16T00:37:52.0887090Z    at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
    2018-10-16T00:37:52.0887269Z    at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
    2018-10-16T00:37:52.0887324Z    at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
    2018-10-16T00:37:52.0887371Z    at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder, IFeatureCollection featureCollection)
    2018-10-16T00:37:52.0887433Z    at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory'1.CreateServer(IWebHostBuilder builder)
    2018-10-16T00:37:52.0887477Z    at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory'1.EnsureServer()
    2018-10-16T00:37:52.0887525Z    at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory'1.CreateDefaultClient(DelegatingHandler[] handlers)
Обновить
Я нашел только одну связанную запись по этой проблеме: https://social.msdn.microsoft.com/Forums/en-US/0bac778a-283a-4be1-bc75-605e776adac0/managed-service-identity-issue?forum=windowsazurewebsitespreview, Но сообщение связано с развертыванием приложения в лазурном слоте. Я просто пытаюсь создать свое приложение в конвейере сборки.
Я все еще пытаюсь решить эту проблему, и я не уверен, что лучший способ обеспечить необходимый доступ.
Обновление 2
Я до сих пор не нашел для этого решения. Я теряюсь на том, как получить мой конвейер для запуска моего теста без проблем. Я видел, что в конвейере выпуска есть варианты запуска тестов. Но, похоже, они берут файлы.dll, а файл с откатным конвейером сборки имеет только веб-приложение (я не вижу ни одного из опубликованных файлов пробных проектов). Не уверен, что это даже возможность.
Обновление 3
Мне удалось заставить его работать, используя последний предоставленный здесь вариант: https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication#connection-string-support
Я попробовал другие способы использования сертификата, но в любое время {CurrentUser} предоставляется в строке подключения, сбой конвейера сборки. Он работает на моей локальной машине, но не в конвейере сборки.
Чтобы заставить его работать, мне пришлось сделать три вещи:
- Войдите в Azure. Настройка регистрации нового приложения в Azure AD
-  В вашей новой регистрации приложения AD создайте новый клиентский секрет ![enter image description here]() 
-  Предоставьте свой новый доступ к приложениям AD в хранилище ключей. Перейдите в свои политики доступа к хранилищу ключей и добавьте приложение, созданное в вашем AD, с доступом для чтения к вашим секретам. ![enter image description here]() 
-  Изменен мой вызов AzureServiceTokenProvier() в файле Program.cs следующим образом: var azureServiceTokenProvider = new AzureServiceTokenProvider("connectionString={your key vault endpoint};RunAs=App;AppId={your app id that you setup in Azure AD};TenantId={your azure subscription};AppKey={your client secret key}")
Обратите внимание, что секрет вашего клиента должен быть отформатирован правильно. Регистрация приложений (предварительный просмотр) генерирует случайный секретный ключ. Иногда этот ключ не работает в строке соединения (выдает ошибку как неправильно отформатированную). Либо попробуйте создать свой собственный ключ в версии предварительного просмотра без предварительного просмотра, либо сгенерируйте новый ключ и повторите попытку.
После этого я смог успешно запустить мой интеграционный тест в моем конвейере сборки и создать выпуск для моего веб-приложения в Azure. Я не удовлетворен этим подходом, потому что, хотя он работает, он раскрывает секретное значение в самом коде. Управление идентификацией службы не обязательно должно быть включено из-за вышеуказанного подхода. Я чувствую, что это очень плохо в этом отношении.
Должен быть лучший путь, чем это. Один из вариантов - не запускать интеграционный тест в конвейере сборки. Не уверен, что это правильный подход. Я все еще надеюсь, что кто-то сможет обеспечить лучший подход к этому или объяснить, подходит ли мой подход.



