This article recommends the best practice on how to use the PropagateTLSInformation feature to secure API proxies by whitelisting specific client certificates signed by a trusted CA. This is an alternative to creating trust stores with long lists of specific client certificates, which can add overheads to the TLS handshake process.
Prerequisite: An API proxy with a virtual host configured for 2-way TLS (ClientAuthEnabled).
Steps
- Update VirtualHost properties
Adding the below two properties to the virtualhost will activate the documented population of TLS flow variables.
<PropagateTLSInformation>
<ConnectionProperties>true</ConnectionProperties>
<ClientProperties>true</ClientProperties>
</PropagateTLSInformation>
The Edge UI doesnāt currently support these flags. You must use the self-serve Virtual hosts API to make the update. For example:
curl -u $USERID:$USERPASSWORD -X PUT \
[https://api.enterprise.apigee.com/v1/o/$org/e/$env/virtualhosts/secure-two-way](https://api.enterprise.apigee.com/v1/o/$org/e/$env/virtualhosts/secure-two-way) \
-H "Content-Type: application/xml" \
-d '<VirtualHost name="secure-two-way">
<HostAliases>
<HostAlias>gsc-test-twoway.apigee.net</HostAlias>
</HostAliases>
<Interfaces/>
<ListenOptions/>
<Port>443</Port>
<Properties>
<Property name="ssl_protocols">TLSv1.2</Property>
</Properties>
<RetryOptions/>
<SSLInfo>
<Ciphers/>
<ClientAuthEnabled>true</ClientAuthEnabled>
<Enabled>true</Enabled>
<IgnoreValidationErrors>false</IgnoreValidationErrors>
<KeyAlias>freetrial</KeyAlias>
<KeyStore>ref://freetrial</KeyStore>
<Protocols/>
<TrustStore>ref://edgemicro-ref</TrustStore>
</SSLInfo>
<PropagateTLSInformation>
<ConnectionProperties>true</ConnectionProperties>
<ClientProperties>true</ClientProperties>
</PropagateTLSInformation>
</VirtualHost>'
Note. ConnectionProperties is optional for the purposes of this tutorial.
Once these flags have been applied, the Edge router will then send HTTP headers to the message processor containing these values (example below). The MP will make them available as flow variables, so you donāt need to access the actual request.header.{header-name}. Instead, use the documented flow vars.
Please note, by default, these headers will be stripped off from the request before it goes to the target from release 190301 of cloud onwards.
Typically, the client certificate would be issued and signed by a Certificate Authority that is in the trust store of the Virtual Host. This trust store may contain an internal CA which is used to sign many x.509 certificates, of which only some should be able to access the proxy.
To get around this without having to load all those specific client certs into the trust store every time, we can whitelist the ātls.client.s.dnā and/or ātls.client.cert.fingerprintā in the actual proxy.
The best place to store the whitelist is in a KVM. Be wary, since client DN may contain commas. This means we are not able to use comma separated lists, but instead should choose some other separator and later separate it using a JavaScript callout policy. For fingerprints it is safe to use comma separated lists because these are SHA1 hashes which only have hex characters.
Ensure to set the TTL of the KVM depending on how quickly you want changes in the whitelist to take effect.
Once the KVM values are retrieved using a KVM policy, a Javascript callout policy can then be used to verify that the client cert is in that whitelist. If it is not, a flow variable can be set so that a subsequent RaiseFault Policy can raise an error and return an HTTP 403 Forbidden error to the client.
References:
https://docs.apigee.com/api-platform/fundamentals/virtual-host-property-reference
https://docs.apigee.com/api-platform/system-administration/tls-vars
https://apidocs.apigee.com/api/virtual-hosts
https://docs.apigee.com/api-platform/reference/policies/key-value-map-operations-policy
