2 way TLS between TLS client and Edge

Hi All,

I have query regarding 2 way TLS between TLS client and Edge. From the Edge documentation here I understand that the client certificate needs to be added in the truststore for validation during handshaking, but i have following doubts

1. How can i make 2 way TLS applicable only for certain proxies and not all ?

2. The document here says that if ca_cert is already added in the truststore then handshaking will pass for any client certificate issued by that ca even when not present in the truststore. In this case how can i restrict handshaking to specific clients?

Solved Solved
2 9 5,242
1 ACCEPTED SOLUTION

Hi Snehal

Good questions.

For #1, the Truststore in Edge is something you may optionally add to a virtual host. This "Virtual host" is the thing that defines the properties for the inbound endpoint on Apigee Edge - for example the server certificate presented, if any, and the client certs or CAs that will be trusted, if any.

THEN, after defining the vhost, you configure your API proxies to listen on that named vhost, using confguration in the ProxyEndpoint. Like this:

<ProxyEndpoint name='default'>
  <Description>...whatever...</Description>
  <HTTPProxyConnection>
    <BasePath>/snehal-1</BasePath>
    <Properties/>
    <!-- specify the name of the vhost here  -->
    <VirtualHost>secure2way</VirtualHost>
  </HTTPProxyConnection>
  ...

But be aware: if you are using the Apigee Edge SaaS, you are not able, at this moment, to create your own vhosts. You must contact Apigee Support to request the configuration of a new vhost.

For #2, you have options.

