From 01d1b101b9d7e6d1a7471f87ceb1555b2ab3b73f Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 30 Jul 2026 10:16:35 +0100 Subject: [PATCH] deduplicate sslcontext code by creating an internal shared util --- .../KubernetesApiServiceDiscovery.scala | 15 +------------ .../internal/AbstractKubernetesApiImpl.scala | 19 +++------------- .../pki/kubernetes/PemManagersProvider.scala | 22 +++++++++++++++++-- .../kubernetes/KubernetesApiImpl.scala | 18 +-------------- 4 files changed, 25 insertions(+), 49 deletions(-) diff --git a/discovery-kubernetes-api/src/main/scala/org/apache/pekko/discovery/kubernetes/KubernetesApiServiceDiscovery.scala b/discovery-kubernetes-api/src/main/scala/org/apache/pekko/discovery/kubernetes/KubernetesApiServiceDiscovery.scala index da497358..943af7b5 100644 --- a/discovery-kubernetes-api/src/main/scala/org/apache/pekko/discovery/kubernetes/KubernetesApiServiceDiscovery.scala +++ b/discovery-kubernetes-api/src/main/scala/org/apache/pekko/discovery/kubernetes/KubernetesApiServiceDiscovery.scala @@ -16,8 +16,6 @@ package org.apache.pekko.discovery.kubernetes import java.net.InetAddress import java.nio.charset.StandardCharsets import java.nio.file.{ Files, Paths } -import java.security.{ KeyStore, SecureRandom } -import javax.net.ssl.{ KeyManager, KeyManagerFactory, SSLContext, TrustManager } import scala.collection.immutable import scala.collection.immutable.Seq @@ -233,18 +231,7 @@ class KubernetesApiServiceDiscovery(settings: Settings)( * This uses blocking IO, and so should only be used at startup from blocking dispatcher. */ private def clientHttpsConnectionContext(): HttpsConnectionContext = { - val certificates = PemManagersProvider.loadCertificates(settings.apiCaPath) - - val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm) - val keyStore = KeyStore.getInstance("PKCS12") - keyStore.load(null) - factory.init(keyStore, Array.empty) - val km: Array[KeyManager] = factory.getKeyManagers - val tm: Array[TrustManager] = - PemManagersProvider.buildTrustManagers(certificates) - val random: SecureRandom = new SecureRandom - val sslContext = SSLContext.getInstance(settings.tlsVersion) - sslContext.init(km, tm, random) + val sslContext = PemManagersProvider.createSslContext(settings.apiCaPath, settings.tlsVersion) ConnectionContext.httpsClient(sslContext) } diff --git a/lease-kubernetes/src/main/scala/org/apache/pekko/coordination/lease/kubernetes/internal/AbstractKubernetesApiImpl.scala b/lease-kubernetes/src/main/scala/org/apache/pekko/coordination/lease/kubernetes/internal/AbstractKubernetesApiImpl.scala index 50fcbfde..49fb33ab 100644 --- a/lease-kubernetes/src/main/scala/org/apache/pekko/coordination/lease/kubernetes/internal/AbstractKubernetesApiImpl.scala +++ b/lease-kubernetes/src/main/scala/org/apache/pekko/coordination/lease/kubernetes/internal/AbstractKubernetesApiImpl.scala @@ -30,8 +30,7 @@ import pekko.stream.scaladsl.{ FileIO, Keep, Sink } import pekko.util.ByteString import java.nio.file.{ Files, Paths } -import java.security.{ KeyStore, SecureRandom } -import javax.net.ssl.{ KeyManager, KeyManagerFactory, SSLContext, TrustManager } +import javax.net.ssl.SSLContext import scala.collection.immutable import scala.concurrent.{ ExecutionContext, Future } import scala.util.control.NonFatal @@ -51,20 +50,8 @@ import scala.util.control.NonFatal protected val log: LoggingAdapter = Logging(system, getClass: Class[?]) private val http: HttpExt = Http()(system) - private lazy val sslContext: SSLContext = { - val certificates = PemManagersProvider.loadCertificates(settings.apiCaPath) - val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm) - val keyStore = KeyStore.getInstance("PKCS12") - keyStore.load(null) - factory.init(keyStore, Array.empty) - val km: Array[KeyManager] = factory.getKeyManagers - val tm: Array[TrustManager] = - PemManagersProvider.buildTrustManagers(certificates) - val random: SecureRandom = new SecureRandom - val sslContext = SSLContext.getInstance(settings.tlsVersion) - sslContext.init(km, tm, random) - sslContext - } + private lazy val sslContext: SSLContext = + PemManagersProvider.createSslContext(settings.apiCaPath, settings.tlsVersion) private lazy val clientSslContext: HttpsConnectionContext = ConnectionContext.httpsClient(sslContext) diff --git a/management-pki/src/main/scala/org/apache/pekko/pki/kubernetes/PemManagersProvider.scala b/management-pki/src/main/scala/org/apache/pekko/pki/kubernetes/PemManagersProvider.scala index 5dd24816..a867dacb 100644 --- a/management-pki/src/main/scala/org/apache/pekko/pki/kubernetes/PemManagersProvider.scala +++ b/management-pki/src/main/scala/org/apache/pekko/pki/kubernetes/PemManagersProvider.scala @@ -16,7 +16,7 @@ package org.apache.pekko.pki.kubernetes import java.io.File import java.nio.charset.StandardCharsets import java.nio.file.Files -import java.security.{ KeyStore, PrivateKey } +import java.security.{ KeyStore, PrivateKey, SecureRandom } import java.security.cert.{ Certificate, CertificateFactory } import scala.concurrent.blocking @@ -27,7 +27,7 @@ import org.apache.pekko import pekko.annotation.InternalApi import pekko.pki.pem.{ DERPrivateKeyLoader, PEMDecoder } -import javax.net.ssl.{ TrustManager, TrustManagerFactory } +import javax.net.ssl.{ KeyManagerFactory, SSLContext, TrustManager, TrustManagerFactory } /** * INTERNAL API @@ -68,4 +68,22 @@ private[pekko] object PemManagersProvider { certFactory.generateCertificates(Files.newInputStream(new File(filename).toPath)).asScala } + /** + * INTERNAL API + * + * Creates an SSLContext that trusts the given CA certificate file, with no client key material. + */ + @InternalApi def createSslContext(caCertPath: String, tlsVersion: String): SSLContext = { + val certificates = loadCertificates(caCertPath) + val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm) + val ks = KeyStore.getInstance("PKCS12") + ks.load(null) + factory.init(ks, Array.empty) + val km = factory.getKeyManagers + val tm = buildTrustManagers(certificates) + val sslContext = SSLContext.getInstance(tlsVersion) + sslContext.init(km, tm, new SecureRandom) + sslContext + } + } diff --git a/rolling-update-kubernetes/src/main/scala/org/apache/pekko/rollingupdate/kubernetes/KubernetesApiImpl.scala b/rolling-update-kubernetes/src/main/scala/org/apache/pekko/rollingupdate/kubernetes/KubernetesApiImpl.scala index c91fca20..188f74fd 100644 --- a/rolling-update-kubernetes/src/main/scala/org/apache/pekko/rollingupdate/kubernetes/KubernetesApiImpl.scala +++ b/rolling-update-kubernetes/src/main/scala/org/apache/pekko/rollingupdate/kubernetes/KubernetesApiImpl.scala @@ -47,12 +47,6 @@ import pekko.util.ByteString import java.nio.file.Files import java.nio.file.Paths -import java.security.KeyStore -import java.security.SecureRandom -import javax.net.ssl.KeyManager -import javax.net.ssl.KeyManagerFactory -import javax.net.ssl.SSLContext -import javax.net.ssl.TrustManager /** * INTERNAL API @@ -473,17 +467,7 @@ PUTs must contain resourceVersions. Response: */ private def clientHttpsConnectionContext(k8sSettings: KubernetesSettings): Option[HttpsConnectionContext] = { if (k8sSettings.secure) { - val certificates = PemManagersProvider.loadCertificates(k8sSettings.apiCaPath) - val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm) - val keyStore = KeyStore.getInstance("PKCS12") - keyStore.load(null) - factory.init(keyStore, Array.empty) - val km: Array[KeyManager] = factory.getKeyManagers - val tm: Array[TrustManager] = - PemManagersProvider.buildTrustManagers(certificates) - val random: SecureRandom = new SecureRandom - val sslContext = SSLContext.getInstance("TLSv1.2") - sslContext.init(km, tm, random) + val sslContext = PemManagersProvider.createSslContext(k8sSettings.apiCaPath, "TLSv1.2") Some(ConnectionContext.httpsClient(sslContext)) } else None