diff --git a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ClientAdapter.kt b/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ClientAdapter.kt index c8d416d4d..a92c41745 100644 --- a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ClientAdapter.kt +++ b/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ClientAdapter.kt @@ -11,7 +11,7 @@ package com.redhat.devtools.intellij.kubernetes.model.client import com.redhat.devtools.intellij.common.kubernetes.ClusterHelper -import com.redhat.devtools.intellij.kubernetes.model.client.ssl.IDEATrustManager +import com.redhat.devtools.intellij.common.ssl.IDEATrustManager import io.fabric8.kubernetes.client.Client import io.fabric8.kubernetes.client.Config import io.fabric8.kubernetes.client.KubernetesClient @@ -59,7 +59,7 @@ abstract class ClientAdapter(private val fabric8Client: C) fun create( namespace: String? = null, context: String? = null, - trustManagerProvider: ((toIntegrate: Array) -> X509TrustManager) + trustManagerProvider: ((toIntegrate: List) -> X509TrustManager) = IDEATrustManager()::configure ): ClientAdapter { val config = Config.autoConfigure(context) @@ -69,7 +69,7 @@ abstract class ClientAdapter(private val fabric8Client: C) fun create( namespace: String? = null, config: Config, - externalTrustManagerProvider: (toIntegrate: Array) -> X509TrustManager + externalTrustManagerProvider: (toIntegrate: List) -> X509TrustManager = IDEATrustManager()::configure ): ClientAdapter { setNamespace(namespace, config) @@ -90,11 +90,10 @@ abstract class ClientAdapter(private val fabric8Client: C) private fun setSslContext( builder: HttpClient.Builder, config: Config, - externalTrustManagerProvider: (toIntegrate: Array) -> X509TrustManager + externalTrustManagerProvider: (toIntegrate: List) -> X509TrustManager ) { val clientTrustManagers = SSLUtils.trustManagers(config) .filterIsInstance() - .toTypedArray() val externalTrustManager = externalTrustManagerProvider.invoke(clientTrustManagers) builder.sslContext(SSLUtils.keyManagers(config), arrayOf(externalTrustManager)) } diff --git a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/CompositeX509ExtendedTrustManager.kt b/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/CompositeX509ExtendedTrustManager.kt deleted file mode 100644 index d15bbb817..000000000 --- a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/CompositeX509ExtendedTrustManager.kt +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Based on nl.altindag.ssl.trustmanager.CompositeX509ExtendedTrustManager at https://github.com/Hakky54/sslcontext-kickstart - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ - -package com.redhat.devtools.intellij.kubernetes.model.client.ssl - -import java.net.Socket -import java.security.cert.CertificateException -import java.security.cert.X509Certificate -import java.util.* -import java.util.function.Consumer -import javax.net.ssl.SSLEngine -import javax.net.ssl.X509ExtendedTrustManager - -class CompositeX509ExtendedTrustManager(trustManagers: List): X509ExtendedTrustManager() { - - companion object { - private const val CERTIFICATE_EXCEPTION_MESSAGE = "None of the TrustManagers trust this certificate chain" - } - - val innerTrustManagers: List - private val acceptedIssuers: Array - - init { - innerTrustManagers = Collections.unmodifiableList(trustManagers) - acceptedIssuers = trustManagers - .map { manager: X509ExtendedTrustManager -> manager.acceptedIssuers } - .flatMap { acceptedIssuers: Array? -> - acceptedIssuers?.asList() ?: emptyList() - } - .toTypedArray() - } - - override fun getAcceptedIssuers(): Array { - return Arrays.copyOf(acceptedIssuers, acceptedIssuers.size) - } - - @Throws(CertificateException::class) - override fun checkClientTrusted(chain: Array, authType: String) { - checkTrusted { trustManager: X509ExtendedTrustManager -> - trustManager.checkClientTrusted( - chain, - authType - ) - } - } - - @Throws(CertificateException::class) - override fun checkClientTrusted(chain: Array, authType: String, socket: Socket) { - checkTrusted { trustManager: X509ExtendedTrustManager -> - trustManager.checkClientTrusted( - chain, - authType, - socket - ) - } - } - - @Throws(CertificateException::class) - override fun checkClientTrusted(chain: Array, authType: String, sslEngine: SSLEngine) { - checkTrusted { trustManager: X509ExtendedTrustManager -> - trustManager.checkClientTrusted( - chain, - authType, - sslEngine - ) - } - } - - @Throws(CertificateException::class) - override fun checkServerTrusted(chain: Array, authType: String) { - checkTrusted{ trustManager: X509ExtendedTrustManager -> - trustManager.checkServerTrusted( - chain, - authType - ) - } - } - - @Throws(CertificateException::class) - override fun checkServerTrusted(chain: Array, authType: String, socket: Socket) { - checkTrusted{ trustManager: X509ExtendedTrustManager -> - trustManager.checkServerTrusted( - chain, - authType, - socket - ) - } - } - - @Throws(CertificateException::class) - override fun checkServerTrusted(chain: Array, authType: String, sslEngine: SSLEngine) { - checkTrusted { trustManager: X509ExtendedTrustManager -> - trustManager.checkServerTrusted( - chain, - authType, - sslEngine - ) - } - } - - @Throws(CertificateException::class) - private fun checkTrusted(consumer: (trustManager: X509ExtendedTrustManager) -> Unit) { - val certificateExceptions: MutableList = ArrayList() - for (trustManager in innerTrustManagers) { - try { - consumer.invoke(trustManager) - return - } catch (e: CertificateException) { - certificateExceptions.add(e) - } - } - val certificateException = CertificateException(CERTIFICATE_EXCEPTION_MESSAGE) - certificateExceptions.forEach(Consumer { exception: CertificateException? -> - certificateException.addSuppressed( - exception - ) - }) - throw certificateException - } -} diff --git a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/IDEATrustManager.kt b/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/IDEATrustManager.kt deleted file mode 100644 index 8bfd5c774..000000000 --- a/src/main/kotlin/com/redhat/devtools/intellij/kubernetes/model/client/ssl/IDEATrustManager.kt +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v20.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package com.redhat.devtools.intellij.kubernetes.model.client.ssl - -import com.intellij.openapi.diagnostic.logger -import com.intellij.util.net.ssl.CertificateManager -import com.intellij.util.net.ssl.ConfirmingTrustManager -import java.lang.reflect.Field -import javax.net.ssl.X509ExtendedTrustManager -import javax.net.ssl.X509TrustManager -import org.apache.commons.lang3.reflect.FieldUtils - -class IDEATrustManager(private val trustManager: X509TrustManager = CertificateManager.getInstance().trustManager) { - - fun configure(toAdd: Array): X509TrustManager { - try { - if (hasSystemManagerField()) { - // < IC-2022.2 - setCompositeManager(toAdd, trustManager) - } else { - // >= IC-2022.2 - addCompositeManager(toAdd, trustManager) - } - } catch (e: RuntimeException) { - logger().warn("Could not configure IDEA trust manager.", e) - } - return trustManager - } - - /** - * Returns `true` if [ConfirmingTrustManager] has a private field `mySystemManager`. - * Returns `false` otherwise. - * IDEA < IC-2022.2 manages a single [X509TrustManager] in a private field called `mySystemManager`. - * IDEA >= IC-2022.2 manages a list of [X509TrustManager]s in a private list called `mySystemManagers`. - * - * @return true if com.intellij.util.net.ssl.ConfirmingTrustManager has a field mySystemManager. False otherwise. - */ - private fun hasSystemManagerField(): Boolean { - return getSystemManagerField() != null - } - - private fun getSystemManagerField(): Field? { - return FieldUtils.getDeclaredField( - trustManager::class.java, - "mySystemManager", - true - ) - } - - /** - * Sets a [CompositeX509ExtendedTrustManager] with the given [X509TrustManager]s - * to the given destination [X509TrustManager]. - * If a [CompositeX509ExtendedTrustManager] already exists, his first entry is taken and set to a new - * [CompositeX509ExtendedTrustManager] that replaces the existing one. - * - * @param trustManagers the trust managers that should be set to the destination trust manager - * @param destination the destination trust manager that should receive the trust managers - * @return true if the operation worked - */ - private fun setCompositeManager( - trustManagers: Array, - destination: X509TrustManager - ): Boolean { - val systemManagerField = getSystemManagerField() ?: return false - val systemManager = systemManagerField.get(destination) as? X509ExtendedTrustManager ?: return false - val compositeTrustManager = createCompositeTrustManager(systemManager, trustManagers) - systemManagerField.set(destination, compositeTrustManager) - return true - } - - private fun createCompositeTrustManager( - systemManager: X509ExtendedTrustManager, - clientTrustManagers: Array - ): X509ExtendedTrustManager { - val trustManagers = if (systemManager is CompositeX509ExtendedTrustManager) { - // already patched CertificateManager, take 1st entry in existing system manager - mutableListOf(systemManager.innerTrustManagers[0]) - } else { - // unpatched CertificateManager, take system manager - mutableListOf(systemManager) - } - trustManagers.addAll(clientTrustManagers) - return CompositeX509ExtendedTrustManager(trustManagers) - } - - /** - * Adds a [CompositeX509ExtendedTrustManager] to the given destination [X509TrustManager]. - * If a [CompositeX509ExtendedTrustManager] already exists, it is replaced by a new [CompositeX509ExtendedTrustManager]. - * - * @param trustManagers the trust managers that should be added to destination trust manager - * @param destination the trust manager that should receive the given trust managers - */ - private fun addCompositeManager( - trustManagers: Array, - destination: X509TrustManager - ): Boolean { - val systemManagersField = FieldUtils.getDeclaredField( - destination::class.java, - "mySystemManagers", - true - ) ?: return false - val managers = systemManagersField.get(destination) as? MutableList ?: return false - val nonCompositeManagers = managers.filterNot { it is CompositeX509ExtendedTrustManager } - val clientTrustManager = CompositeX509ExtendedTrustManager(trustManagers.asList()) - managers.clear() - managers.addAll(nonCompositeManagers) - managers.add(clientTrustManager) - return true - } -} \ No newline at end of file