From a6f6bb549f8fee9f89655d344fd17c8e7c52d3f8 Mon Sep 17 00:00:00 2001 From: mherman22 Date: Sat, 4 Apr 2026 11:18:27 +0000 Subject: [PATCH] Fix SSL hostname verification failure in PullNotificationsTask The OkHttpClient in NotificationsPullPointClientImpl used default SSL configuration, causing SSLPeerUnverifiedException when the server certificate CN does not match the hostname (e.g., behind a load balancer or reverse proxy). Reuse the existing xdssender.exportCcd.ignoreCerts global property to optionally bypass SSL hostname verification and certificate validation for the pull notifications endpoint, matching the behavior already available for CCD export via XdsRetriever. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../NotificationsPullPointClientImpl.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java b/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java index 5048d35..de398cc 100644 --- a/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java +++ b/api/src/main/java/org/openmrs/module/xdssender/api/notificationspullpoint/impl/NotificationsPullPointClientImpl.java @@ -49,6 +49,12 @@ import org.w3c.dom.Element; import ca.uhn.hl7v2.model.Message; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.net.ssl.SSLSocketFactory; +import java.security.cert.X509Certificate; + import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -162,7 +168,22 @@ private GetMessagesResponse getResponseHttpClient(GetMessages requestPayload) th StringResult result = new StringResult(); marshaller.marshal(requestPayload, result); - OkHttpClient client = new OkHttpClient().newBuilder().build(); + OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder(); + if (config.getExportCcdIgnoreCerts()) { + final TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} + @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} + @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + clientBuilder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); + clientBuilder.hostnameVerifier((hostname, session) -> true); + } + OkHttpClient client = clientBuilder.build(); MediaType mediaType = MediaType.parse("text/xml; charset=utf-8"); String facilitySiteCode = requestPayload.getOtherAttributes().get(new QName(FACILITY_QNAME)); String sinceAttribute = StringUtils.isNotBlank(lastRequestDate) && isValidISODate(lastRequestDate) ? String.format("since=\"%s\"", lastRequestDate)