From f9de4142ba7029b62c8c47a251f29c48f0ee0b5a Mon Sep 17 00:00:00 2001 From: Stephane Bouchet Date: Wed, 22 Nov 2023 16:29:41 +0100 Subject: [PATCH] fix: can't connect to a cluster with private certificate (#599) * fix: fix private certificate connexion Signed-off-by: Stephane Bouchet * fix: fix private certificate connexion fix test Signed-off-by: Stephane Bouchet --------- Signed-off-by: Stephane Bouchet --- .github/workflows/validate_IJ_versions.yml | 2 +- build.gradle | 3 +- .../intellij/openshift/utils/odo/OdoCli.java | 40 +++++++++++++++---- src/main/resources/META-INF/plugin.xml | 2 +- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/.github/workflows/validate_IJ_versions.yml b/.github/workflows/validate_IJ_versions.yml index 9391341ea..d6b8151ed 100644 --- a/.github/workflows/validate_IJ_versions.yml +++ b/.github/workflows/validate_IJ_versions.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - IJ: [ IU-2021.2, IU-2021.3, IU-2022.1, IU-2022.2, IU-2022.3, IU-2023.1, IU-2023.2 ] + IJ: [ IU-2022.1, IU-2022.2, IU-2022.3, IU-2023.1, IU-2023.2 ] steps: - name: Checkout Code diff --git a/build.gradle b/build.gradle index 5eea41d57..be1ad931d 100644 --- a/build.gradle +++ b/build.gradle @@ -54,7 +54,7 @@ intellij { 'com.intellij.css', 'yaml', 'com.redhat.devtools.intellij.telemetry:1.0.0.44', - 'com.redhat.devtools.intellij.kubernetes:0.8.0.220' + 'com.redhat.devtools.intellij.kubernetes:1.2.0.271' ] updateSinceUntilBuild = false } @@ -106,6 +106,7 @@ tasks.register('integrationTest', Test) { testClassesDirs = sourceSets.integrationTest.output.classesDirs classpath = sourceSets.integrationTest.runtimeClasspath outputs.upToDateWhen { false } + jvmArgs "-Djava.awt.headless=true" testlogger { showStandardStreams true showPassedStandardStreams false diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java index 73e8a32f3..4e877b998 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java @@ -26,21 +26,27 @@ import com.intellij.util.messages.MessageBusConnection; import com.redhat.devtools.intellij.common.kubernetes.ClusterHelper; import com.redhat.devtools.intellij.common.kubernetes.ClusterInfo; +import com.redhat.devtools.intellij.common.utils.ConfigHelper; import com.redhat.devtools.intellij.common.utils.ExecHelper; import com.redhat.devtools.intellij.common.utils.NetworkUtils; +import com.redhat.devtools.intellij.kubernetes.model.client.ssl.IDEATrustManager; import com.redhat.devtools.intellij.telemetry.core.configuration.TelemetryConfiguration; import com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder; +import io.fabric8.kubernetes.api.Pluralize; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.DeletionPropagation; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.api.model.Namespace; +import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.VersionInfo; import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; +import io.fabric8.kubernetes.client.http.HttpClient; import io.fabric8.kubernetes.client.http.HttpRequest; import io.fabric8.kubernetes.client.http.HttpResponse; +import io.fabric8.kubernetes.client.internal.SSLUtils; import io.fabric8.kubernetes.model.Scope; import io.fabric8.openshift.api.model.Project; import io.fabric8.openshift.client.OpenShiftClient; @@ -56,6 +62,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -64,6 +73,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -116,7 +130,6 @@ public class OdoCli implements Odo { private final AtomicBoolean swaggerLoaded = new AtomicBoolean(); private JSonParser swagger; - /* Map of process launched for feature (dev, debug,...) related. Key is component name @@ -135,7 +148,10 @@ public OdoCli(com.intellij.openapi.project.Project project, String command) { this.command = command; this.project = project; this.connection = ApplicationManager.getApplication().getMessageBus().connect(); - this.client = new KubernetesClientBuilder().build(); + String context = ConfigHelper.getCurrentContext().getName(); + Config config = Config.autoConfigure(context); + + this.client = new KubernetesClientBuilder().withConfig(config).withHttpClientBuilderConsumer(builder -> setSslContext(builder, config)).build(); try { this.envVars = NetworkUtils.buildEnvironmentVariables(this.getMasterUrl().toString()); computeTelemetrySettings(); @@ -156,6 +172,17 @@ private TelemetryConfiguration.ConfigurationChangedListener onTelemetryConfigura }; } + private void setSslContext(HttpClient.Builder builder, Config config) { + try { + List clientTrustManagers = Arrays.stream(SSLUtils.trustManagers(config)).filter(X509ExtendedTrustManager.class::isInstance).map(X509ExtendedTrustManager.class::cast).collect(Collectors.toList()); + X509TrustManager externalTrustManager = new IDEATrustManager().configure(clientTrustManagers.toArray(new X509ExtendedTrustManager[0])); + builder.sslContext(SSLUtils.keyManagers(config), List.of(externalTrustManager).toArray(new TrustManager[0])); + } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | + UnrecoverableKeyException | InvalidKeySpecException e) { + throw new RuntimeException(e); + } + } + private void computeTelemetrySettings() { if (TelemetryConfiguration.getInstance().isEnabled()) { this.envVars.put("ODO_TRACKING_CONSENT", "yes"); @@ -188,7 +215,6 @@ private void reportTelemetry() { } } - private ObjectMapper configureObjectMapper(final StdNodeBasedDeserializer> deserializer) { final SimpleModule module = new SimpleModule(); module.addDeserializer(List.class, deserializer); @@ -395,7 +421,7 @@ private CustomResourceDefinitionContext toCustomResourceDefinitionContext(org.jb .withGroup(group) .withScope(Scope.NAMESPACED.value()) .withKind(service.getKind()) - .withPlural(service.getKind().toLowerCase() + "s") + .withPlural(Pluralize.toPlural(service.getKind().toLowerCase())) .withVersion(version) .build(); } @@ -631,7 +657,7 @@ private void doLog(String context, String component, boolean follow, boolean dep if (follow) { args.add("--follow"); } - if (StringUtils.isNotBlank(platform)){ + if (StringUtils.isNotBlank(platform)) { args.add("--platform"); args.add(platform); } @@ -682,12 +708,12 @@ private File createWorkingDirectory(String context) { @Override public void createProject(String project) throws IOException { - execute(command, envVars, "create", "namespace", project, "-w"); + execute(command, envVars, "create", NAMESPACE_FIELD, project, "-w"); } @Override public void deleteProject(String project) throws IOException { - execute(command, envVars, "delete", "namespace", project, "-f", "-w"); + execute(command, envVars, "delete", NAMESPACE_FIELD, project, "-f", "-w"); if (project.equals(namespace)) { namespace = null; } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 53c3ba6bb..d87d8551a 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -219,7 +219,7 @@ - +