secureServers) {
+ exposerStrategy.expose(k8sEnv, machineName, serviceName, servicePort, secureServers);
+ }
+ }
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposer.java
new file mode 100644
index 00000000000..67b1ce058d5
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure;
+
+import io.fabric8.kubernetes.api.model.ServicePort;
+import java.util.Map;
+import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
+import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+
+/**
+ * Modifies the specified Kubernetes environment to expose secure servers.
+ *
+ * Note that ONE {@link SecureServerExposer} instance should be used for one workspace start.
+ *
+ * @author Sergii Leshchenko
+ */
+public interface SecureServerExposer {
+
+ /**
+ * Modifies the specified Kubernetes environment to expose secure servers.
+ *
+ * @param k8sEnv Kubernetes environment that should be modified.
+ * @param machineName machine name to which secure servers belong to
+ * @param serviceName service name that exposes secure servers
+ * @param servicePort service port that exposes secure servers
+ * @param secureServers secure servers to expose
+ * @throws InfrastructureException when any exception occurs during servers exposing
+ */
+ void expose(
+ T k8sEnv,
+ String machineName,
+ String serviceName,
+ ServicePort servicePort,
+ Map secureServers)
+ throws InfrastructureException;
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactory.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactory.java
new file mode 100644
index 00000000000..72e2eee9738
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactory.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure;
+
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+
+/**
+ * Helps to create {@link SecureServerExposer} instances.
+ *
+ * Note that ONE {@link SecureServerExposer} instance should be used for one workspace start.
+ *
+ * @author Sergii Leshchenko
+ */
+public interface SecureServerExposerFactory {
+ SecureServerExposer create(RuntimeIdentity runtimeId);
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProvider.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProvider.java
new file mode 100644
index 00000000000..a50796d304f
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure;
+
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import org.eclipse.che.inject.ConfigurationException;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+
+/** @author Sergii Leshchenko */
+public class SecureServerExposerFactoryProvider
+ implements Provider> {
+
+ private final boolean agentsAuthEnabled;
+ private final String serverExposer;
+
+ private final DefaultSecureServersFactory defaultSecureServersFactory;
+ private final Map> factories;
+
+ @Inject
+ public SecureServerExposerFactoryProvider(
+ @Named("che.agents.auth_enabled") boolean agentsAuthEnabled,
+ @Named("che.server.secure_exposer") String serverExposer,
+ DefaultSecureServersFactory defaultSecureServersFactory,
+ Map> factories) {
+ this.agentsAuthEnabled = agentsAuthEnabled;
+ this.serverExposer = serverExposer;
+ this.defaultSecureServersFactory = defaultSecureServersFactory;
+ this.factories = factories;
+ }
+
+ /**
+ * Creates instance of {@link SecureServerExposerFactory} that will expose secure servers for
+ * runtime with the specified runtime identity.
+ */
+ @Override
+ public SecureServerExposerFactory get() {
+ if (!agentsAuthEnabled) {
+ // return default secure server exposer because no need to protect servers with authentication
+ return defaultSecureServersFactory;
+ }
+
+ SecureServerExposerFactory serverExposerFactory = factories.get(serverExposer);
+ if (serverExposerFactory == null) {
+ throw new ConfigurationException(
+ "Unknown secure servers exposer is configured '" + serverExposer + "'. ");
+ }
+
+ return serverExposerFactory;
+ }
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilder.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilder.java
new file mode 100644
index 00000000000..d580bd88de3
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_CONFIG_FOLDER;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_PUBLIC_KEY_FILE;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helps to build JWTProxy config with several verifier proxies.
+ *
+ * @author Sergii Leshchenko
+ */
+public class JwtProxyConfigBuilder {
+ private final List verifierProxies = new ArrayList<>();
+ private final String workspaceId;
+
+ public JwtProxyConfigBuilder(String workspaceId) {
+ this.workspaceId = workspaceId;
+ }
+
+ public void addVerifierProxy(Integer listenPort, String upstream) {
+ verifierProxies.add(new VerifierProxy(listenPort, upstream));
+ }
+
+ public String build() {
+ StringBuilder configBuilder = new StringBuilder();
+
+ configBuilder.append("jwtproxy:\n" + " verifier_proxies:\n");
+ for (VerifierProxy verifierProxy : verifierProxies) {
+ configBuilder.append(
+ String.format(
+ " - listen_addr: :%s\n" // :4471
+ + " verifier:\n"
+ + " upstream: %s/\n" // http://localhost:4401
+ + " audience: http://%s\n"
+ + " max_skew: 1m\n"
+ + " max_ttl: 3h\n"
+ + " key_server:\n"
+ + " type: preshared\n"
+ + " options:\n"
+ + " issuer: wsmaster\n"
+ + " key_id: mykey\n"
+ + " public_key_path: "
+ + JWT_PROXY_CONFIG_FOLDER
+ + "/"
+ + JWT_PROXY_PUBLIC_KEY_FILE
+ + "\n"
+ + " claims_verifiers:\n"
+ + " - type: static\n"
+ + " options:\n"
+ + " iss: wsmaster\n"
+ + " nonce_storage:\n"
+ + " type: void\n",
+ verifierProxy.listenPort,
+ verifierProxy.upstream,
+ workspaceId));
+ }
+ configBuilder.append(" signer_proxy:\n" + " enabled: false\n");
+ return configBuilder.toString();
+ }
+
+ private class VerifierProxy {
+ private Integer listenPort;
+ private String upstream;
+
+ VerifierProxy(Integer listenPort, String upstream) {
+ this.listenPort = listenPort;
+ this.upstream = upstream;
+ }
+ }
+}
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
new file mode 100644
index 00000000000..3a4f5e9b7d0
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisioner.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
+import static org.eclipse.che.commons.lang.NameGenerator.generate;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.CHE_ORIGINAL_NAME_LABEL;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_PREFIX;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_UNIQUE_PART_SIZE;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
+import io.fabric8.kubernetes.api.model.ContainerBuilder;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodBuilder;
+import io.fabric8.kubernetes.api.model.Service;
+import io.fabric8.kubernetes.api.model.ServicePort;
+import io.fabric8.kubernetes.api.model.ServicePortBuilder;
+import io.fabric8.kubernetes.api.model.VolumeBuilder;
+import io.fabric8.kubernetes.api.model.VolumeMount;
+import java.security.KeyPair;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
+import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
+import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.ServerServiceBuilder;
+
+/**
+ * Modifies Kubernetes environment to expose the specified service port via JWTProxy.
+ *
+ * Exposing includes the following operation:
+ *
+ *
+ * - Putting Machine configuration into Kubernetes environment if absent;
+ *
- Putting JwtProxy pod with one container if absent;
+ *
- Putting JwtProxy service that will expose added JWTProxy pod if absent;
+ *
- Putting JwtProxy ConfigMap that contains public key and jwtproxy config in yaml format if
+ * absent;
+ *
- Updating JwtProxy Service to expose port for secure server;
+ *
- Updating jwtproxy configuration in config map by adding the corresponding verifier proxy
+ * there;
+ *
+ *
+ * @see JwtProxyConfigBuilder
+ * @see SignatureKeyManager
+ * @author Sergii Leshchenko
+ */
+public class JwtProxyProvisioner {
+
+ static final int FIRST_AVAILABLE_PORT = 4400;
+
+ static final int JWT_PROXY_MEMORY_LIMIT_BYTES = 128 * 1024 * 1024; // 128mb
+
+ static final String PUBLIC_KEY_HEADER = "-----BEGIN PUBLIC KEY-----\n";
+ static final String PUBLIC_KEY_FOOTER = "\n-----END PUBLIC KEY-----";
+
+ static final String JWTPROXY_IMAGE = "ksmster/jwtproxy";
+ 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";
+
+ private final SignatureKeyManager signatureKeyManager;
+
+ private final RuntimeIdentity identity;
+
+ private final JwtProxyConfigBuilder proxyConfigBuilder;
+
+ private final String serviceName;
+ private int availablePort;
+
+ public JwtProxyProvisioner(RuntimeIdentity identity, SignatureKeyManager signatureKeyManager) {
+ this.signatureKeyManager = signatureKeyManager;
+
+ this.identity = identity;
+
+ this.proxyConfigBuilder = new JwtProxyConfigBuilder(identity.getWorkspaceId());
+
+ this.serviceName = generate(SERVER_PREFIX, SERVER_UNIQUE_PART_SIZE) + "-jwtproxy";
+ this.availablePort = FIRST_AVAILABLE_PORT;
+ }
+
+ /**
+ * Modifies Kubernetes environment to expose the specified service port via JWTProxy.
+ *
+ * @param k8sEnv Kubernetes environment to modify
+ * @param backendServiceName service name that will be exposed
+ * @param backendServicePort service port that will be exposed
+ * @param protocol protocol that will be used for exposed port
+ * @return JWTProxy service port that expose the specified one
+ * @throws InfrastructureException if any exception occurs during port exposing
+ */
+ public ServicePort expose(
+ KubernetesEnvironment k8sEnv,
+ String backendServiceName,
+ int backendServicePort,
+ String protocol)
+ throws InfrastructureException {
+ ensureJwtProxyInjected(k8sEnv);
+
+ int listenPort = availablePort++;
+
+ proxyConfigBuilder.addVerifierProxy(
+ listenPort, "http://" + backendServiceName + ":" + backendServicePort);
+ k8sEnv
+ .getConfigMaps()
+ .get(getConfigMapName())
+ .getData()
+ .put(JWT_PROXY_CONFIG_FILE, proxyConfigBuilder.build());
+
+ ServicePort exposedPort =
+ new ServicePortBuilder()
+ .withName("server-" + listenPort)
+ .withPort(listenPort)
+ .withProtocol(protocol)
+ .withNewTargetPort(listenPort)
+ .build();
+
+ k8sEnv.getServices().get(getServiceName()).getSpec().getPorts().add(exposedPort);
+
+ return exposedPort;
+ }
+
+ /** Returns service name that exposed JWTProxy Pod. */
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ /** Returns config map name that will be mounted into JWTProxy Pod. */
+ @VisibleForTesting
+ String getConfigMapName() {
+ return "jwtproxy-config-" + identity.getWorkspaceId();
+ }
+
+ private void ensureJwtProxyInjected(KubernetesEnvironment k8sEnv) throws InfrastructureException {
+ if (!k8sEnv.getMachines().containsKey(JWT_PROXY_MACHINE_NAME)) {
+ k8sEnv.getMachines().put(JWT_PROXY_MACHINE_NAME, createJwtProxyMachine());
+ k8sEnv.getPods().put(JWT_PROXY_POD_NAME, createJwtProxyPod(identity));
+
+ KeyPair keyPair = signatureKeyManager.getKeyPair();
+ if (keyPair == null) {
+ throw new InternalInfrastructureException(
+ "Key pair for machine authentication does not exist");
+ }
+ Map initConfigMapData = new HashMap<>();
+ initConfigMapData.put(
+ JWT_PROXY_PUBLIC_KEY_FILE,
+ PUBLIC_KEY_HEADER
+ + java.util.Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded())
+ + PUBLIC_KEY_FOOTER);
+
+ initConfigMapData.put(JWT_PROXY_CONFIG_FILE, proxyConfigBuilder.build());
+
+ ConfigMap jwtProxyConfigMap =
+ new ConfigMapBuilder()
+ .withNewMetadata()
+ .withName(getConfigMapName())
+ .endMetadata()
+ .withData(initConfigMapData)
+ .build();
+ k8sEnv.getConfigMaps().put(jwtProxyConfigMap.getMetadata().getName(), jwtProxyConfigMap);
+
+ Service jwtProxyService =
+ new ServerServiceBuilder()
+ .withName(serviceName)
+ .withSelectorEntry(CHE_ORIGINAL_NAME_LABEL, JWT_PROXY_MACHINE_NAME)
+ .withMachineName(JWT_PROXY_MACHINE_NAME)
+ .withPorts(emptyList())
+ .build();
+ k8sEnv.getServices().put(jwtProxyService.getMetadata().getName(), jwtProxyService);
+ }
+ }
+
+ private InternalMachineConfig createJwtProxyMachine() {
+ return new InternalMachineConfig(
+ null,
+ emptyMap(),
+ emptyMap(),
+ ImmutableMap.of(
+ MachineConfig.MEMORY_LIMIT_ATTRIBUTE, Integer.toString(JWT_PROXY_MEMORY_LIMIT_BYTES)),
+ null);
+ }
+
+ private Pod createJwtProxyPod(RuntimeIdentity identity) {
+ return new PodBuilder()
+ .withNewMetadata()
+ .withName(JWT_PROXY_POD_NAME)
+ .withAnnotations(
+ ImmutableMap.of(
+ "org.eclipse.che.container.verifier.machine_name", JWT_PROXY_MACHINE_NAME))
+ .endMetadata()
+ .withNewSpec()
+ .withContainers(
+ new ContainerBuilder()
+ .withName("verifier")
+ .withImage(JWTPROXY_IMAGE)
+ .withVolumeMounts(
+ new VolumeMount(
+ JWT_PROXY_CONFIG_FOLDER + "/", "jwtproxy-config-volume", false, null))
+ .withArgs("-config", JWT_PROXY_CONFIG_FOLDER + "/" + JWT_PROXY_CONFIG_FILE)
+ .build())
+ .withVolumes(
+ new VolumeBuilder()
+ .withName("jwtproxy-config-volume")
+ .withNewConfigMap()
+ .withName("jwtproxy-config-" + identity.getWorkspaceId())
+ .endConfigMap()
+ .build())
+ .endSpec()
+ .build();
+ }
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposer.java
new file mode 100644
index 00000000000..3c7aa75d798
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposer.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.inject.assistedinject.Assisted;
+import io.fabric8.kubernetes.api.model.ServicePort;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
+import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
+
+/**
+ * Exposes secure servers with JWTProxy.
+ *
+ * To expose secure servers it provisions JwtProxy objects into environment with {@link
+ * JwtProxyProvisioner}. Then JwtProxy service port is made public accessible by {@link
+ * ExternalServerExposerStrategy}.
+ *
+ * In this way, requests to exposed secure servers will be routed via JwtProxy pod that is added
+ * one per workspace. And it will be impossible to requests secure servers if there is no machine
+ * token in request.
+ *
+ * @see JwtProxyProvisioner
+ * @author Sergii Leshchenko
+ */
+public class JwtProxySecureServerExposer
+ implements SecureServerExposer {
+
+ private final ExternalServerExposerStrategy exposerStrategy;
+ private final JwtProxyProvisioner proxyProvisioner;
+
+ @VisibleForTesting
+ JwtProxySecureServerExposer(
+ JwtProxyProvisioner jwtProxyProvisioner, ExternalServerExposerStrategy exposerStrategy) {
+ this.exposerStrategy = exposerStrategy;
+ this.proxyProvisioner = jwtProxyProvisioner;
+ }
+
+ @Inject
+ public JwtProxySecureServerExposer(
+ @Assisted RuntimeIdentity identity,
+ SignatureKeyManager signatureKeyManager,
+ ExternalServerExposerStrategy exposerStrategy) {
+ this.exposerStrategy = exposerStrategy;
+
+ proxyProvisioner = new JwtProxyProvisioner(identity, signatureKeyManager);
+ }
+
+ @Override
+ public void expose(
+ T k8sEnv,
+ String machineName,
+ String serviceName,
+ ServicePort servicePort,
+ Map secureServers)
+ throws InfrastructureException {
+ ServicePort exposedServicePort =
+ proxyProvisioner.expose(
+ k8sEnv,
+ serviceName,
+ servicePort.getTargetPort().getIntVal(),
+ servicePort.getProtocol());
+
+ exposerStrategy.expose(
+ k8sEnv, machineName, proxyProvisioner.getServiceName(), exposedServicePort, secureServers);
+ }
+}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerFactory.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerFactory.java
new file mode 100644
index 00000000000..47d45ac15ac
--- /dev/null
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactory;
+
+/**
+ * Helps to create {@link JwtProxySecureServerExposerFactory} with fields injected from DI
+ * container.
+ *
+ * @author Sergii Leshchenko
+ */
+public interface JwtProxySecureServerExposerFactory
+ extends SecureServerExposerFactory {
+ @Override
+ JwtProxySecureServerExposer create(RuntimeIdentity identity);
+}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
index eb049a85fa9..f85428cfcc1 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
@@ -41,6 +41,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
@@ -109,6 +110,7 @@
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesServerImpl;
+import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesDeployments;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesIngresses;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespace;
@@ -172,6 +174,7 @@ public class KubernetesInternalRuntimeTest {
@Mock private KubernetesServices services;
@Mock private KubernetesIngresses ingresses;
@Mock private KubernetesSecrets secrets;
+ @Mock private KubernetesConfigsMaps configMaps;
@Mock private KubernetesDeployments deployments;
@Mock private KubernetesBootstrapper bootstrapper;
@Mock private WorkspaceVolumesStrategy volumesStrategy;
@@ -256,6 +259,7 @@ public void setup() throws Exception {
when(namespace.ingresses()).thenReturn(ingresses);
when(namespace.deployments()).thenReturn(deployments);
when(namespace.secrets()).thenReturn(secrets);
+ when(namespace.configMaps()).thenReturn(configMaps);
when(bootstrapperFactory.create(any(), anyList(), any(), any(), any()))
.thenReturn(bootstrapper);
doReturn(
@@ -288,12 +292,15 @@ public void setup() throws Exception {
@Test
public void startsKubernetesEnvironment() throws Exception {
when(k8sEnv.getSecrets()).thenReturn(ImmutableMap.of("secret", new Secret()));
+ when(k8sEnv.getConfigMaps()).thenReturn(ImmutableMap.of("configMap", new ConfigMap()));
+
internalRuntime.internalStart(emptyMap());
verify(deployments).deploy(any());
verify(ingresses).create(any());
verify(services).create(any());
verify(secrets).create(any());
+ verify(configMaps).create(any());
verify(namespace.deployments(), times(2)).watchEvents(any());
verify(bootstrapper, times(2)).bootstrapAsync();
verify(eventService, times(4)).publish(any());
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactoryTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactoryTest.java
index 3e2576cd163..f0597212ff5 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactoryTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactoryTest.java
@@ -18,6 +18,8 @@
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.MACHINE_NAME_ANNOTATION_FMT;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory.CONFIG_MAP_IGNORED_WARNING_CODE;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory.CONFIG_MAP_IGNORED_WARNING_MESSAGE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory.INGRESSES_IGNORED_WARNING_CODE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory.INGRESSES_IGNORED_WARNING_MESSAGE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory.PVC_IGNORED_WARNING_CODE;
@@ -33,6 +35,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.DoneableKubernetesList;
import io.fabric8.kubernetes.api.model.HasMetadata;
@@ -150,13 +153,28 @@ public void ignoreSecretsWhenRecipeContainsThem() throws Exception {
final KubernetesEnvironment parsed =
k8sEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
- assertTrue(parsed.getPersistentVolumeClaims().isEmpty());
+ assertTrue(parsed.getSecrets().isEmpty());
assertEquals(parsed.getWarnings().size(), 1);
assertEquals(
parsed.getWarnings().get(0),
new WarningImpl(SECRET_IGNORED_WARNING_CODE, SECRET_IGNORED_WARNING_MESSAGE));
}
+ @Test
+ public void ignoreConfigMapsWhenRecipeContainsThem() throws Exception {
+ final List recipeObjects = singletonList(new ConfigMap());
+ when(validatedObjects.getItems()).thenReturn(recipeObjects);
+
+ final KubernetesEnvironment parsed =
+ k8sEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
+
+ assertTrue(parsed.getConfigMaps().isEmpty());
+ assertEquals(parsed.getWarnings().size(), 1);
+ assertEquals(
+ parsed.getWarnings().get(0),
+ new WarningImpl(CONFIG_MAP_IGNORED_WARNING_CODE, CONFIG_MAP_IGNORED_WARNING_MESSAGE));
+ }
+
@Test
public void testSetsRamLimitAttributeFromKubernetesResource() throws Exception {
final long firstMachineRamLimit = 3072;
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceTest.java
index 6336717f621..c6c80ad9f83 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/namespace/KubernetesNamespaceTest.java
@@ -68,6 +68,7 @@ public class KubernetesNamespaceTest {
@Mock private KubernetesIngresses ingresses;
@Mock private KubernetesPersistentVolumeClaims pvcs;
@Mock private KubernetesSecrets secrets;
+ @Mock private KubernetesConfigsMaps configMaps;
@Mock private KubernetesClientFactory clientFactory;
@Mock private KubernetesClient kubernetesClient;
@Mock private NonNamespaceOperation namespaceOperation;
@@ -125,7 +126,8 @@ public void setUp() throws Exception {
services,
pvcs,
ingresses,
- secrets);
+ secrets,
+ configMaps);
}
@Test
@@ -163,6 +165,7 @@ public void testKubernetesNamespaceCleaningUp() throws Exception {
verify(services).delete();
verify(deployments).delete();
verify(secrets).delete();
+ verify(configMaps).delete();
}
@Test
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java
index 9fcefa3f9fb..a68b79558d6 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java
@@ -37,6 +37,7 @@
import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
@@ -52,11 +53,15 @@
public class KubernetesServerExposerTest {
@Mock private ExternalServerExposerStrategy externalServerExposerStrategy;
+ @Mock private SecureServerExposer secureServerExposer;
private static final Map ATTRIBUTES_MAP = singletonMap("key", "value");
private static final Map INTERNAL_SERVER_ATTRIBUTE_MAP =
singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, Boolean.TRUE.toString());
+ private static final Map SECURE_SERVER_ATTRIBUTE_MAP =
+ singletonMap(ServerConfig.SECURE_SERVER_ATTRIBUTE, Boolean.TRUE.toString());
+
private static final Pattern SERVER_PREFIX_REGEX =
Pattern.compile('^' + SERVER_PREFIX + "[A-z0-9]{" + SERVER_UNIQUE_PART_SIZE + "}-pod-main$");
private static final String MACHINE_NAME = "pod/main";
@@ -82,7 +87,12 @@ public void setUp() throws Exception {
KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build();
this.serverExposer =
new KubernetesServerExposer<>(
- externalServerExposerStrategy, MACHINE_NAME, pod, container, kubernetesEnvironment);
+ externalServerExposerStrategy,
+ secureServerExposer,
+ MACHINE_NAME,
+ pod,
+ container,
+ kubernetesEnvironment);
}
@Test
@@ -270,33 +280,36 @@ public void shouldExposeContainerPortAndCreateServiceForInternalServer() throws
}
@Test
- public void shouldExposeInternalAndExternalServers() throws Exception {
+ public void shouldExposeInternalAndExternalAndSecureServers() throws Exception {
// given
+ ServerConfigImpl secureServerConfig =
+ new ServerConfigImpl("8282/tcp", "http", "/api", SECURE_SERVER_ATTRIBUTE_MAP);
ServerConfigImpl internalServerConfig =
new ServerConfigImpl("8080/tcp", "http", "/api", INTERNAL_SERVER_ATTRIBUTE_MAP);
ServerConfigImpl externalServerConfig =
new ServerConfigImpl("9090/tcp", "http", "/api", ATTRIBUTES_MAP);
Map serversToExpose =
- ImmutableMap.of("int-server", internalServerConfig, "ext-server", externalServerConfig);
+ ImmutableMap.of(
+ "int-server",
+ internalServerConfig,
+ "ext-server",
+ externalServerConfig,
+ "secure-server",
+ secureServerConfig);
// when
serverExposer.expose(serversToExpose);
// then
assertThatInternalServerIsExposed(
- MACHINE_NAME,
- "int-server",
- "tcp",
- 8080,
- new ServerConfigImpl(internalServerConfig).withAttributes(INTERNAL_SERVER_ATTRIBUTE_MAP));
+ MACHINE_NAME, "int-server", "tcp", 8080, new ServerConfigImpl(internalServerConfig));
assertThatExternalServerIsExposed(
- MACHINE_NAME,
- "tcp",
- 9090,
- "ext-server",
- new ServerConfigImpl(externalServerConfig).withAttributes(ATTRIBUTES_MAP));
+ MACHINE_NAME, "tcp", 9090, "ext-server", new ServerConfigImpl(externalServerConfig));
+ assertThatSecureServerIsExposed(
+ MACHINE_NAME, "tcp", 8282, "secure-server", new ServerConfigImpl(secureServerConfig));
}
+ @SuppressWarnings("SameParameterValue")
private void assertThatExternalServerIsExposed(
String machineName,
String portProtocol,
@@ -314,38 +327,14 @@ private void assertThatExternalServersAreExposed(
Integer port,
Map expectedServers) {
// then
- assertTrue(
- container
- .getPorts()
- .stream()
- .anyMatch(
- p ->
- p.getContainerPort().equals(port)
- && p.getProtocol().equals(portProtocol.toUpperCase())));
+ assertThatContainerPortIsExposed(portProtocol, port);
// ensure that service is created
- Service service = null;
- for (Entry entry : kubernetesEnvironment.getServices().entrySet()) {
- if (SERVER_PREFIX_REGEX.matcher(entry.getKey()).matches()) {
- service = entry.getValue();
- break;
- }
- }
+ Service service = findContainerRelatedService();
assertNotNull(service);
// ensure that required service port is exposed
- Optional servicePortOpt =
- service
- .getSpec()
- .getPorts()
- .stream()
- .filter(p -> p.getTargetPort().getIntVal().equals(port))
- .findAny();
- assertTrue(servicePortOpt.isPresent());
- ServicePort servicePort = servicePortOpt.get();
- assertEquals(servicePort.getTargetPort().getIntVal(), port);
- assertEquals(servicePort.getPort(), port);
- assertEquals(servicePort.getName(), SERVER_PREFIX + "-" + port);
+ ServicePort servicePort = assertThatServicePortIsExposed(port, service);
Annotations.Deserializer serviceAnnotations =
Annotations.newDeserializer(service.getMetadata().getAnnotations());
@@ -360,6 +349,37 @@ private void assertThatExternalServersAreExposed(
expectedServers);
}
+ @SuppressWarnings("SameParameterValue")
+ private void assertThatSecureServerIsExposed(
+ String machineName,
+ String portProtocol,
+ Integer port,
+ String serverName,
+ ServerConfig serverConfig)
+ throws Exception {
+ // then
+ assertThatContainerPortIsExposed(portProtocol, port);
+ // ensure that service is created
+
+ Service service = findContainerRelatedService();
+ assertNotNull(service);
+
+ // ensure that required service port is exposed
+ ServicePort servicePort = assertThatServicePortIsExposed(port, service);
+
+ Annotations.Deserializer serviceAnnotations =
+ Annotations.newDeserializer(service.getMetadata().getAnnotations());
+ assertEquals(serviceAnnotations.machineName(), machineName);
+
+ verify(secureServerExposer)
+ .expose(
+ kubernetesEnvironment,
+ machineName,
+ service.getMetadata().getName(),
+ servicePort,
+ ImmutableMap.of(serverName, serverConfig));
+ }
+
@SuppressWarnings("SameParameterValue")
private void assertThatInternalServerIsExposed(
String machineName,
@@ -367,7 +387,26 @@ private void assertThatInternalServerIsExposed(
String portProtocol,
Integer port,
ServerConfigImpl expected) {
- // then
+ assertThatContainerPortIsExposed(portProtocol, port);
+
+ // ensure that service is created
+
+ Service service = findContainerRelatedService();
+ assertNotNull(service);
+
+ // ensure that required service port is exposed
+ assertThatServicePortIsExposed(port, service);
+
+ Annotations.Deserializer serviceAnnotations =
+ Annotations.newDeserializer(service.getMetadata().getAnnotations());
+ assertEquals(serviceAnnotations.machineName(), machineName);
+
+ Map servers = serviceAnnotations.servers();
+ ServerConfig serverConfig = servers.get(serverNameRegex);
+ assertEquals(serverConfig, expected);
+ }
+
+ private void assertThatContainerPortIsExposed(String portProtocol, Integer port) {
assertTrue(
container
.getPorts()
@@ -376,8 +415,9 @@ private void assertThatInternalServerIsExposed(
p ->
p.getContainerPort().equals(port)
&& p.getProtocol().equals(portProtocol.toUpperCase())));
- // ensure that service is created
+ }
+ private Service findContainerRelatedService() {
Service service = null;
for (Entry entry : kubernetesEnvironment.getServices().entrySet()) {
if (SERVER_PREFIX_REGEX.matcher(entry.getKey()).matches()) {
@@ -385,9 +425,10 @@ private void assertThatInternalServerIsExposed(
break;
}
}
- assertNotNull(service);
+ return service;
+ }
- // ensure that required service port is exposed
+ private ServicePort assertThatServicePortIsExposed(Integer port, Service service) {
Optional servicePortOpt =
service
.getSpec()
@@ -400,13 +441,6 @@ private void assertThatInternalServerIsExposed(
assertEquals(servicePort.getTargetPort().getIntVal(), port);
assertEquals(servicePort.getPort(), port);
assertEquals(servicePort.getName(), SERVER_PREFIX + "-" + port);
-
- Annotations.Deserializer serviceAnnotations =
- Annotations.newDeserializer(service.getMetadata().getAnnotations());
- assertEquals(serviceAnnotations.machineName(), machineName);
-
- Map servers = serviceAnnotations.servers();
- ServerConfig serverConfig = servers.get(serverNameRegex);
- assertEquals(serverConfig, expected);
+ return servicePort;
}
}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProviderTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProviderTest.java
new file mode 100644
index 00000000000..f9e494d3595
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/SecureServerExposerFactoryProviderTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure;
+
+import static org.testng.Assert.assertSame;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.che.inject.ConfigurationException;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/** @author Sergii Leshchenko */
+@Listeners(MockitoTestNGListener.class)
+public class SecureServerExposerFactoryProviderTest {
+ @Mock private DefaultSecureServersFactory defaultSecureServersFactory;
+
+ @Mock private SecureServerExposerFactory customSecureServerExposer;
+
+ private Map> factories =
+ new HashMap<>();
+
+ @Test
+ public void shouldReturnDefaultSecureServerExposerWhenAgentAuthIsDisabled() {
+ // given
+ SecureServerExposerFactoryProvider factoryProvider =
+ new SecureServerExposerFactoryProvider<>(
+ false, "custom", defaultSecureServersFactory, factories);
+
+ // when
+ SecureServerExposerFactory factory = factoryProvider.get();
+
+ // then
+ assertSame(factory, defaultSecureServersFactory);
+ }
+
+ @Test
+ public void shouldReturnConfiguredSecureServerExposerWhenAgentAuthIsEnabled() {
+ // given
+ factories.put("custom", customSecureServerExposer);
+ SecureServerExposerFactoryProvider factoryProvider =
+ new SecureServerExposerFactoryProvider<>(
+ true, "custom", defaultSecureServersFactory, factories);
+
+ // when
+ SecureServerExposerFactory factory = factoryProvider.get();
+
+ // then
+ assertSame(factory, customSecureServerExposer);
+ }
+
+ @Test(expectedExceptions = ConfigurationException.class)
+ public void shouldThrowAnExceptionIfConfiguredSecureServerWasNotFound() {
+ // given
+ SecureServerExposerFactoryProvider factoryProvider =
+ new SecureServerExposerFactoryProvider<>(
+ true, "non-existing", defaultSecureServersFactory, factories);
+
+ // when
+ factoryProvider.get();
+ }
+}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilderTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilderTest.java
new file mode 100644
index 00000000000..0334798a41f
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyConfigBuilderTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.testng.reporters.Files;
+
+/**
+ * Tests {@link JwtProxyConfigBuilder}.
+ *
+ * @author Sergii Leshchenko
+ */
+public class JwtProxyConfigBuilderTest {
+
+ private JwtProxyConfigBuilder jwtProxyConfigBuilder;
+
+ @BeforeMethod
+ public void setUp() {
+ jwtProxyConfigBuilder = new JwtProxyConfigBuilder("workspace123");
+ }
+
+ @Test
+ public void shouldBuildJwtProxyConfigInYamlFormat() throws Exception {
+ // given
+ jwtProxyConfigBuilder.addVerifierProxy(8080, "http://tomcat:8080");
+ jwtProxyConfigBuilder.addVerifierProxy(4101, "ws://terminal:4101");
+
+ // when
+ String jwtProxyConfigYaml = jwtProxyConfigBuilder.build();
+
+ // then
+ assertEquals(
+ jwtProxyConfigYaml,
+ Files.readFile(getClass().getClassLoader().getResourceAsStream("jwtproxy-confg.yaml")));
+ }
+}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java
new file mode 100644
index 00000000000..405caa4edc5
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxyProvisionerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_PREFIX;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_UNIQUE_PART_SIZE;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_CONFIG_FILE;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.JWT_PROXY_PUBLIC_KEY_FILE;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.PUBLIC_KEY_FOOTER;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxyProvisioner.PUBLIC_KEY_HEADER;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.Service;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.util.Base64;
+import java.util.regex.Pattern;
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
+import org.eclipse.che.multiuser.machine.authentication.server.signature.SignatureKeyManager;
+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;
+
+/**
+ * Tests {@link JwtProxyProvisioner}.
+ *
+ * @author Sergii Leshchenko
+ */
+@Listeners(MockitoTestNGListener.class)
+public class JwtProxyProvisionerTest {
+
+ private static final String WORKSPACE_ID = "workspace123";
+ private static final Pattern JWTPROXY_SERVICE_NAME_PATTERN =
+ Pattern.compile(SERVER_PREFIX + "\\w{" + SERVER_UNIQUE_PART_SIZE + "}-jwtproxy");
+ private final RuntimeIdentity runtimeId =
+ new RuntimeIdentityImpl(WORKSPACE_ID, "env123", "owner123");
+
+ @Mock private SignatureKeyManager signatureKeyManager;
+ private KeyPair keyPair;
+ @Mock private PublicKey publicKey;
+
+ private JwtProxyProvisioner jwtProxyProvisioner;
+ private KubernetesEnvironment k8sEnv;
+
+ @BeforeMethod
+ public void setUp() {
+ keyPair = new KeyPair(publicKey, null);
+ when(signatureKeyManager.getKeyPair()).thenReturn(keyPair);
+ when(publicKey.getEncoded()).thenReturn("publickey".getBytes());
+
+ jwtProxyProvisioner = new JwtProxyProvisioner(runtimeId, signatureKeyManager);
+ k8sEnv = KubernetesEnvironment.builder().build();
+ }
+
+ @Test
+ public void shouldReturnGeneratedJwtProxyServiceName() {
+ // when
+ String jwtProxyServiceName = jwtProxyProvisioner.getServiceName();
+
+ // then
+ assertTrue(JWTPROXY_SERVICE_NAME_PATTERN.matcher(jwtProxyServiceName).matches());
+ }
+
+ @Test
+ public void shouldReturnGeneratedJwtProxyConfigMapName() {
+ // when
+ String jwtProxyConfigMap = jwtProxyProvisioner.getConfigMapName();
+
+ // then
+ assertEquals(jwtProxyConfigMap, "jwtproxy-config-" + WORKSPACE_ID);
+ }
+
+ @Test
+ public void shouldProvisionJwtProxyRelatedObjectsIntoKubernetesEnvironment() throws Exception {
+ // when
+ jwtProxyProvisioner.expose(k8sEnv, "terminal", 4401, "TCP");
+
+ // then
+ InternalMachineConfig jwtProxyMachine =
+ k8sEnv.getMachines().get(JwtProxyProvisioner.JWT_PROXY_MACHINE_NAME);
+ assertNotNull(jwtProxyMachine);
+
+ ConfigMap configMap = k8sEnv.getConfigMaps().get(jwtProxyProvisioner.getConfigMapName());
+ assertNotNull(configMap);
+ assertEquals(
+ configMap.getData().get(JWT_PROXY_PUBLIC_KEY_FILE),
+ PUBLIC_KEY_HEADER
+ + Base64.getEncoder().encodeToString("publickey".getBytes())
+ + PUBLIC_KEY_FOOTER);
+ assertNotNull(configMap.getData().get(JWT_PROXY_CONFIG_FILE));
+
+ Pod jwtProxyPod = k8sEnv.getPods().get("che-jwtproxy");
+ assertNotNull(jwtProxyPod);
+
+ Service jwtProxyService = k8sEnv.getServices().get(jwtProxyProvisioner.getServiceName());
+ assertNotNull(jwtProxyService);
+ }
+}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerTest.java
new file mode 100644
index 00000000000..ba19af057a9
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/secure/jwtproxy/JwtProxySecureServerExposerTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableMap;
+import io.fabric8.kubernetes.api.model.IntOrString;
+import io.fabric8.kubernetes.api.model.ServicePort;
+import java.util.Map;
+import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
+import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/**
+ * Tests {@link JwtProxySecureServerExposer}
+ *
+ * @author Sergii Leshchenko
+ */
+@Listeners(MockitoTestNGListener.class)
+public class JwtProxySecureServerExposerTest {
+
+ private static final String MACHINE_SERVICE_NAME = "service123";
+ private static final String MACHINE_NAME = "machine123";
+ public static final String JWT_PROXY_SERVICE_NAME = "jwtProxyServiceName";
+
+ @Mock private KubernetesEnvironment k8sEnv;
+ @Mock private JwtProxyProvisioner jwtProxyProvisioner;
+ @Mock private ExternalServerExposerStrategy externalServerExposer;
+
+ private JwtProxySecureServerExposer secureServerExposer;
+
+ @BeforeMethod
+ public void setUp() {
+ secureServerExposer =
+ new JwtProxySecureServerExposer<>(jwtProxyProvisioner, externalServerExposer);
+ }
+
+ @Test
+ public void shouldExposeSecureServersWithNewJwtProxyServicePort() throws Exception {
+ // given
+ ServicePort machineServicePort = new ServicePort();
+ machineServicePort.setTargetPort(new IntOrString(8080));
+ machineServicePort.setProtocol("TCP");
+ Map servers =
+ ImmutableMap.of(
+ "server1",
+ new ServerConfigImpl("8080/tcp", "http", "/api", ImmutableMap.of("secure", "true")),
+ "server2",
+ new ServerConfigImpl("8080/tcp", "ws", "/connect", ImmutableMap.of("secure", "true")));
+
+ ServicePort jwtProxyServicePort = new ServicePort();
+ doReturn(jwtProxyServicePort)
+ .when(jwtProxyProvisioner)
+ .expose(any(), anyString(), anyInt(), anyString());
+
+ when(jwtProxyProvisioner.getServiceName()).thenReturn(JWT_PROXY_SERVICE_NAME);
+
+ // when
+ secureServerExposer.expose(
+ k8sEnv, MACHINE_NAME, MACHINE_SERVICE_NAME, machineServicePort, servers);
+
+ // then
+ verify(jwtProxyProvisioner).expose(k8sEnv, MACHINE_SERVICE_NAME, 8080, "TCP");
+ verify(externalServerExposer)
+ .expose(k8sEnv, MACHINE_NAME, JWT_PROXY_SERVICE_NAME, jwtProxyServicePort, servers);
+ }
+}
diff --git a/infrastructures/kubernetes/src/test/resources/jwtproxy-confg.yaml b/infrastructures/kubernetes/src/test/resources/jwtproxy-confg.yaml
new file mode 100644
index 00000000000..a6f83c5c240
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/resources/jwtproxy-confg.yaml
@@ -0,0 +1,40 @@
+jwtproxy:
+ verifier_proxies:
+ - listen_addr: :8080
+ verifier:
+ upstream: http://tomcat:8080/
+ audience: http://workspace123
+ max_skew: 1m
+ max_ttl: 3h
+ key_server:
+ type: preshared
+ options:
+ issuer: wsmaster
+ key_id: mykey
+ public_key_path: /config/mykey.pub
+ claims_verifiers:
+ - type: static
+ options:
+ iss: wsmaster
+ nonce_storage:
+ type: void
+ - listen_addr: :4101
+ verifier:
+ upstream: ws://terminal:4101/
+ audience: http://workspace123
+ max_skew: 1m
+ max_ttl: 3h
+ key_server:
+ type: preshared
+ options:
+ issuer: wsmaster
+ key_id: mykey
+ public_key_path: /config/mykey.pub
+ claims_verifiers:
+ - type: static
+ options:
+ iss: wsmaster
+ nonce_storage:
+ type: void
+ signer_proxy:
+ enabled: false
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
index 99bdc580c9d..4fc8a6d23eb 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
@@ -42,6 +42,10 @@
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.LogsRootEnvVariableProvider;
import org.eclipse.che.workspace.infrastructure.kubernetes.provision.server.ServersConverter;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerStrategy;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.DefaultSecureServersFactory;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactory;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactoryProvider;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.JwtProxySecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsnext.KubernetesWorkspaceNextApplier;
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory;
@@ -97,5 +101,26 @@ protected void configure() {
MapBinder wsNext =
MapBinder.newMapBinder(binder(), String.class, WorkspaceNextApplier.class);
wsNext.addBinding(OpenShiftEnvironment.TYPE).to(KubernetesWorkspaceNextApplier.class);
+
+ bind(new TypeLiteral>() {})
+ .toProvider(new TypeLiteral>() {});
+
+ MapBinder>
+ secureServerExposerFactories =
+ MapBinder.newMapBinder(
+ binder(),
+ new TypeLiteral() {},
+ new TypeLiteral>() {});
+
+ secureServerExposerFactories
+ .addBinding("default")
+ .to(new TypeLiteral>() {});
+
+ install(
+ new FactoryModuleBuilder()
+ .build(new TypeLiteral>() {}));
+ secureServerExposerFactories
+ .addBinding("jwtproxy")
+ .to(new TypeLiteral>() {});
}
}
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntime.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntime.java
index bec9c6390f3..13a3f8d627c 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntime.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntime.java
@@ -12,6 +12,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.inject.assistedinject.Assisted;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.Service;
@@ -98,6 +99,10 @@ protected void startMachines() throws InfrastructureException {
project.secrets().create(secret);
}
+ for (ConfigMap configMap : osEnv.getConfigMaps().values()) {
+ project.configMaps().create(configMap);
+ }
+
List createdServices = new ArrayList<>();
for (Service service : osEnv.getServices().values()) {
createdServices.add(project.services().create(service));
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
index 610cc110d48..2d485fcfdbb 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
@@ -10,6 +10,7 @@
*/
package org.eclipse.che.workspace.infrastructure.openshift.environment;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.Secret;
@@ -54,8 +55,9 @@ public OpenShiftEnvironment(
Map ingresses,
Map pvcs,
Map secrets,
+ Map configMaps,
Map routes) {
- super(internalRecipe, machines, warnings, pods, services, ingresses, pvcs, secrets);
+ super(internalRecipe, machines, warnings, pods, services, ingresses, pvcs, secrets, configMaps);
this.routes = routes;
}
@@ -117,6 +119,12 @@ public Builder setSecrets(Map secrets) {
return this;
}
+ @Override
+ public Builder setConfigMaps(Map configMaps) {
+ this.configMaps.putAll(configMaps);
+ return this;
+ }
+
public Builder setRoutes(Map route) {
this.routes.putAll(route);
return this;
@@ -124,7 +132,16 @@ public Builder setRoutes(Map route) {
public OpenShiftEnvironment build() {
return new OpenShiftEnvironment(
- internalRecipe, machines, warnings, pods, services, ingresses, pvcs, secrets, routes);
+ internalRecipe,
+ machines,
+ warnings,
+ pods,
+ services,
+ ingresses,
+ pvcs,
+ secrets,
+ configMaps,
+ routes);
}
}
}
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
index 30b04899174..316f4249aa7 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
@@ -15,6 +15,7 @@
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import com.google.common.annotations.VisibleForTesting;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.KubernetesList;
@@ -68,6 +69,10 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory())
.setSecrets(new HashMap<>())
+ .setConfigMaps(new HashMap<>())
.setRoutes(new HashMap<>())
.build();
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java
index 11ec7bf9ea1..0a514420256 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java
@@ -18,6 +18,7 @@
import io.fabric8.openshift.client.OpenShiftClient;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException;
+import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesDeployments;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesIngresses;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespace;
@@ -46,8 +47,18 @@ public class OpenShiftProject extends KubernetesNamespace {
OpenShiftRoutes routes,
KubernetesPersistentVolumeClaims pvcs,
KubernetesIngresses ingresses,
- KubernetesSecrets secrets) {
- super(clientFactory, workspaceId, name, deployments, services, pvcs, ingresses, secrets);
+ KubernetesSecrets secrets,
+ KubernetesConfigsMaps configMaps) {
+ super(
+ clientFactory,
+ workspaceId,
+ name,
+ deployments,
+ services,
+ pvcs,
+ ingresses,
+ secrets,
+ configMaps);
this.clientFactory = clientFactory;
this.routes = routes;
}
@@ -84,7 +95,12 @@ public OpenShiftRoutes routes() {
/** Removes all object except persistent volume claims inside project. */
public void cleanUp() throws InfrastructureException {
- doRemove(routes::delete, services()::delete, deployments()::delete, secrets()::delete);
+ doRemove(
+ routes::delete,
+ services()::delete,
+ deployments()::delete,
+ secrets()::delete,
+ configMaps()::delete);
}
private void create(String projectName, KubernetesClient kubeClient, OpenShiftClient ocClient)
diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntimeTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntimeTest.java
index 1908a0f3b9b..37a4a74bc9f 100644
--- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntimeTest.java
+++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntimeTest.java
@@ -29,6 +29,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
@@ -70,6 +71,7 @@
import org.eclipse.che.workspace.infrastructure.kubernetes.bootstrapper.KubernetesBootstrapperFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesMachineCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
+import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesDeployments;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesSecrets;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesServices;
@@ -125,6 +127,7 @@ public class OpenShiftInternalRuntimeTest {
@Mock private OpenShiftProject project;
@Mock private KubernetesServices services;
@Mock private KubernetesSecrets secrets;
+ @Mock private KubernetesConfigsMaps configMaps;
@Mock private OpenShiftRoutes routes;
@Mock private KubernetesDeployments deployments;
@Mock private KubernetesBootstrapper bootstrapper;
@@ -195,6 +198,7 @@ public void setup() throws Exception {
when(project.services()).thenReturn(services);
when(project.routes()).thenReturn(routes);
when(project.secrets()).thenReturn(secrets);
+ when(project.configMaps()).thenReturn(configMaps);
when(project.deployments()).thenReturn(deployments);
when(bootstrapperFactory.create(any(), anyList(), any(), any(), any()))
.thenReturn(bootstrapper);
@@ -218,6 +222,7 @@ public void setup() throws Exception {
when(osEnv.getRoutes()).thenReturn(allRoutes);
when(osEnv.getPods()).thenReturn(allPods);
when(osEnv.getSecrets()).thenReturn(ImmutableMap.of("secret", new Secret()));
+ when(osEnv.getConfigMaps()).thenReturn(ImmutableMap.of("configMap", new ConfigMap()));
}
@Test
@@ -234,6 +239,7 @@ public void shouldStartMachines() throws Exception {
verify(routes).create(any());
verify(services).create(any());
verify(secrets).create(any());
+ verify(configMaps).create(any());
verify(project.deployments(), times(2)).watchEvents(any());
verify(eventService, times(2)).publish(any());
diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactoryTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactoryTest.java
index cec7268221c..035b44db985 100644
--- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactoryTest.java
+++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactoryTest.java
@@ -18,6 +18,8 @@
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.MACHINE_NAME_ANNOTATION_FMT;
+import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory.CONFIG_MAP_IGNORED_WARNING_CODE;
+import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory.CONFIG_MAP_IGNORED_WARNING_MESSAGE;
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory.PVC_IGNORED_WARNING_CODE;
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory.PVC_IGNORED_WARNING_MESSAGE;
import static org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory.ROUTES_IGNORED_WARNING_MESSAGE;
@@ -33,6 +35,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.DoneableKubernetesList;
import io.fabric8.kubernetes.api.model.HasMetadata;
@@ -59,6 +62,7 @@
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentValidator;
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientFactory;
import org.mockito.Mock;
@@ -137,7 +141,7 @@ public void ignorePVCsWhenRecipeContainsThem() throws Exception {
final OpenShiftEnvironment parsed =
osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
- assertTrue(parsed.getRoutes().isEmpty());
+ assertTrue(parsed.getPersistentVolumeClaims().isEmpty());
assertEquals(parsed.getWarnings().size(), 1);
assertEquals(
parsed.getWarnings().get(0),
@@ -152,13 +156,28 @@ public void ignoreSecretsWhenRecipeContainsThem() throws Exception {
final OpenShiftEnvironment parsed =
osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
- assertTrue(parsed.getRoutes().isEmpty());
+ assertTrue(parsed.getSecrets().isEmpty());
assertEquals(parsed.getWarnings().size(), 1);
assertEquals(
parsed.getWarnings().get(0),
new WarningImpl(SECRET_IGNORED_WARNING_CODE, SECRET_IGNORED_WARNING_MESSAGE));
}
+ @Test
+ public void ignoreConfigMapsWhenRecipeContainsThem() throws Exception {
+ final List recipeObjects = singletonList(new ConfigMap());
+ when(validatedObjects.getItems()).thenReturn(recipeObjects);
+
+ final KubernetesEnvironment parsed =
+ osEnvironmentFactory.doCreate(internalRecipe, emptyMap(), emptyList());
+
+ assertTrue(parsed.getConfigMaps().isEmpty());
+ assertEquals(parsed.getWarnings().size(), 1);
+ assertEquals(
+ parsed.getWarnings().get(0),
+ new WarningImpl(CONFIG_MAP_IGNORED_WARNING_CODE, CONFIG_MAP_IGNORED_WARNING_MESSAGE));
+ }
+
@Test
public void testSetsRamLimitAttributeFromOpenShiftResource() throws Exception {
final long firstMachineRamLimit = 3072 * BYTES_IN_MB;
diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java
index e0165658ef2..14762c09cb8 100644
--- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java
+++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProjectTest.java
@@ -32,6 +32,7 @@
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.client.dsl.ProjectRequestOperation;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
+import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesDeployments;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesIngresses;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesPersistentVolumeClaims;
@@ -61,6 +62,7 @@ public class OpenShiftProjectTest {
@Mock private KubernetesPersistentVolumeClaims pvcs;
@Mock private KubernetesIngresses ingresses;
@Mock private KubernetesSecrets secrets;
+ @Mock private KubernetesConfigsMaps configsMaps;
@Mock private OpenShiftClientFactory clientFactory;
@Mock private OpenShiftClient openShiftClient;
@Mock private KubernetesClient kubernetesClient;
@@ -93,7 +95,8 @@ public void setUp() throws Exception {
routes,
pvcs,
ingresses,
- secrets);
+ secrets,
+ configsMaps);
}
@Test
@@ -133,6 +136,7 @@ public void testOpenShiftProjectCleaningUp() throws Exception {
verify(services).delete();
verify(deployments).delete();
verify(secrets).delete();
+ verify(configsMaps).delete();
}
@Test
diff --git a/wsagent/agent/src/main/resources/installers/1.0.0/org.eclipse.che.ws-agent.json b/wsagent/agent/src/main/resources/installers/1.0.0/org.eclipse.che.ws-agent.json
index 92fdd63013f..2df0eecf510 100644
--- a/wsagent/agent/src/main/resources/installers/1.0.0/org.eclipse.che.ws-agent.json
+++ b/wsagent/agent/src/main/resources/installers/1.0.0/org.eclipse.che.ws-agent.json
@@ -12,12 +12,18 @@
"wsagent/http": {
"port": "4401/tcp",
"protocol": "http",
- "path" : "/api"
+ "path" : "/api",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent/ws": {
"port": "4401/tcp",
"protocol": "ws",
- "path" : "/wsagent"
+ "path" : "/wsagent",
+ "attributes": {
+ "secure": "true"
+ }
}
}
}
diff --git a/wsagent/agent/src/main/resources/installers/1.0.1/org.eclipse.che.ws-agent.json b/wsagent/agent/src/main/resources/installers/1.0.1/org.eclipse.che.ws-agent.json
index 2b1398b50ca..5b5d33f0a86 100644
--- a/wsagent/agent/src/main/resources/installers/1.0.1/org.eclipse.che.ws-agent.json
+++ b/wsagent/agent/src/main/resources/installers/1.0.1/org.eclipse.che.ws-agent.json
@@ -12,12 +12,18 @@
"wsagent/http": {
"port": "4401/tcp",
"protocol": "http",
- "path" : "/api"
+ "path" : "/api",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent/ws": {
"port": "4401/tcp",
"protocol": "ws",
- "path" : "/wsagent"
+ "path" : "/wsagent",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent-debug": {
"port": "4403/tcp",
diff --git a/wsagent/agent/src/main/resources/installers/1.0.2/org.eclipse.che.ws-agent.json b/wsagent/agent/src/main/resources/installers/1.0.2/org.eclipse.che.ws-agent.json
index 8ee354599ba..b48e5cd0c07 100644
--- a/wsagent/agent/src/main/resources/installers/1.0.2/org.eclipse.che.ws-agent.json
+++ b/wsagent/agent/src/main/resources/installers/1.0.2/org.eclipse.che.ws-agent.json
@@ -12,12 +12,18 @@
"wsagent/http": {
"port": "4401/tcp",
"protocol": "http",
- "path" : "/api"
+ "path" : "/api",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent/ws": {
"port": "4401/tcp",
"protocol": "ws",
- "path" : "/wsagent"
+ "path" : "/wsagent",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent-debug": {
"port": "4403/tcp",
diff --git a/wsagent/agent/src/main/resources/installers/1.0.3/org.eclipse.che.ws-agent.json b/wsagent/agent/src/main/resources/installers/1.0.3/org.eclipse.che.ws-agent.json
index 2d40a32df9e..f4cac844b90 100644
--- a/wsagent/agent/src/main/resources/installers/1.0.3/org.eclipse.che.ws-agent.json
+++ b/wsagent/agent/src/main/resources/installers/1.0.3/org.eclipse.che.ws-agent.json
@@ -9,12 +9,18 @@
"wsagent/http": {
"port": "4401/tcp",
"protocol": "http",
- "path" : "/api"
+ "path" : "/api",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent/ws": {
"port": "4401/tcp",
"protocol": "ws",
- "path" : "/wsagent"
+ "path" : "/wsagent",
+ "attributes": {
+ "secure": "true"
+ }
},
"wsagent-debug": {
"port": "4403/tcp",