diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisioner.java index b3e2f83b7d9..c95d409cfec 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisioner.java @@ -11,6 +11,8 @@ */ package org.eclipse.che.workspace.infrastructure.kubernetes.provision; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_POD_NAME; + import io.fabric8.kubernetes.api.model.EnvVar; import java.util.HashMap; import java.util.Map; @@ -21,7 +23,6 @@ import org.eclipse.che.commons.annotation.Traced; import org.eclipse.che.commons.tracing.TracingTags; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; -import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData; /** * Add proxy configuration to pod containers @@ -29,9 +30,9 @@ * @author Mykhailo Kuznietsov */ public class ProxySettingsProvisioner implements ConfigurationProvisioner { - private static final String HTTPS_PROXY = "https_proxy"; - private static final String HTTP_PROXY = "http_proxy"; - private static final String NO_PROXY = "no_proxy"; + static final String HTTPS_PROXY = "https_proxy"; + static final String HTTP_PROXY = "http_proxy"; + static final String NO_PROXY = "no_proxy"; private final Map proxyEnvVars; @@ -60,13 +61,17 @@ public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) TracingTags.WORKSPACE_ID.set(identity::getWorkspaceId); if (!proxyEnvVars.isEmpty()) { - for (PodData pod : k8sEnv.getPodsData().values()) { - pod.getSpec() - .getContainers() - .forEach( - container -> - proxyEnvVars.forEach((k, v) -> container.getEnv().add(new EnvVar(k, v, null)))); - } + k8sEnv + .getPodsData() + .entrySet() + .stream() + // JWTProxy container doesn't need proxy settings since it never does any outbound + // requests, and setting of it may fail accessing internal addresses. + .filter(entry -> !entry.getKey().equals(JWT_PROXY_POD_NAME)) + .flatMap(entry -> entry.getValue().getSpec().getContainers().stream()) + .forEach( + container -> + proxyEnvVars.forEach((k, v) -> container.getEnv().add(new EnvVar(k, v, null)))); } } } diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java index d70cb4a1c07..ec64a009089 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java @@ -91,11 +91,12 @@ public class JwtProxyProvisioner { static final String JWT_PROXY_CONFIG_FILE = "config.yaml"; static final String JWT_PROXY_MACHINE_NAME = "che-jwtproxy"; - static final String JWT_PROXY_POD_NAME = JWT_PROXY_MACHINE_NAME; static final String JWT_PROXY_CONFIG_FOLDER = "/config"; static final String JWT_PROXY_PUBLIC_KEY_FILE = "mykey.pub"; + public static final String JWT_PROXY_POD_NAME = JWT_PROXY_MACHINE_NAME; + private final SignatureKeyManager signatureKeyManager; private final RuntimeIdentity identity; diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisionerTest.java new file mode 100644 index 00000000000..ce38a373b2b --- /dev/null +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ProxySettingsProvisionerTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.provision; + +import static org.eclipse.che.commons.lang.NameGenerator.generate; +import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.ProxySettingsProvisioner.HTTPS_PROXY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.ProxySettingsProvisioner.HTTP_PROXY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.provision.ProxySettingsProvisioner.NO_PROXY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_POD_NAME; +import static org.mockito.Mockito.lenient; +import static org.testng.Assert.assertTrue; + +import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.ContainerBuilder; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.PodBuilder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +@Listeners(MockitoTestNGListener.class) +public class ProxySettingsProvisionerTest { + + private static final String WORKSPACE_ID = "workspace123"; + + private static final String HTTP_PROXY_VALUE = "http.proxy1.somewhere.com:3128"; + private static final String HTTPS_PROXY_VALUE = "https.proxy2.somewhere.com:8080"; + private static final String NO_PROXY_VALUE = "localhost,127.0.0.1"; + + @Mock private RuntimeIdentity runtimeId; + + private ProxySettingsProvisioner provisioner; + + @BeforeMethod + public void setUp() { + lenient().when(runtimeId.getWorkspaceId()).thenReturn(WORKSPACE_ID); + provisioner = new ProxySettingsProvisioner(HTTPS_PROXY_VALUE, HTTP_PROXY_VALUE, NO_PROXY_VALUE); + } + + @Test + public void shouldApplyProxySettingsToAllContainers() throws Exception { + + Map pods = new HashMap<>(); + pods.put("pod1", buildPod("pod1", buildContainers(2))); + pods.put("pod2", buildPod("pod2", buildContainers(3))); + + KubernetesEnvironment k8sEnv = KubernetesEnvironment.builder().setPods(pods).build(); + provisioner.provision(k8sEnv, runtimeId); + + assertTrue( + k8sEnv + .getPodsData() + .values() + .stream() + .flatMap(pod -> pod.getSpec().getContainers().stream()) + .allMatch( + container -> + container.getEnv().contains(new EnvVar(HTTP_PROXY, HTTP_PROXY_VALUE, null)) + && container + .getEnv() + .contains(new EnvVar(HTTPS_PROXY, HTTPS_PROXY_VALUE, null)) + && container + .getEnv() + .contains(new EnvVar(NO_PROXY, NO_PROXY_VALUE, null)))); + } + + @Test + public void shouldNotApplyProxySettingsToJWTProxyContainer() throws Exception { + + Map pods = new HashMap<>(); + pods.put(JWT_PROXY_POD_NAME, buildPod(JWT_PROXY_POD_NAME, buildContainers(2))); + + KubernetesEnvironment k8sEnv = KubernetesEnvironment.builder().setPods(pods).build(); + provisioner.provision(k8sEnv, runtimeId); + + assertTrue( + k8sEnv + .getPodsData() + .values() + .stream() + .filter(pod -> pod.getMetadata().getName().equals(JWT_PROXY_POD_NAME)) + .flatMap(pod -> pod.getSpec().getContainers().stream()) + .noneMatch( + container -> + container.getEnv().contains(new EnvVar(HTTP_PROXY, HTTP_PROXY_VALUE, null)) + || container + .getEnv() + .contains(new EnvVar(HTTPS_PROXY, HTTPS_PROXY_VALUE, null)) + || container + .getEnv() + .contains(new EnvVar(NO_PROXY, NO_PROXY_VALUE, null)))); + } + + private Pod buildPod(String podName, Container... containers) { + return new PodBuilder() + .withNewMetadata() + .withName(podName) + .endMetadata() + .withNewSpec() + .withContainers(containers) + .endSpec() + .build(); + } + + private Container[] buildContainers(int size) { + List result = new ArrayList<>(); + for (int i = 0; i < size; i++) { + result.add( + new ContainerBuilder() + .withName(generate("container-", 4)) + .withNewResources() + .endResources() + .build()); + } + return result.toArray(new Container[size]); + } +}