Mutual TLS Certificate Error When Single Signed Cert in Truststore

Follow up to: https://community.apigee.com/questions/80254/are-certificate-chains-required-in-the-truststore.html

See the link above for comments establishing how we expect Apigee to behave in regards to Mutual TLS and Truststores. The error I'm seeing below applies to the case where we have two certificates:

1) alice.crt a client certificate signed by a CA

2) ca.crt the root certificate for the CA that signed alice.crt

In this scenario I have added alice.crt to the Truststore. Currently alice.crt is the single certificate in the Truststore. My understanding, from my prior community post, is that alice.crt is viewed as a Trustanchor because it is the single cert in the Truststore and matches the cert sent by the client during the MTLs connection. So, the expected behavior is that clients initiating a connection by including alice.crt and alice.key should be accepted.

The problem: Currently when sending a request to https://{org}-{env}.apigee.net/{my-proxy-basepath} I'm getting a '400 The SSL certificate error'. The structure of my cURL request is found below.

curl -v \

--cacert ./apigee.crt

--key ./alice.key \

--cert ./alice.crt \

https://{org}-{env}.apigee.net/{my-proxy-basepath}

This is for Apigee public cloud. When I add the root CA to the Truststore the connection is accepted. Only when alice.crt is present alone in the Truststore is the request not accepted. I've tested both sending alice.crt and sending a chain.crt which is ca.crt appended to alice.crt with a space in blank line in between. I've also checked to ensure that the files are in PEM format.

One possible cause is that Apigee always looks for a self signed cert when validating certificates. Meaning only self signed (root) certs can be valid trust anchors.

See this related posts (at the bottom, comments made by Kurt and Sam:

https://community.apigee.com/questions/36406/2-way-tls-between-tls-client-and-edge.html

For testing purposes I created my own root CA and client cert. Below I've included a link of a post with a script that generates a root ca, intermediate ca, and client cert. I've tested scenarios where I only generated a client cert and ca cert and also scenarios involving an intermediate cert as well. In all cases it appears that Apigee only accepts the request when ca.crt is present in the Truststore. (Note if you exclude the intermediate cert but send the complete chain in the request then the request is accepted if and only if CA.crt is present in the Truststore).

https://stackoverflow.com/questions/26759550/how-to-create-own-self-signed-root-certificate-and-inte...

Solved Solved
1 1 689
1 ACCEPTED SOLUTION

I think this is by design, perhaps considering the number of individual client certs that may come into play. So, you only need the CA.pem in the truststore alias for all clients that where signed by that CA. Of course you can have multiple CA aliases.

9787-screen-shot-2020-03-31-at-85522-am.png

What I've done to validate an App, is to associate a custom attribute on the App (e.g. client_cn=Partner1-Client1) then compare that to the value of "client.cn" from the certificate presented by the App.

https://docs.apigee.com/api-platform/reference/variables-reference#client

You could also created a KVM with a list of valid "client_cns", then check if the value of "client.cn" is in the list.

Hope that helps.

View solution in original post

1 REPLY 1

I think this is by design, perhaps considering the number of individual client certs that may come into play. So, you only need the CA.pem in the truststore alias for all clients that where signed by that CA. Of course you can have multiple CA aliases.

9787-screen-shot-2020-03-31-at-85522-am.png

What I've done to validate an App, is to associate a custom attribute on the App (e.g. client_cn=Partner1-Client1) then compare that to the value of "client.cn" from the certificate presented by the App.

https://docs.apigee.com/api-platform/reference/variables-reference#client

You could also created a KVM with a list of valid "client_cns", then check if the value of "client.cn" is in the list.

Hope that helps.