We have the license and certificates. The only thing left is to create the DLB. Go to Anypoint Platform > Runtime Manager > Load Balancers and click “Create Load Balancer”.
The first thing we need to set is the Name of the DLB. The naming convention is important here not only because it has to be unique across all the Mulesoft DLB users in a control plane but also if your company starts to use more than one VPC and maybe different region, it would be nice to know which DLB is for which VPC just looking at to the name.
The name I chose for this DLB is “fct-dlb-non-prod-de-vpc-01”. Break down is like this:
<companyName or alias> – ”dlb” – <environment> – <region> – <vpc it belongs to>
We already have addressed the use of the properties and options on this page here. For test purposes, I will pick one of the VPCs from the list to assign this DLB and leave all the remaining options as default.
Even though you accept HTTP calls by selecting “Inbound HTTP Mode – ON” you cannot create the DLB without a certificate. You can add more than 1 certificate to 1 DLB. That comes in handy if you would like to use only 1 DLB for both your external and internal applications. Remember, when a DLB is created there will be 2 DNS addresses; 1 DNS is for public and resolves to 2 Public IPs (if you are using 2 workers) and 1 DNS is for private and resolves to 2 private IPs (two of the IPs of VPC’s CIDR block, randomly). Let’s add the certificates for the public and create a mapping rule:
In the image, you can see the key and the certificate added, and also URL Mapping Rules are changed. You will see the Mapping Rules section is closed when you first open this page because it is optional and will be set as a direct mapping. But I prefer to create a special mapping here to address only the external APIs which will add another level of security. Even when my internal app names are known to an outsider, it will not be possible for them to call my internal application due to this mapping rule. Because application names will not match. Of course to achieve that we also need to create our applications with names that will align with these mapping rules. Meaning all our external facing applications’ names must have “ext-” and internal applications’ names must have “int-” prefixes.
Also, you can see the protocol here as “http”. That means the request will be routed to the 8091 port, so your applications’ listeners should be deployed to listen to the 8091 port. If you go with “https”, then applications need to listen to 8092 ports and have a TLS configuration.
Additionally, you can use 2-way authentication with the Trusted CA File section. Let’s say you would like to be called by only certain clients, then you can upload the public key (truststore) of that client as pem-formatted here. This will enable this endpoint to validate the certificate sent back by the app by checking the local client certificate file.
After putting a file in the Trusted CA File section, you will see there are 2 more options enabled: Client Certificate Validation and Revocation List. If you would like to pass the requests nevertheless the client has the certificates of 2-way SSL, you can put the Client Certificate Validation to Optional. Then the header X-SSL-Client-Verify is set to false, which later you can control in your apps with validations. Such as, if you are doing 2-way SSL for Salesforce and the header is set to false, do not accept it on your Salesforce experience APIs but accept it on other APIs. If you need more than 1 certificate to be validated, then simply concatenate them in the same file and upload them like this:
Another use case would be creating and installing another certificate on DLB for a subdomain such as salesforce.mycompany.com and setting this certificate’s Client Certificate Validation to Mandatory. So this endpoint can only be called by a Salesforce endpoint of yours.
I will be creating one DLB with 2 certificates, 1 for external, and 1 for internal endpoints:
Now we have the following DNS:
fct-dlb-non-prod-de-vpc-01.lb.anypointdns.net for external
internal-fct-dlb-non-prod-de-vpc-01.lb.anypointdns.net for internal
For the CNAME records, we can use them as
api.mycompany.com – – – CNAME – – – fct-dlb-non-prod-de-vpc-01.lb.anypointdns.net
internal.mycompany.com – – – CNAME – – – internal-fct-dlb-non-prod-de-vpc-01.lb.anypointdns.net
Now we can call api.mycompany.com from the internet with:
api.mycompany.com/<app-name> for example;
https://api.mycompany.com;443/order-api/v1/orders will map to our ext-order-api on the VPC that DLB is addressing.
3-layered API architecture suggests that Process and System layers should not be reachable from the public internet. So we have only 2 options to call these applications from our Experience layer:
1- Call the downstream APIs with their application internal DNS as in mule-worker-internal-<app-name>.de-c1.cloudhub.io
2- Use the internal endpoint of DLB as in internal.mycompany.com/<app-name>/
It is okay to use the first option unless you don’t use CloudHub apps with more than 1 worker. So you don’t actually need a load balancing there, you may directly call the internal app with its internal DNS.
When you are planning to have some or all of the apps get more than 1 worker, then it is suggested that you should use DLB for internal load balancing again. Because, even though the internal worker DNS returns workers’ IP in a round-robin, the first IP from the DNS will be your request’s destination and if that request fails, your client application has to retry for the second worker’s IP and goes on. But if you use DLB to call your internal apps as well, it will try all the workers automatically.
Having only one DLB per environment (capacity-wise) is enough. But what about security? There is a catch for using only one DLB; your DLB can be tricked to call your internal applications directly. When you send a request to your DLB’s public DNS (or to your vanity domain) with a header key “host” and value that targets your internal DNS, then you will see that you can call your internal application from the internet.
There are 2 ways to prevent that (other than getting the second DLB):
- You can add a client certificate to where your internal certificate is configured, as here. Now public applications cannot call your internal APIs without the proper certificate, but you have to add that certificate to the HTTP requester component for all your upstream APIs since those are the one that is going to call your internal APIs.
- You can put an IP Whitelisting policy for your internal (VPC) CIDR. With that, you make sure your internal applications can only be called by the IPs that are in the range.