Facing issue in Ingress integration with Apigee X

Hi All,

We are trying to reach backend service from Apigee X using ingress ILB in GKE.

PFB the Steps which we have implemented from Apigee X end-

  1. Created trust Store-> upload server certificate chain.cer.

Admin->Environments->TLS Keystores->Create Trust store->Alias Name->upload certificate

2. Created reference for Trust Store -

Admin->Environments->References->create name and attached references of trust store.

3. A target can be represented by an XML object like the one below(using One-way TLS certification)-

<HTTPTargetConnection>
    <Properties/>
    <URL>https:myTargetAddress</URL>
    <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>false</ClientAuthEnabled>

        <TrustStore>ref://myTruststoreRef</TrustStore>
        <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>
</HTTPTargetConnection>

4. Validating api proxy from postman and getting error-

{

    "fault": {

        "faultstring": "SSL Handshake failed sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",

        "detail": {

            "errorcode": "messaging.adaptors.http.flow.SslHandshakeFailed"

        }

    }

}

 

We followed Apigee document- https://cloud.google.com/apigee/docs/api-platform/system-administration/options-configuring-tls

We have also tried with LGRootCertificate_chain but result is same.

0 4 1,126
4 REPLIES 4

thanks for the clear question and helpful context.

The error like "SSL Handshake failed sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"

...

Indicates that Apigee, in the course of the TLS/SSL handshake, cannot verify that the certificate chain presented by the target, is trusted.

TLS is s standard.  TLS in Apigee works as it does in any other TLS-enabled system.  In a TLS handshake (details here), the requesting peer (in this case Apigee) initiates a connection to the remote peer. The remote peer sends a list, a chain really, of X.509 certificates. The topmost certificate identifies itself, the target server. If the target url is https://abc.example.com , then this topmost certificate must include that as the common name (there are some variations here). That certificate must be digitally signed. The signature can be verified by another certificate. The server must send THAT certificate too. Extending the idea, we can have a chain of many certificates, each one can be used to verify the signature on the one above it. The last cert in the chain is known as the "root" certificate and it is self-signed.

The TrustStore on the Apigee (client) side must contain that root certificate. Apigee then uses the root cert to verify the sig on the next cert. If that signature verifies, then it uses THAT cert to verify the next one in the chain. And so on, until it reaches the topmost certificate.

If all of this works, then Apigee has followed the chain of trust, or "certification path". If Apigee cannot follow that chain then you will see the error you observed on the Apigee side.

That can happen for one of two reasons:

  1. the target did not send the correct chain of certificates! This can happen if the target is mis-configured. Specifically if its keystore does not contain the chain of certs.
  2. Apigee does not have a root certificate in its truststore that can be used to verify the bottom most cert in the chain that the target sent.

There are numerous other things that must "go right" in order for the TLS handshake to succeed. Expiries and name mismatches and bad ciphers etc. But, the error you reported indicates that it's a matter of configuration of the certificates on one side or the other.

So check both of those things. 

First, check the chain of certificates that the target sends, using the openssl tool. For example, if I want to see the certs for www.steakumm.com, I can use this set of commands:

 

$ HOST=www.steakumm.com
$ PORT=443
$ openssl s_client -connect ${HOST}:${PORT} -servername ${HOST}
CONNECTED(00000005)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = www.steakumm.com
verify return:1
---
Certificate chain
 0 s:/CN=www.steakumm.com
   i:/C=US/O=Let's Encrypt/CN=R3
 1 s:/C=US/O=Let's Encrypt/CN=R3
   i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
 2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---

 

You can see

  • the zeroth cert has a subject with CN (common name) of www.steakumm.com, and issuer /C=US/O=Let's Encrypt/CN=R3
  • the 1st cert has a subject with /C=US/O=Let's Encrypt/CN=R3 (matching the issuer of cert 0), and issuer of /C=US/O=Internet Security Research Group/CN=ISRG Root X1
  • the 2nd cert in the chain has subject /C=US/O=Internet Security Research Group/CN=ISRG Root X1 and issuer /O=Digital Signature Trust Co./CN=DST Root CA X3

An example of a site that delivers an incomplete chain: 

$ HOST=incomplete-chain.badssl.com  
$ openssl s_client -connect ${HOST}:${PORT} -servername ${HOST}
CONNECTED(00000005)
depth=0 C = US, ST = California, L = Walnut Creek, O = Lucas Garron Torres, CN = *.badssl.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = California, L = Walnut Creek, O = Lucas Garron Torres, CN = *.badssl.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Walnut Creek/O=Lucas Garron Torres/CN=*.badssl.com
   i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA

You can see the errors there. "unable to verify the first certificate." 

After you check the chain of certificates on YOUR target, verify that openssl thinks it is a complete chain, and then verify that a cert with a subject equal to the issuer of the final cert in the chain, is present in your truststore.  

Getting back to the steakumm example, a client connecting to that target, in order to verify the chain of trust, must have a self-signed cert with a subject that corresponds to the issuer for cert #2.  If steakumm didn't send the full chain, then the client would not be able to verify the chain of signatures. If the client did not have the self-signed cert with the subject of /O=Digital Signature Trust Co./CN=DST Root CA X3, then again, the client would not be able to verify the chain of signatures. And in either case it would return a result like "could not find certification path" etc.

Thanks @dchiesa1 ,

Now I am getting error- Unable to resolve host 'https://XXXXXXX/yy/uu'.

using ingress Host name in target flow using 1 way TLS communication-

<HTTPTargetConnection>
<URL>https://XXXXXXX/yy/uu</URL>
<SSLInfo>
<Enabled>true</Enabled>
<ClientAuthEnabled>false</ClientAuthEnabled>
<!-- <KeyStore></KeyStore>
<KeyAlias></KeyAlias>-->
<TrustStore>ref://aaaaa</TrustStore>
<IgnoreValidationErrors>false</IgnoreValidationErrors>
</SSLInfo>
</HTTPTargetConnection>
</TargetEndpoint>

Ingress host -https://XXXXXXX/yy/uu  is getting resolved by browser and other non-APIGEE flows. we were successfully able to get result. 

We are using Root CA cert chain  in trust store in Apigee. 

I read your reply and I am not clear at all what problem you are having now. 

"unable to resolve host" has nothing to do with certificate chains or keystores.  It's a DNS problem.

I thought you were having a TLS handshake problem.  I made some suggestions to help resolve that problem.

Now I think you are asking me about hostname resolution for ingress?   In other words accessing an Apigee-managed endpoint from the internet? That seems to be a totally different problem. Is that correct? 

If so, can you please ask a new question ?

If you are getting an error FROM APIGEE that it is unable to resolve a hostname, then.... I think maybe you need to check that hostname.  Apigee will use DNS to resolve hostnames. If you have Apigee hybrid, it may use its own DNS setup.  That's all under your control. 

 

Thanks Dino,

its resolved