Я пытаюсь использовать VSTS (теперь Azure DevOps) для создания конвейера CI / CD.Для моего конвейера сборки у меня есть очень базовая настройка, включающая выполнение шагов восстановления, сборки, тестирования и публикации.
Для моего шага тестирования у меня настроено выполнение двух тестовых проектов - одного проекта модульного тестирования и одного проекта интеграционного тестирования.У меня есть настройка политики доступа к Key Vault, чтобы обеспечить доступ как к себе, так и к 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 - упрощает выборку токенов доступа для сценариев проверки подлинности между службами.
- 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)
Обновление
Я нашел только 1 связанный пост с этой проблемой: 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 создайте новый секретный ключ клиента
Предоставьте доступ к новому приложению ADк вашему хранилищу ключей.Зайдите в свои политики доступа к хранилищу ключей и добавьте приложение, созданное вами в AD, с доступом для чтения к вашим секретам.
Изменил мой вызов на 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.Я не удовлетворен этим подходом, потому что, хотя он работает, он показывает секретное значение в самом коде.Управлять идентификацией службы не нужно, чтобы включить из-за вышеупомянутого подхода.Я чувствую, что это очень плохо в этом отношении.
Должен быть лучший способ, чем этот.Один из вариантов - не запускать тест интеграции в конвейере сборки.Не уверен, что это правильный подход.Я все еще надеюсь, что кто-то сможет предоставить лучший подход к этому или объяснить, подходит ли мой подход для использования.