'Remote certificate is invalid because of errors in the certificate chain: PartialChain in Ocelot

I have deployed multiple services to a single Linux VM sitting behind Ocelot. However, when making requests against Ocelot I get a 502 back. Looking at the results from Edge or Brave, it seems that the site doesn't have a certificate. However, when I run the same request from Postman I get this:

enter image description here

It appears that the certificate has expired, but in the future? Looking at the Ocelot logs I see this:

Apr 25 12:52:03 alpha-services apigateway-log[25055]:       requestId: 0HMH6N9IJL29D:00000002, previousRequestId: no previous request id, message: No authentication needed for /auth/users/[email protected]
Apr 25 12:52:03 alpha-services apigateway-log[25055]: info: Ocelot.Authorization.Middleware.AuthorizationMiddleware[0]
Apr 25 12:52:03 alpha-services apigateway-log[25055]:       requestId: 0HMH6N9IJL29D:00000002, previousRequestId: no previous request id, message: /users/{everything} route does not require user to be authorized
Apr 25 12:52:03 alpha-services apigateway-log[25055]: warn: Ocelot.Responder.Middleware.ResponderMiddleware[0]
Apr 25 12:52:03 alpha-services apigateway-log[25055]:       requestId: 0HMH6N9IJL29D:00000002, previousRequestId: no previous request id, message: Error Code: ConnectionToDownstreamServiceError Message: Error connecting to downstream service, exception: System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
Apr 25 12:52:03 alpha-services apigateway-log[25055]:        ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: PartialChain

Looking at the logs, this question and this GitHub post, it seems like the issue comes from this piece of code in Startup.cs on my API gateway project:

string authenticationProviderKey = "IdentityApiKey";
services.AddAuthentication()
    .AddJwtBearer(authenticationProviderKey, x => {
        x.Authority = "https://localhost:5001";
        x.TokenValidationParameters = new TokenValidationParameters {
            ValidateAudience = false
        };
    });

Judging from this, it appears that the certificate I have on the server is good enough to allow requests to Ocelot but that the request, when forwarded to my Authenication service on the same machine, cannot be validated for some reason. I find this odd as the Authenciation service does have a certificate that it pulls in from the Azure Key Vault:

public void ConfigureServices(IServiceCollection services) {
    X509Certificate2 certData = DownloadCertificate(Configuration.GetSection("APICertificate").Get<Secret>());
    builder.AddSigningCredential(certData);
}

private static X509Certificate2 DownloadCertificate(Secret secret) {

    // First, retrieve the secret value from the key vault
    KeyVaultSecret secretValue = new Provider(secret.KeyVaultName).GetSecretAsync(secret.SecretName).Result;

    // Next, create a new PKCS12 store and load the secret value data into it
    var store = new Pkcs12Store();
    using (Stream stream = secret.KeyVaultName.Equals("local")
        ? new FileStream(Environment.GetEnvironmentVariable(secret.SecretName), FileMode.Open)
        : new MemoryStream(Convert.FromBase64String(secretValue.Value))) {
        store.Load(stream, Array.Empty<char>());
    }

    // Get an alias to the secret and get the key associated with it
    string keyAlias = store.Aliases.Cast<string>().SingleOrDefault(a => store.IsKeyEntry(a));
    var key = (RsaPrivateCrtKeyParameters)store.GetKey(keyAlias).Key;

    // Now, create a new X509 certificate by getting the certificate from the store
    var certificate = new X509Certificate2(
        DotNetUtilities.ToX509Certificate(store.GetCertificate(keyAlias).Certificate));

    // Create the RSA parameters from the key
    var rsa = new RSACryptoServiceProvider();
    rsa.ImportParameters(DotNetUtilities.ToRSAParameters(key));

    // Finally, copy the certificate with the private key from the certificate and RSA
    // parameters and return it
    return RSACertificateExtensions.CopyWithPrivateKey(certificate, rsa);
}

What is the problem here and how do I address this?

Update:

I removed the API gateway in favor of Nginx direct calls to the services but I'm still experiencing the issue. However, now it appears to be happening when a service receives a request with a bearer token that it then tries to authenticate with my authentication service, which relies on Identity Server 4. It's probably a missing certificate or something similar but I'm not sure how to debug the problem or fix it.

Update 2:

I SSH-ed into the machine running these services and attempted to curl them directly by doing curl https://localhost:5001 for the authentication service and curl https://localhost:5006 for the upstream service. However, both returned this:

curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above.

Update 3:

I downloaded and installed my CA-signed certificate but the issue persists. I think it might have something to do with the fact that the authority for authentication is https://localhost:5001 rather than a web address.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source