Search code examples
c#ssl.net-corecertificatessl-certificate

.Net Core + Kubernettes > AuthenticationException: The remote certificate is invalid according to the validation procedure


I'm working on several Dotnet Core APIs hosted on a Kubernettes cluster and some of the APIs do call other APIs, and that's when the exception in title is thrown.

It doesn't matter whether I edit the appsettings.json and replace all https by http -in fact people at devops team suggested me to do that- as the same exception is thrown.

This is the little piece of code I use for the http call:

int idCity = Convert.ToInt32(Utils.GetConfig().GetSection("Settings")["idCity"]);

using (HttpClient client = new HttpClient())
{
    client.BaseAddress = new Uri(Utils.GetConfig().GetSection("xxx")["xxxx"]);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    string queryString = "?startDate=" + startDate + "&endDate=" + endDate + "&idCity=" + idCity;

    HttpResponseMessage response = client.GetAsync(queryString).GetAwaiter().GetResult();

    if (response.IsSuccessStatusCode)
    {
        var resultHolidays = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        return JsonConvert.DeserializeObject<JSONGeneric<HolidayDTO>>(resultHolidays);
    }
    else
    {
        return null;
    }
}

I have a copy of the certificate in .crt format and also tried:

string certPath = Path.Combine(_env.ContentRootPath, _configuration.GetSection("Certificate")["certificatePath"]);
string pwd = _configuration.GetSection("Certificate")["certificatePwd"];

HttpClientHandler requestHandler = new HttpClientHandler();
requestHandler.ClientCertificates.Add(new X509Certificate2(certPath, pwd,
    X509KeyStorageFlags.MachineKeySet));

using (HttpClient client = new HttpClient(requestHandler))
{
    ...
}

To no avail, as the same exception is thrown.

I'm not an expert on working with certificates, but I truly need to make this to work, to be able to make on api in a pod call other api, so any help will be much appreciated.

Update 1: The "weird" thing is that if I just copy the url to be requested -no matter if you use http or https- and paste it into a browser with the certificate installed it does work. If you copy and paste the http version of the url n the browser, Kubernettes (or whoever it is) does a redirection to the https version but in the end you get results. Not from .Net


Solution

  • I would start by disabling certificate validation in the client and see what is the behavior. You can do it like this:

    var httpHandler = new HttpClientHandler {
        ServerCertificateCustomValidationCallback = (m, crt, chn, e) => true
    };
    
    using var httpClient = new HttpClient(httpHandler);
    // rest of the code 
    

    If the call succeeds, the next step is to adapt the certificate validation callback to check the server's certificate.

    Note: in your example you're configuring a client certificate, which is useful if you host a service and want to authorize your clients based on their certificates, as described here. From the problem description I understand that what you need is the opposite: validate the server certificate in your client.

    var srvCrt = new X509Certificate2(certPath, pwd);
    
    var httpHandler = new HttpClientHandler {
        ServerCertificateCustomValidationCallback = (m, crt, chn, e) => {
            return crt.Thumbprint == srvCrt.Thumbprint;
        }
    };
    
    using var httpClient = new HttpClient(httpHandler);
    // rest of the code