Reputation: 153
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
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:
Solution:
This Microsoft article provided the solution, summarized below:
openssl version -a
sudo apt install openssl
dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
sudo update-ca-certificates
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:
ls -lah /etc/ssl/certs
ls -lah /etc/ssl/certs | grep https.crt
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
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
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