From 2e17eca1913564126d54df1ee9b1e51617b4794c Mon Sep 17 00:00:00 2001 From: JinwooHwang Date: Sun, 15 Mar 2026 10:31:53 -0400 Subject: [PATCH] GEODE-10556: Use localhost for Pulse JMX host when JmxManagerBindAddress is empty When JmxManagerBindAddress is not configured (empty string, meaning bind all interfaces), ManagementAgent was setting the pulse.host system property to the empty string. On Linux/Docker, an empty host in the JMX service URL resolves to InetAddress.getLocalHost(), which returns the container bridge IP (e.g. 172.17.0.2) rather than 127.0.0.1. The embedded test keystore (trusted.keystore) only contains IPAddress:127.0.0.1 as a Subject Alternative Name. The SSL handshake between Pulse JMXDataUpdater and the JMX connector server therefore failed: SSLHandshakeException: No subject alternative names matching IP address 172.17.0.2 found This caused PulseSecurityWithSSLTest to consistently fail on CI (Ubuntu, Liberica JDK 17, Docker) with BAD_CREDS while passing locally on macOS with Zulu JDK 17 (where getLocalHost() returns 127.0.0.1). Fix: when JmxManagerBindAddress is empty, pass localhost as the pulse.host property so JMXDataUpdater connects to 127.0.0.1, which is always covered by the certificate SAN. --- .../geode/management/internal/ManagementAgent.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java b/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java index 89ebe3bf844..82f908459f6 100755 --- a/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java @@ -296,7 +296,14 @@ private void loadWebApplications() { // we need to pass in the sllConfig to pulse because it needs it to make jmx connection if (agentUtil.isAnyWarFileAvailable(pulseWar)) { System.setProperty(PULSE_EMBEDDED_PROP, "true"); - System.setProperty(PULSE_HOST_PROP, "" + config.getJmxManagerBindAddress()); + // When JmxManagerBindAddress is empty (bind all interfaces), Pulse must connect to + // localhost rather than the empty string. An empty host in the JMX URL resolves to + // InetAddress.getLocalHost(), which on Linux/Docker gives the container's bridge IP + // (e.g. 172.17.0.2) instead of 127.0.0.1. The embedded keystore only contains + // IPAddress:127.0.0.1 as a SAN, so the SSL handshake fails on any non-loopback IP. + String jmxBindAddress = config.getJmxManagerBindAddress(); + System.setProperty(PULSE_HOST_PROP, + jmxBindAddress.isEmpty() ? "localhost" : jmxBindAddress); System.setProperty(PULSE_PORT_PROP, "" + config.getJmxManagerPort()); final SocketCreator jmxSocketCreator =