VSTS生成管道:连接到Azure Key Vault的测试失败 [英] VSTS Build Pipeline: Test fails connecting to Azure Key Vault

查看:76
本文介绍了VSTS生成管道:连接到Azure Key Vault的测试失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用VSTS(现在称为Azure DevOps)来执行CI/CD管道.对于我的构建管道,我有一个非常基本的设置,涉及执行还原,构建,测试和发布步骤.

I am trying to use VSTS (now Azure DevOps) to do a CI/CD pipeline. For my build pipeline, I have a very basic setup involving doing a restore, build, test, and publish steps.

对于我的测试步骤,我将其设置为运行两个测试项目-一个单元测试项目和一个集成测试项目.我具有密钥保管库"访问策略设置,以提供对本人和Azure Devops的访问.当我使用Visual Studio在本地运行测试时,由于我登录到有权访问Azure密钥保险库的同一帐户,因此我可以运行测试而不会出现任何错误.

For my test step, I have it setup to run two test projects - one unit test project and one integration test project. I have my Key Vault access policy setup to provide access to both myself and Azure Devops. When I run my tests locally using visual studio, as I am logged into the same account which has access to azure key vault, I can run the tests without any errors.

使用以下设置将我的应用程序配置为访问密钥库:

My application is configured to access key vault using below setup:

 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>();

运行构建管道时,我使用的是VS2017托管实例来构建我的项目.除了试图访问密钥库的集成测试失败之外,其他所有程序都在运行.我正在使用以下软件包:

When I run the build pipeline, I am using a Hosted VS2017 instance to build my project. Everything is running except the integration tests which try and access the key vault fail. I am using the following packages:

  • Microsoft.Azure.Services.AppAuthentication -易于获取 访问服务到Azure服务身份验证方案的令牌.
  • Microsoft.Azure.KeyVault -包含与Key Vault进行交互的方法.
  • Microsoft.Extensions.Configuration.AzureKeyVault -包含
    Azure Key Vault的IConfiguration扩展
  • Microsoft.Azure.Services.AppAuthentication - makes it easy to fetch access tokens for Service-to-Azure-Service authentication scenarios.
  • Microsoft.Azure.KeyVault - contains methods for interacting with Key Vault.
  • Microsoft.Extensions.Configuration.AzureKeyVault - contains
    IConfiguration extensions for Azure Key Vault

我遵循了本教程 https://docs.microsoft.com/zh-CN/azure/key-vault/tutorial-web-application-keyvault 来设置密钥库并将其集成到我的应用程序中.

I followed this tutorial https://docs.microsoft.com/en-us/azure/key-vault/tutorial-web-application-keyvault to setup the key vault and integrate it into my app.

我只是想通过确保单元测试和集成测试都通过来使我的构建工作.我尚未将其部署到应用程序服务.单元测试运行时没有任何问题,因为我正在模拟各种服务.我的集成测试失败,并显示以下错误消息.如何获得对密钥库的测试访问权限?我是否需要为托管的VS2017构建向密钥库添加任何特殊的访问策略?不知道该怎么办,因为我看不到任何突出的地方.

I am merely trying to get my build to work by making sure both the unit and integration tests pass. I am not deploying it to an app service yet. The unit tests run without any issues as I am mocking the various services. My integration test is failing with below error messages. How do I get my test access to the key vault? Do I need to add any special access policies to my key vault for the hosted VS2017 build? Not sure what to do as I don't see anything that stands out.

以下是错误的堆栈跟踪:

Below is the stack trace for the error:

    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个与此问题相关的帖子:


Update

I have found only 1 related post to this issue: https://social.msdn.microsoft.com/Forums/en-US/0bac778a-283a-4be1-bc75-605e776adac0/managed-service-identity-issue?forum=windowsazurewebsitespreview. But the post is related to deploying an application into an azure slot. I am merely trying to build my application in a build pipeline.

我仍在尝试解决此问题,并且不确定提供所需访问权限的最佳方法是什么.

I am still trying to solve this issue and am not sure what the best way to provide the required access is.

我仍然没有找到解决方案.我迷失了如何让我的管道顺利运行测试的问题.我看到发布管道也可以选择运行测试.但是这些似乎使用.dll文件,而我的构建管道放置文件仅具有Web应用程序(我看不到任何测试项目发布的放置文件).不知道这是否有可能.

I have still not found a solution for this. I am lost on how to get my pipeline to run my test without issues. I saw that the release pipeline you have the options of running tests too. But these seem to take .dll files and my build pipeline drop file only has the web app (I don't see any of the test projects published drop file). Not sure if that is even a possibility.

通过使用此处提供的最后一个选项,我设法使其正常工作:

I managed to get it to work by using the last option provided here: https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication#connection-string-support

我尝试了使用证书的其他方式,但是只要在连接字符串中提供{CurrentUser},构建管道就会失败.它可以在我的本地计算机上工作,但不能在构建管道中工作.

I tried the other ways of using a certificate but anytime {CurrentUser} is provided in a connection string, the build pipeline fails. It works on my local machine but not in the build pipeline.

要使其正常工作,我必须做三件事:

To get it to work, I had to do three things:

  • 登录到Azure.在Azure AD中设置新的应用程序注册
  • 在新的AD应用程序注册中,创建一个新的客户机密
  • 为您的密钥保管库提供新的AD App访问权限.进入关键保管库访问策略,然后添加您在AD中创建的具有对机密的读取权限的应用程序.

  • Log in to Azure. Setup a new app registration in Azure AD
  • In your new AD app registration, create a new client secret
  • Provide your new AD App access to your key vault. Go into your key vault access policies and add the app that you created in your AD with read access to your secrets.

将我对 Program.cs 文件中的 AzureServiceTokenProvier() 的调用修改为:

Modified my call to AzureServiceTokenProvier() in my Program.cs file as follows:

 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}")

