通过SSL与.net核心TestHost/TestServer调用第三方容器:使用Testservers CreateClient()方法绕过SSL验证 [英] Calling thirdparty container with .net core TestHost/TestServer via SSL: Bypass SSL Validation using Testservers CreateClient() method

查看:115
本文介绍了通过SSL与.net核心TestHost/TestServer调用第三方容器:使用Testservers CreateClient()方法绕过SSL验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用dotnet-testcontainers 库.

我的问题是,我在使用具有自签名证书和 TestServer -用于集成测试的类.

My Problem is, I am struggling with HTTPS-Support having a container using self-signed certificates and TestServer-Class for my integration tests.

确切地说,我正在使用Microsoft的TestServer类创建带有内存配置的真实API请求,以使用具有暴露端口8443及其自签名证书的keycloak-testcontainer.

To be precise, I am using Microsofts TestServer class to create real API requests with an in-memory config for using a keycloak-testcontainer with exposed port 8443 and its self-signed certificate.

问题是:我无法将 HttpClientHandler 添加到TestServers HttpClient(通过 serverCreateClient()创建),以允许此处理程序中的不受信任证书.我在分支apitests-https上的此处中创建了一个具体示例.可以在此处找到失败的测试它在 SucceedsWhenGetRequestWithTokenReturnsListOfArticles test方法中.我在类和DemoApi的Startup.cs-项目中添加了一些注释,以显示我的尝试.

The Problem is: I can’t add a HttpClientHandler to TestServers HttpClient(created via serverCreateClient()) to allow non-trusted certs within this handler. I have created a concrete example here on branch apitests-https. The failing test can be found here, its in the SucceedsWhenGetRequestWithTokenReturnsListOfArticlestest method. I added some Comments to the class and the Startup.cs of DemoApi - Project that shows what i've tried.

结果,TestServers内部Jwt中间件使用默认的HttpClient并抛出以下AuthenticationException:

As a result, the TestServers internal Jwt Middleware uses the default HttpClient and throws the following AuthenticationException:

 ---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'System.String'.
 ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch, RemoteCertificateChainErrors
   at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---

我已经尝试了多种方法来使其工作,这些在代码中已注释.

I already tried multiple things to make it work which are commented in the code.

  • DemoApi/Startup.cs :试图添加我自己的测试"具有以下代码的环境:

  • DemoApi/Startup.cs: Tried to add my own "Testing" Environment with following Code:

ServicePointManager.Expect100Continue = true;ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls|SecurityProtocolType.Tls11|SecurityProtocolType.Tls12;ServicePointManager.ServerCertificateValidationCallback + =(发件人,证书,链,sslPolicyErrors)=>真的;

ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

使用它.调试显示代码已被调用,但仍然会发生异常.

using it via UseEnvironment("Testing") when creating the TestServer-Instance in the Api Test. Debugging shows the code is called, but still the exception occurs.

  • DemoApiTestsApi/BaseFixture.cs DemoApiTests/Infrastructure/Persistence/KeycloakTest.cs :请参见此处,了解我自己的带有处理程序的HttpClient的有效实现,以获取令牌常规(在分支中有效)- GetTestToken 是BaseFixture中的方法.
  • DemoApiTestsApi/BaseFixture.cs or DemoApiTests/Infrastructure/Persistence/KeycloakTest.cs: See here for a working Implementation of my own HttpClient with handler to obtain the token in general (this works in the branch) - GetTestToken is the method in BaseFixture.

因此,说实话,我对如何使它与TestServer或其他方式无关的想法不多.本质上,我需要在 BaseFixture.GetTestToken()/ KeycloakTest.cs 中使用的处理程序也可以在我的TestServer实例中使用,但不能在 CreateClient()不接受参数.我们非常感谢您提供的任何帮助,它可能是解决方案或其他解决方案的暗示.当有另一种解决方法时,TestServer不一定是固定的.

So, honestly I am a bit out of ideas on how to make this work with TestServer or otherwise. Essentially, I need the handler I use in BaseFixture.GetTestToken()/KeycloakTest.cs to be also used within my TestServer instance, but can't apply it in the CreateClient() which does not accept parameters. Any help is highly appreciated, may it be a solution or a hint to another way to solve this. TestServer is not necessarily fixed when there's another way to work this out.

推荐答案

好的,我已经解决了.恕我直言,这不是最好的解决方案,但是只要我没有其他解决方案,它就可以工作.我要做的就是:

Ok, I worked it out. Imho it is not the best solution, but as long as I don't have another one, this should work. All I had to do was:

  1. IWebHostEnvironment 作为字段添加到Startup.cs,并在 Startup()构造函数中注入.
  1. Add IWebHostEnvironment as a field to Startup.cs and inject in in Startup() constructor.

启动,然后看起来像这样:

Startup then looks like this:

        private IWebHostEnvironment CurrentEnv { get; }

        public Startup(IWebHostEnvironment env, IConfiguration configuration)
        {
            Configuration = configuration;
            CurrentEnv = env;
        }

从这里开始,其余的工作非常简单.现在,在我的 ConfigureServices()方法中,我可以通过 CurrentEnv.IsEnvironment("Testing")进行检查,如果我正在进行集成测试,则可以绕过ssl通过手动设置jwt BackChannelHandler进行验证.

From here on, the rest was pretty easy. In my ConfigureServices() method, I can now check via CurrentEnv.IsEnvironment("Testing") if I am in an integration test, and for these I could bypass ssl validation by setting the jwt BackChannelHandler manually.

代码:

services.ConfigureJwtAuthentication(options =>
            {
                options.Audience = Configuration["Jwt:Audience"];
                options.Authority = Configuration["Jwt:Issuer"];
                options.TokenValidationParameters.ValidIssuer = options.Authority;

                if (CurrentEnv.IsEnvironment("Testing"))
                {
                    options.BackchannelHttpHandler = new HttpClientHandler()
                    {
                        ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
                    };
                }
            });

我必须承认,这感觉很hacky,至多我不希望触摸任何与应用程序相关的代码来完成此测试.最好的解决方案是从我的密钥库testcontainer中获取证书,并将其自动添加到TestServers Application实例的受信任证书中.如果有人能给出另一个答案/关于如何与之相处的提示,我将很高兴看到它.但是现在这才是最有效的.

I have to admit, this feels hacky and at best I would love to not need to touch any application related code to make this test work. Best solution would be to get the certificate from my keycloak testcontainer and add it automatically to the trusted certs of the TestServers Application instance. If anyone could give another answer / a hint on how to get along with this, I'd be happy to see it. But for now this is what works best.

这篇关于通过SSL与.net核心TestHost/TestServer调用第三方容器:使用Testservers CreateClient()方法绕过SSL验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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