Network and Envoy Proxy Configuration to manage mTLS on Apigee X - part2/2

Reminder

In this two-part article we discuss the network configuration for consuming APIs on Apigee X using mutual TLS (mTLS).

As mentioned in the first article of the series, the scope is a situation where external client applications must use mTLS to access APIs hosted on Apigee X.

joel_gauci_0-1636368023698.png

We go on with the configuration of the TCP Proxy load balancer and conclude tests of the overall configuration.

Google Cloud TCP Proxy Load Balancer

In this second part of the article we describe the creation of the TCP Proxy load Balancer. This LB is attached to the NEG created in the previous section.

joel_gauci_0-1636366784137.png

Let’s start creating the load balancer’s health check component, using the following gcloud command:

gcloud compute health-checks create tcp my-tcp-health-check --port 8443

Configure the firewall to allow traffic from the load balancer and health checker to the instances. In this case, we will open TCP port 8443. The health check will use the same port.

gcloud compute firewall-rules create allow-tcplb-and-health \
--source-ranges 130.211.0.0/22,35.191.0.0/16 \
--network=$VPC_NET \
--allow tcp:8443

Create the backend service for the TCP Proxy load balancer:

gcloud compute backend-services create my-tcp-lb \
--global-health-checks \
--global \
--protocol TCP \
--health-checks my-tcp-health-check \
--timeout 5m

Add the NEG to the backend service:

gcloud compute backend-services add-backend my-tcp-lb \
--global \
--network-endpoint-group $NEG \
--network-endpoint-group-zone $ZONE \
--balancing-mode CONNECTION \
--max-connections 100000

Configure the target TCP proxy for the load balancer:

gcloud compute target-tcp-proxies create my-tcp-lb-target-proxy \
--backend-service my-tcp-lb \
--proxy-header NONE

Reserve a global static IPV4 address:

gcloud compute addresses create tcp-lb-static-ipv4 \
--ip-version=IPV4 \
--global

Get the list of IP addresses and check the tcp-lb-static-ipv4 has been created:

gcloud compute addresses list

Create an environment variable that contains the global IPV4 address:

export IPV4_ADDRESS=$(gcloud compute addresses list --format=json | jq -r '.[] | select( .name | contains("tcp-lb-static-ipv4")) | .address')

You can now configure the global forwarding rules of the TCP Proxy load balancer:

gcloud compute forwarding-rules create my-tcp-lb-ipv4-forwarding-rule \
--global \
--target-tcp-proxy my-tcp-lb-target-proxy \
--address tcp-lb-static-ipv4 \
--ports 443

Testing the configuration on Apigee X

At this step, you can create a proxy and deploy it on one of the environments related to the environment group for which mTLS is required.

joel_gauci_1-1636366784092.png

Once the proxy has been deployed, you can access it using an HTTP client like cURL. 

Here is the cURL command to request an API proxy (hello-world), whose basepath is /hello-world:

curl https://$RUNTIME_MTLS_HOST_ALIAS/hello-world \
--cert $CLIENTAPP_CERT_FILE \
--key $CLIENTAPP_KEY_FILE \
--cacert $ENVOY_PROXY_CERT_FILE \
--resolve $RUNTIME_MTLS_HOST_ALIAS:443:$IPV4_ADDRESS -v

The client cert used during the mTLS handshake is retrieved in the envoy proxy and transmitted to Apigee X. 

Activate a debug trace on your API proxy to check that the x-apigee-tls-client-raw-cert request header is received on the proxy, as shown on the following picture:

joel_gauci_2-1636366784133.png

 

The x-client-cert request header is automatically forwarded to the target unless explicitly removed from the request. So it is recommended to put an Assign Message policy to remove the certificate information from the request headers before the target communication. 

This policy can be added on the Apigee target endpoint, at the Preflow level, as shown here:

 

joel_gauci_3-1636366784164.png

Here is the configuration of the Assign Message policy:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage name="AM-RemoveHeader">
    <Remove>
        <Headers>
            <Header name="x-apigee-tls-client-raw-cert"/>
        </Headers>
    </Remove>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

Thanks to Priya Saxena, Daniel Strebel and Omid Tahouri for their feedback on drafts of this article!

Contributors
Version history
Last update:
‎03-24-2022 03:43 AM
Updated by: