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

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

问题描述

我正在尝试使用 将 keycloak 作为测试容器添加到我的 .net 核心 (5) 集成测试中dotnet-testcontainers 库.

I am trying to add keycloak as a testcontainer to my .net core (5) integration tests using the dotnet-testcontainers library .

我的问题是,我正在为使用自签名证书和 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.

问题是:我无法向 TestServers HttpClient(通过 serverCreateClient() 创建)添加 HttpClientHandler 以允许在此处理程序中使用不受信任的证书.我在分支 apitests-https 上创建了一个具体示例 here.失败的测试可以在这里找到,它在 SucceedsWhenGetRequestWithTokenReturnsListOfArticles 测试方法中.我在类和 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 Middleware 使用默认的 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|安全协议类型.Tls11|SecurityProtocolType.Tls12;ServicePointManager.ServerCertificateValidationCallback +=(发件人,证书,链,sslPolicyErrors)=>真的;

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

在 Api 测试中创建 TestServer-Instance 时通过 UseEnvironment("Testing") 使用它.调试显示代码被调用,但还是出现异常.

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.csDemoApiTests/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 实例中使用,但不能将它应用于 BaseFixture.GetTestToken()/KeycloakTest.cscode>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
                    };
                }
            });

我不得不承认,这感觉很糟糕,充其量我希望不需要接触任何与应用程序相关的代码来使这个测试工作.最好的解决方案是从我的 keycloak testcontainer 获取证书并将其自动添加到 TestServers 应用程序实例的受信任证书中.如果有人可以就如何处理这个问题给出另一个答案/提示,我会很高兴看到它.但就目前而言,这是最有效的方法.

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 core TestHost/TestServer 调用第三方容器:使用 Testservers CreateClient() 方法绕过 SSL 验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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