Reputation: 41
I am having an SSL issue when calling internal https url (like https://sample/demoapi/api/item/) from a containerized .net core 2.2 API. The API works fine when run outside of container.
Note: The container works perfect when mounting the ssl folder from the Docker thin Linux VM to the container. docker run -itd -p 5011:80 -v /etc/ssl/certs:/etc/ssl/certs
Information Windows Version: Win 10 Docker for windows CE Version: Docker CE 2.0.0.3 (not the latest. I have DNS name resolution issue when calling a URL from a container with the latest docker CE. Docker 2.0.0.3 is the one found working without issues) Docker is running on windows 10 machine not on VM. Running Linux host and containers. I have followed the following resolutions to copy and update the ssl certificate onto the container but didn't work. Linux docker: System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure How do I add a CA root certificate inside a docker image?
Steps to reproduce the issue:
Create a sample .net core api and call an https service as follows.
try { var client = new HttpClient(); var resp = await client.GetAsync("https://test.com"); data = await resp.Content.ReadAsStringAsync(); } catch(Exception e) { data = e.StackTrace + "- " + e.Message + " - " + e.InnerException; }
Publish the application as specified above Application type: .net core 2.2 api Publish configuration: Target framework: .netcoreapp2.2 Deployment method: self-contained Target run time: linux-x64
Build image using the docker file FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime COPY Publish/ app/ COPY ./certf.crt /usr/local/share/ca-certificates/certf.crt RUN chmod 644 /usr/local/share/ca-certificates/certf.crt && update-ca-certificates ENTRYPOINT ["dotnet", "app/testapp1.dll"]
Run docker command - docker run -itd -p 5011:80 --name demoapi demoapi
Error received: at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask1.get_Result() at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask1.get_Result() at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask) at System.Threading.Tasks.ValueTask1.get_Result() at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at demoapiapp1.Controllers.ValuesController.Get(Int32 id) in C:\dev\Controllers\ItemsController.cs:line 41 ----- The SSL connection could not be established, see inner exception. <--------------------> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure. at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest) --- End of stack trace from previous location where exception was thrown --- at System.Net.Security.SslState.ThrowIfExceptional() at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result) at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult) at System.Net.Security.SslStream.<>c.b__47_1(IAsyncResult iar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task`1 promise, Boolean requiresSynchronization) --- End of stack trace from previous location where exception was thrown --- at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
Upvotes: 1
Views: 3223
Reputation: 41
Found the problem and resolved it. Posting this to help anyone who experience the same problem.
I used wrong certificate. The certificate to be used is the certificate authority certificate (root certificate) but I used the certificate issued to the system. I generated the root certificate from the chain and imported to container using the 'stakoverlow' resolution referenced above.
Resolution: The ca certificate is named as ca-cert.crt. Added the following lines the Dockerfile.
COPY ca-cert.crt /usr/local/share/ca-certificates/ca-cert.crt
RUN chmod 644 /usr/local/share/ca-certificates/ca-cert.crt && update-ca-certificates
Upvotes: 3