This document is a continuation of the Gist AzureEventHubsJavaSDKCustomEndpointWebSockets.md, where we are going to use a custom domain (e.g., apg-eh.anuchan.us) to connect to the Application Gateway (instead of using its Public IPv4 address, e.g., 20.232.196.115).
If you own the root domain (e.g., anuchan.us), we can use Azure DNS Zone to create a DNS record (e.g., apg-eh.anuchan.us) under the root and associate it with the Application Gateway Public IPv4 address.
Let's create an Azure DNS Zone by following the official documentation.
The overview page will list all the nameservers associated with the Azure DNS Zone.
As mentioned in the documentation, update the DNS management section of the domain you own (e.g., anuchan.us) to delegate the domain lookup to the Azure DNS Zone's nameservers.
It takes around 20 minutes to complete the delegation. As mentioned in the official documentation, once completed, nslookup will output the Azure nameserver for your domain (e.g., anuchan.us)
Now using Azure DNS Zone, we can create a DNS record (e.g., apg-eh.anuchan.us) under the domain you own (e.g., anuchan.us) and associate it with the Application Gateway's Public IPv4 address.
Create an A Record for the domain (e.g., apg-eh.anuchan.us) and associate it with AppGateway's Public IPv4 address.
Prepare a self-signed certificate for the domain (e.g., apg-eh.anuchan.us).
-
Create a config file config3.txt - ensure the config file's alt_names section has
- the domain name.
- the "Public IP" if you continue to use the IP address in addition to the domain name as CustomEndpointAddress.
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = WA
L = Redmond
O = Contoso
OU = JavaSDK
CN = DevExperience
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = apg-eh.anuchan.us
IP.1 = 20.232.196.115
- Use the openssl tool with the config file to generate the PFX certificate.
openssl req -x509 -nodes -keyout ./cert-3.pem -out ./cert-3.pem -days 365 -newkey rsa:2048 -config ./config3.txt
openssl pkcs12 -export -out ./cert-3.pfx -in ./cert-3.pem -name "AppGateway Cert apg-eh.anuchan.us" -passout pass:
<pfx-password>
We can export the CRT (client certificate) from the cert-3.pfx using openssl
openssl pkcs12 -in ./cert-3.pfx -out cert-3.crt -nokeys -clcerts
then import it to the Java KeyStore.
keytool -import -file cert-3.crt -keystore "C:\Program Files\Zulu\zulu-11\lib\security\cacerts" -alias AppGatway-SelfSigned-apg-eh-anuchan-us-Cert
Note: To find the absolute path to the Keystore
- Use mvn --version to print the Java Home (below the value of runtime:)
C:\code> mvn --version
Apache Maven 3.8.6 (...)
Maven home: C:\apache-maven-3.8.6
Java version: 11.0.15, vendor: Azul Systems, Inc., runtime: C:\Program Files\Zulu\zulu-11
- The Java KeyStore will at "\lib\security\cacerts" relative to the Java Home e.g. "C:\Program Files\Zulu\zulu-11\lib\security\cacerts".
At this point, the java code can connect to Event Hubs through the Custom domain assigned to AppGateway Public IP.
List<EventData> telemetryEvents = Arrays.asList(
new EventData("Roast beef".getBytes(UTF_8)),
new EventData("Cheese".getBytes(UTF_8)),
new EventData("Tofu".getBytes(UTF_8)),
new EventData("Turkey".getBytes(UTF_8)));
AzureNamedKeyCredential credential = new AzureNamedKeyCredential("RootManageSharedAccessKey",
"<Shared Access Policy Primary or Secondary Key from the Portal>");
EventHubProducerClient producer = new EventHubClientBuilder()
.credential("<eventubs-namespace>.servicebus.windows.net", "<eventhubs-name>", credential)
.customEndpointAddress("https://<custom-domain-app-gateway>") // e.g. "https://apg-eh.anuchan.us"
.transportType(AmqpTransportType.AMQP_WEB_SOCKETS)
.buildProducerClient();
EventDataBatch currentBatch = producer.createBatch();
for (EventData event : telemetryEvents) {
if (currentBatch.tryAdd(event)) {
continue;
}
producer.send(currentBatch);
currentBatch = producer.createBatch();
if (!currentBatch.tryAdd(event)) {
System.err.printf("Event is too large for an empty batch. Skipping. Max size: %s. Event: %s%n",
currentBatch.getMaxSizeInBytes(), event.getBodyAsString());
}
}
producer.send(currentBatch);
Application gateway allows hosting multiple backends with a unique custom domain — for example, apg-eh.anuchan.us for Event Hubs, apg-sb.anuchan.us for Service Bus, so on.
It can be configured by opting in for "Multi-site listener type".
Note: Once the muti-site is enabled, the AppGateway will validate if the client request initiating the connection contains a "Host" header matching the listener's "Host name" value (e.g., apg-eh.anuchan.us). AppGateway returns the status code 404 (Not Found) if there is a mismatch. So, for example, if the client uses WebSocket underneath and fails to set the correct "Host" header, then the client connect-init requests expecting 101 response (Switching Protocol) fail with 404.