I created a gRPC WebService (netcoreapp3.1) that is hosted in a docker container with C#. It runs well locally. I do a docker build with following dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
# USER ContainerAdministrator
WORKDIR /app
EXPOSE 443
WORKDIR /app
COPY publish .
ENTRYPOINT ["dotnet", "MyService.dll"]
On an Ubuntu 20.4 machine I start the container by
docker run --rm -it -p 32555:443 -e ASPNETCORE_URLS="https://+" -e ASPNETCORE_HTTPS_PORT=443 -e ASPNETCORE_Kestrel__Certificates__Default__Password=secretpassword -e ASPNETCORE_Kestrel__Certificates__Default__Path=/https/ourdomain.de.pfx -v /home/user/.aspnet/https:/https/ myservice
That produces the following output
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://[::]:443
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /app
The ourdomain.de.pfx was created by my admin for our domain. If I call the service from a client I get an execption
Error on call 'CreateGaebAsync' with SSL certificate check: Status(StatusCode=Internal, Detail="Error starting gRPC call. HttpRequestException: The SSL connection could not be established, see inner exception. AuthenticationException: The remote certificate is invalid according to the validation procedure.")
To get more infos I added a HttpClientHandler to the GrpcChannel
private GrpcChannel CreateGrpcChannelWithDangerousIgnoreSslCertificate()
{
var httpHandler = new HttpClientHandler();
httpHandler.ServerCertificateCustomValidationCallback = DangerousServerCertificateCustomValidationCallback;
var httpClient = new HttpClient(httpHandler);
return GrpcChannel.ForAddress(serviceUri, new GrpcChannelOptions() { HttpClient = httpClient });
}
private bool DangerousServerCertificateCustomValidationCallback(HttpRequestMessage arg1, X509Certificate2 arg2, X509Chain arg3, SslPolicyErrors arg4)
{
Console.WriteLine(arg1);
Console.WriteLine("X509Certificate2:");
Console.WriteLine(arg2);
Console.WriteLine("X509Chain:");
Console.WriteLine(arg3);
Console.WriteLine("SslPolicyErrors:");
Console.WriteLine(arg4);
// No check of Certificate is done so this will accept any response.
// For production this has to be fixed by acceptiong only valid SSL certificates!!!
return true;
}
The validation callback generates the following output
Method: POST, RequestUri: 'https://computername.ourdomain.de:32555/mysvc.TextService/CreateText',
Version: 2.0, Content: Grpc.Net.Client.Internal.PushUnaryContent`2[MyService.CreateTextRequest,MyService.CraeteTextReply],
Headers:
{
User-Agent: grpc-dotnet/2.29.0.0
TE: trailers
grpc-accept-encoding: identity,gzip
Transfer-Encoding: chunked
Content-Type: application/grpc
}
X509Certificate2:
[Subject]
CN=localhost
[Issuer]
CN=localhost
[Serial Number]
00F059E1CA7B219BF3
[Not Before]
09.06.2020 07:29:50
[Not After]
09.06.2021 07:29:50
[Thumbprint]
E272ACFB1C55B28A6ED08A0AFD2F7D97801447AF
X509Chain:
System.Security.Cryptography.X509Certificates.X509Chain
SslPolicyErrors:
RemoteCertificateNameMismatch, RemoteCertificateChainErrors
I expected to see the certificate infos from ourdomain.de.pfx but what I get seems to imply that the certificate given at ASPNETCORE_Kestrel__Certificates__Default__Path=/https/ourdomain.de.pfx is ignored?! I have nearly no experience with certificates at all... If I start the container with a wrong password or a wrong name for the pfx, I get appropriate error messages. So it seems to me the webservice should use the right one. Because I am not sure if I have to set the port within the container (443) or the mapped port of host machine (32555), I changed
ASPNETCORE_HTTPS_PORT=443
by
ASPNETCORE_HTTPS_PORT=32555
when running the docker container with no success. Could you explain, what I'm missing, please?