Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling HTTPS using RestSharp within a Azure function gives "The SSL connection could not be established"

How can I call a HTTPS site from within Azure Function using a specific Certificate to establish the HTTPS connection ?

I have a Azure Function that needs to communicate with a remote server with a certificate. The remote server is a bank.

Installing the Certificate and running local the Azure Function Emulator starts and the connection is made.

Uploading to Azure i get this message

The SSL connection could not be established, see inner exception. Authentication failed, see inner exception. 

I tried to include the certificate under the Azure Function SLL I installed all certificates in the Certificate chain as public certificates (.cer) and the private certificate (.pfx)

Trying to reach the certificate with thumbprint fails.

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
    {
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection certificates = store.Certificates;

        foreach (var certificate2 in certificates)
        {
            if (certificate2.Thumbprint.ToLower() == thumbprint.ToLower())
            {
                return certificate2;
            }
        }
     }

In this case I try too loop instead of finding the certificate using the builtin function to find Cert using the Tumbprint

When this did not work I provided the Certificate (.pfx) as file.

Getting the Certificate works.

certificate = new X509Certificate2(filename, password, X509KeyStorageFlags.MachineKeySet);

X509KeyStorageFlags.MachineKeySet is needed at Azure function but not when running local Azure Function Emulator

The RestSharp is working in Azure Function Emulator

var client = new RestClient(BaseUrl)
{
    Timeout = 180000,
    ClientCertificates = new X509CertificateCollection() { cert }

};
client.AddDefaultHeader("Content-type", "application/json");
var request = new RestRequest(Query, Method.POST);
request.Parameters.Clear();
request.AddParameter("application/json", jsonSwish, ParameterType.RequestBody);
IRestResponse response = await client.ExecuteTaskAsync(request);

I get "The SSL connection could not be established..."

I added this before creating the Client but it did not solve the problem

ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

I then created a simple PHP that has HTTP in input and creates the HTTPS output with CURL and the needed certicicate as parameters to CURL. That works but is an ugly solution.

How can I call a HTTPS site from within Azure Function using a specific Certificate to establish the HTTPS connection ?

like image 627
Johnny Nilsson Avatar asked May 24 '26 21:05

Johnny Nilsson


1 Answers

From the description there is code in the web app that makes a HTTPS request to a backend service that is using a certificate that is only trusted in your network. Since the web app server doesn’t have the trusted root certificate, it is failing with a “not trusted” error. If I am misunderstanding the configuration please let me know.

However, the below information is based on that specific assumption.

Unfortunately, it is not possible to import a cert to the trusted root store in Azure Web Apps due to security concerns. The only option to workaround this error would be to handle the validation in app code similar to what is described here: https://stackoverflow.com/a/34204814. We have used these steps successfully in the past, as an example:

  1. Create a new certificate to obtain a PFX file to upload.
  2. Upload the PFX to app service in the SSL Certificates area
  3. Follow steps 1 and 2 from this link to load the certificate: https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/
  4. Add a combination of the code in step 3 from the above link and the code here: Azure Web App calling on-prem service with Self-Signed SSL Cert. Essentially, get the certificate from the cert store, but from within the ServerCertificateValidationCallback function and then return true if the certs match for validation. The code looks something like this:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) =>
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                {
                    return true;
                }
 
                var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                certStore.Open(OpenFlags.ReadOnly);
                var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, "THUMBPRINT", false);
 
                if (certCollection.Count > 0)
                {
                    var validCertificate = certCollection[0];
                    var passedCert = new X509Certificate2(certificate);
                    certStore.Close();
 
                    return validCertificate.Equals(passedCert);
                }
                certStore.Close();
                return false;
            };
 
like image 104
DixitArora-MSFT Avatar answered May 27 '26 09:05

DixitArora-MSFT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!