Option 1: you can specify the root CA (and maybe other CAs in the chain) in the Truststore for the vhost. In that case, any in bound request toward that vhost, bearing a certificate signed by any member of the chain will be trusted by Apigee Edge. If you would like to be more discriminating, you can interrogate the CN from the cert in the API Proxy. I think the scenario you are describing is one in which ... your API Proxy receives a call from client Alice, who presents a valid certificate that is certified by someone you trust (let's say, Verisign, or GTE Cybertrust). Therefore Alice is authentic, but you want to reject all inbound calls that are not from Bob. The Virtual Host will allow the inbound call. Your API Proxy can use a Policy Step like this to reject calls that are not from Bob:

<Step>
  <Name>RaiseFault-Unauthorized</Name>
  <Condition>client.cn != "Bob"</Condition>
</Step>

The client.cn is a variable that will be populated into the message context when a request arrives via a 2-ay TLS connection. There are other variables populated about the client. You can find more information about these TLS-specific variables populated in the message context on this documentation page.

Option 2: you can specify ONLY the cert for the specific client in the Truststore. In that case, the vhost will work ONLY with clients that present that specific certificate. In this case the client.cn (and the other variables) will always be the CN on that specific client cert. This latter option works with self-signed certificates.

Good luck!

View solution in original post

9 REPLIES 9

Hi Snehal

Good questions.

For #1, the Truststore in Edge is something you may optionally add to a virtual host. This "Virtual host" is the thing that defines the properties for the inbound endpoint on Apigee Edge - for example the server certificate presented, if any, and the client certs or CAs that will be trusted, if any.

THEN, after defining the vhost, you configure your API proxies to listen on that named vhost, using confguration in the ProxyEndpoint. Like this:

<ProxyEndpoint name='default'>
  <Description>...whatever...</Description>
  <HTTPProxyConnection>
    <BasePath>/snehal-1</BasePath>
    <Properties/>
    <!-- specify the name of the vhost here  -->
    <VirtualHost>secure2way</VirtualHost>
  </HTTPProxyConnection>
  ...

But be aware: if you are using the Apigee Edge SaaS, you are not able, at this moment, to create your own vhosts. You must contact Apigee Support to request the configuration of a new vhost.

For #2, you have options.

Option 1: you can specify the root CA (and maybe other CAs in the chain) in the Truststore for the vhost. In that case, any in bound request toward that vhost, bearing a certificate signed by any member of the chain will be trusted by Apigee Edge. If you would like to be more discriminating, you can interrogate the CN from the cert in the API Proxy. I think the scenario you are describing is one in which ... your API Proxy receives a call from client Alice, who presents a valid certificate that is certified by someone you trust (let's say, Verisign, or GTE Cybertrust). Therefore Alice is authentic, but you want to reject all inbound calls that are not from Bob. The Virtual Host will allow the inbound call. Your API Proxy can use a Policy Step like this to reject calls that are not from Bob:

<Step>
  <Name>RaiseFault-Unauthorized</Name>
  <Condition>client.cn != "Bob"</Condition>
</Step>

The client.cn is a variable that will be populated into the message context when a request arrives via a 2-ay TLS connection. There are other variables populated about the client. You can find more information about these TLS-specific variables populated in the message context on this documentation page.

Option 2: you can specify ONLY the cert for the specific client in the Truststore. In that case, the vhost will work ONLY with clients that present that specific certificate. In this case the client.cn (and the other variables) will always be the CN on that specific client cert. This latter option works with self-signed certificates.

Good luck!

Thanks Dino for the elaborate response. We do have a SaaS environment, we will try out the suggestions you gave.

@Dino, Can you please elaborate on Option 2? This is what we are trying to implement, but it seems that I need the entire certificate chain in the truststore.
If I import the full chain to the truststore I am able to access the API with the specific client cert i imported, BUT other certs (valid) are able to access too because they are signed by the same CA. I understand this is a valid scenario, but not what we want

The documentation here makes it seem that the CA cert can be excluded: http://docs.apigee.com/api-services/content/keystores-and-truststores#createatruststore? However, if I just import the client cert to the truststore (successfully) I get a '400 The SSL certificate error' when accessing the API with the same client cert.

Do you have any ideas?

Hummmmm, well I haven't looked at that specific doc page recently. But maybe the scenario I looked at was different. Or maybe the thing you are importing into the truststore isn't the thing you think it is?

TLS trust is based on the Certificate Authority model. This is true of every system that uses TLS; Apigee Edge is just one example. The terminology across Windows, Java, and other systems might vary, but everything works the same way. For cert verifiers (either client or server side) there are "trust stores" or lists of certs or chains that are trusted. And the app will examine the inbound cert, and reconcile it against the certs that are trusted. You know all this.

But here's a key point: the so-called "chain of trust" must terminate at a self-signed cert. This is true of all correctly-implemented TLS systems. Suppose you have a trust store with a cert for B in it. And that cert is signed by A. But there is no cert for A in the truststore. When cert C is presented, signed by B, then the receiving app will not trust cert C. Even though the cert for B is in the truststore for the receiving app, the chain of trust does not terminate at a self-signed cert. It terminates at the cert B, which is signed by... somebody.... aka "who knows?" (some party the receiving app does not trust). If you add the cert for A into the truststore, and the cert for A is signed by A, then the receiving app will trust cert C.

Now suppose cert D is presented, and it is signed by E. Cert E is in the truststore, and it is self-signed. Then the receiving app will trust cert D.

Now suppose cert F is presented, and the cert for F is self-signed and it is present in the truststore. The receiving app will trust cert F.

This is explained better here.

That definitely makes sense.

I guess I assumed two way TLS worked differently... I was thinking more of a whitelisting like IP whitelisting, but with specific client certificates in the truststore. However, based on your answer to this post this can still be achieved it just takes one more step...

<Step>
<Name>RaiseFault-Unauthorized</Name>
<Condition>client.cn != "Bob"</Condition>
</Step>

Right! I think that's right on.

@Liz Lynch or @Steve Traut - what do you think of this exchange? Is there an opportunity to clarify things in the docs?

@Dino Thanks for brining this post to our attention! Copying @Stephen Gilson, as well, as he's intimately familiar with this content. We'll work on clarifying this specific use case in the documentation.

@Sam Maniscalco I have come to the same conclusion using self signed certs:

  1. Installing just the CA.pem in the truststore will trust all clients that where signed with that CA
  2. Installing the CA.pem and alice.crt (pem) has the same affect, still allows me to access with bob.crt signed by CA.pem.
  3. Installing just the alice.crt alone does not work.

There is no way, via the TrustStore, to  allow specific client certs.  If you want to restrict access to particular client certs,  you must configure your API proxy to check the client.cn variable.

Is this still the conclusion you have come to?

@Kurt Kanaskie yes, that was the same conclusion we came to as well..

If the users intent of using 2way tls was to verify the client identity then they needed to use a step that verifies client.cn