Skip to content

Instantly share code, notes, and snippets.

@anuchandy
Last active October 30, 2022 20:22
Show Gist options
  • Save anuchandy/7c0f76f0cfc5a82beb8eced40f53843f to your computer and use it in GitHub Desktop.
Save anuchandy/7c0f76f0cfc5a82beb8eced40f53843f to your computer and use it in GitHub Desktop.

Custom Domain and CustomEndpointAddress

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.

Public Azure DNS Zone

Let's create an Azure DNS Zone by following the official documentation.

CreateDNSZone

The overview page will list all the nameservers associated with the Azure DNS Zone.

DNSZoneNameServer

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.

CustomNameServers

CustomNameServersReady

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)

NSLookup

Creating DNS Record for App Gateway's Public IP

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.

DNSRecordSet

RecordSetAdded

Create a self-signed PFX certificate

Prepare a self-signed certificate for the domain (e.g., apg-eh.anuchan.us).

  1. 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
  1. 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>

Associate the self-signed PFX certificate to AppGateway's port 443

Apg443CertUpdate

Import the CER version of PFX to Java KeyStore

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

  1. 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
  1. The Java KeyStore will at "\lib\security\cacerts" relative to the Java Home e.g. "C:\Program Files\Zulu\zulu-11\lib\security\cacerts".

That's It

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 Multi-site

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".

Apg443MultiSite

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment