Buckaroo Banzai
Buckaroo Banzai

Reputation: 153

C# .NET Core 3.1 The SSL connection could not be established

I use an OData service with an C# ASP.NET Core 3.1 service inside a docker container from SAP with a customer self-signed certificate.

In the meantime I have tried a thousand things, but the error persists.

System.InvalidOperationException: An error occurred while processing this request. mdt2oowvsap_1 | ---> System.Data.Services.Client.DataServiceTransportException: The SSL connection could not be established, see inner exception. The remote certificate is invalid according to the validation procedure.

Even the unsafe solutions like using HttpClientHandler.ServerCertificateCustomValidationCallback with direct return true did not change anything.

 public MyService()
 {
        :
        handler = new HttpClientHandler()
        {
            Credentials = new NetworkCredential(Username, Password, Domain),
            PreAuthenticate = true,                
            ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                {
                    logger.LogDebug($"No SSL policy errors!");
                    return true;   //Is valid
                }

                logger.LogDebug($"Get certificate hash: {cert.GetCertHashString()}");
                // From: https://stackoverflow.com/questions/2675133/c-sharp-ignore-certificate-errors
                if (!String.IsNullOrEmpty(certificateHash) && cert.GetCertHashString().Equals(certificateHash))
                {
                    // Get hash string via: openssl s_client -connect <host>:<port> < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin
                    // see: https://stackoverflow.com/questions/5164804/get-certificate-fingerprint-of-https-server-from-command-line
                    logger.LogDebug($"Using certificate hash: {certificateHash}");
                    return true;
                }
                return false;
            },
            UseCookies = true,
            CookieContainer = cookieContainer
        };
        String[] files = Directory.GetFiles("./certs/", "*.*", SearchOption.TopDirectoryOnly);
        logger.LogInformation($"Found {files.Length} certificate files");
        // see: https://stackoverflow.com/questions/40014047/add-client-certificate-to-net-core-httpclient
        foreach (string cfile in files)
        {
            try
            {
                logger.LogDebug($"Try adding {cfile} as trusted client certificate...");
                handler.ClientCertificates.Add(new X509Certificate2(Path.GetFullPath(cfile)));
            }catch(Exception e)
            {
                logger.LogInformation($"Exception while adding certificate file {cfile} to 'ClientCertificates'");
                logger.LogError(e.ToString());
            }
        }
        httpClient = new HttpClient(handler);
        :
 }

The last attempt was to download the certificate and give it to the HttpClientHandler using ClientCertificates.Add. Without success.

Using curl, passing this certificate file works.

 $> curl --location --request GET 'https://customer.de:1234/sap/opu/odata/something/useful_srv' \
 --header 'Authorization: Basic ABCDEFGHIJKLMNOPQRST='
 curl: (60) SSL certificate problem: self signed certificate
 More details here: https://curl.haxx.se/docs/sslcerts.html
 :
 $> echo -n | openssl s_client -connect customer.de:1234 -servername customer.de | \
 openssl x509 > /full/path/to/customer.cert
 depth=0 CN = customer.de
 verify error:num=18:self signed certificate
 verify return:1
 depth=0 CN = customer.de
 verify return:1
 DONE
 $> 
 $> curl --location --cacert '/full/path/to/customer.cert' --request GET \
 'https://customer.de:1234/sap/opu/odata/something/useful_srv' \
 --header 'Authorization: Basic ABCDEFGHIJKLMNOPQRST='
 <?xml version="1.0" encoding="utf-8"?><app:service xml:lang="de" xml:base="https:blablabla.../></app:service>
 $> _

Does anyone have another idea?

Solutions viewed (incomplete):

Thanks in advance.

Upvotes: 5

Views: 37153

Answers (4)

fire_water
fire_water

Reputation: 1449

Thanks for the inspiration, guys. I was battling a similar issue on Ubuntu server running in a Docker container and figured I'd share my solution in case anyone ends up in the same situation.

Docker Container Environment:

  • Ubuntu Server 22.04.3 LTS
  • .NET SDK 8.0.100
  • ASP.NET Core Minimal Web API
  • Blazor Web App (server, not webassembly)

Solution:

This Microsoft article provided the solution, summarized below:

  1. Verify OpenSSL is installed: openssl version -a
  2. If not installed: sudo apt install openssl
  3. Create the developer certificate: dotnet dev-certs https
  4. Export the certificate: sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
  5. Add the certificate to the certificate store: sudo update-ca-certificates
  6. Expected output:

Updating certificates in /etc/ssl/certs... rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL 1 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done.

Verify:

  1. List all available SSL certificates in the default store of the system: ls -lah /etc/ssl/certs
  2. List the certificate we just added: ls -lah /etc/ssl/certs | grep https.crt
  3. Expected output:

https.pem -> /usr/local/share/ca-certificates/aspnet/https.crt

Upvotes: 0

杨贤文
杨贤文

Reputation: 451

question: with minio sdk,I have error: MinIO API responded with message=Connection error: The SSL connection could not be established, see inner exception.. Status code=0, response=The SSL connection could not be established, see inner exception., content=

my Answer: I registed self-signed certificate:

Import-Certificate -FilePath “public.crt” -CertStoreLocation 'Cert:\LocalMachine\Root'

system echo: PSParentPath:Microsoft.PowerShell.Security\Certificate::LocalMachine\Root

Thumbprint Subject


E021FFABABAF32318D31BB18867F3BFAB788FFC0 OU=BETVSYS\andy@andy-tp (andy), O=Certgen Development

so problem resolved. don't change any code. ref link: 1 https://github.com/minio/certgen 2 https://github.com/minio/minio-go/issues/1000#issuecomment-550262204

Upvotes: 1

Cotin
Cotin

Reputation: 21

I would like to add to Buckaroo Banzai's answer that for others running .NET applications in a docker container, the package update-ca-certificates might not even be installed by default.

Get shell access by executing this command:

sudo docker exec -it containerName /bin/bash

And execute this to update package lists, install and run update-ca-certificates:

apt update && \
apt install -y ca-certificates && \ 
update-ca-certificates

Now i can communicate with my(and others) web api again from my .NET application running inside the container.

To make this permanent you should add this snippet to your dockerfile for the image used before the ENTRYPOINT.

RUN \ 
  apt update && \
  apt install -y ca-certificates && \
  update-ca-certificates

Find a great explanation to why this issue occurs and get a better understanding of how Certificate Authority works here:

What is CA certificate, and why do we need it?

Upvotes: 2

Buckaroo Banzai
Buckaroo Banzai

Reputation: 153

The solution to the problem was to make the "self-signed" certificate available to the Docker container or the operating system it contains (Ubuntu) and provide it with

cp certs/customer.cert /usr/local/share/ca-certificates/customer.crt &&
update-ca-certificates

Now the communication works over SSL.

Upvotes: 3

Related Questions