请注意,您的客户机密必须正确设置格式.应用程序注册(预览)会生成一个随机密钥.有时,该键在连接字符串中不起作用(格式错误会引发错误).可以尝试在非预览版的应用程序注册中生成您自己的密钥,也可以生成一个新密钥,然后重试.

Note that your client secret has to be formatted correctly. The app registrations (preview) generates a random secret key. Sometimes this key does not work in the connection string (throws an error as incorrectly formatted). Either try generating your own key in the non-preview version of app registration or generate a new key and try again.

此后,我能够在构建管道中成功运行集成测试,并在Azure中创建到Web应用程序的发行版.我对这种方法不满意,因为尽管它可以工作,但是它在代码本身中暴露了一个秘密值.由于上述方法,不需要打开管理服务身份.在这方面,我感到这非常糟糕.

After that I was able to run my integration test in my build pipeline successfully and create a release to my web app in Azure. I'm not satisfied with this approach because although it works, its exposing a secret value in the code itself. Manages service identity does not need to be turned on due to above approach. I feel that this is extremely bad in that regard.

必须有一个比这更好的方法.一种选择是不在构建管道中运行集成测试.不知道这是否是正确的方法.我仍然希望有人能够提供更好的方法或解释我的方法是否可以使用.

There has to be a better way than this. One option is not to run the integration test in the build pipeline. Not sure if this is the correct approach. I'm still hoping someone will be able to provide a better approach to this or explain if my approach is okay to use.

推荐答案

由于您使用的是Azure DevOps默认托管代理,因此不应在Azure DevOps Pipelines构建中对Azure KeyVault进行身份验证集成测试.

You should not do the integration test of authentication to Azure KeyVault within Azure DevOps Pipelines build, because you are using Azure DevOps default hosted agents.

默认情况下,Azure DevOps管道使用的是基本的默认托管代理,并且这些托管代理无法通过Azure订阅进行访问.这些不足为奇,因为这些托管代理是满足所有常见构建需求的通用代理,包括构建/编译,运行单元测试,获取测试覆盖率,并且所有这些任务都没有其他附加功能,例如具有ActiveDirectory,数据库和其他功能.对其他方的实际身份验证/请求,例如对任何Azure Keyvault的身份验证.因此,默认情况下,这些代理未在您的Azure订阅中注册.

By default, the Azure DevOps Pipelines are using basic default hosted agents, and these hosted agents are not accessible from your Azure subscription. These are not surprising, because these hosted agents are common agents for all common build needs, including build/compile, running unit tests, getting test coverages, and all of these tasks has no other additional features such as having ActiveDirectory, database, and other actual authentication/requests to other party such as authentication to any Azure Keyvault. Therefore these agents by default are not registered in your Azure subscription.

如果要针对这些特殊需求进行成功的集成测试,则必须为Azure DevOps Pipelines构建和发布创建自己的代理.因此,除了创建自己的代理并配置Azure DevOps以使用自己的代理外,没有其他方法可以强制Azure DevOps默认代理运行KeyVault身份验证测试.

If you want to have successful integration tests for these special needs, you have to create your own agents for Azure DevOps Pipelines build and release. Therefore, there is no other way to force Azure DevOps default agent to run your KeyVault authentication tests, other than creating your own agents and configure your Azure DevOps to use your own agents.

要创建自己的代理,请查阅Microsoft的以下文档:

To create your own agents, consult this documentation from Microsoft:

https://docs. microsoft.com/en-us/azure/devops/pipelines/agents/agents?view=vsts#install

更新2018年10月29日:

为更清楚起见,我还回答了您的"Update 3"解决方法.当Microsoft更新Azure DevOps的默认托管代理时,无法保证您的解决方法将正常工作. 因此,我还需要补充一点:进行集成测试而不依赖Azure DevOps Pipeline构建领域之外的另一方(例如连接到数据库服务器或在内部使用外部身份验证(甚至在Azure KeyVault上)),这不是一个好习惯您的CI,尤其是在使用Microsoft的默认托管代理的情况下.

For more clarity, I also reply for your "Update 3" workaround. There is no guarantee that your workaround will work nicely when Microsoft updates the Azure DevOps' default hosted agent. Therefore I also need to add more point: it's not a good practice to have integration test that relies on other party beyond the realm of your Azure DevOps Pipelines build such as connecting to a database server or using external authentications (even on Azure KeyVault) within your CI, especially if you are using Microsoft's default hosted agents.

不仅由于无效的身份验证配置而容易出错,而且不能保证默认托管代理上的进一步更新将确保您的第三方逻辑测试能够正常工作.

Not just it will be error-prone due to invalid authentication configuration, but there's no guarantee that the further updates on the default hosted-agents would guarantee your third-party logic test will work.

这篇关于VSTS生成管道:连接到Azure Key Vault的测试失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