Fixes #17852 - jwtproxy is the new default for the secure servers (#17946)

Signed-off-by: Lukas Krejci <lkrejci@redhat.com>
7.20.x
Lukas Krejci 2020-10-05 13:14:26 +02:00 committed by GitHub
parent 9f2a6a2dc5
commit 23c5fb2b47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 87 deletions

View File

@ -93,9 +93,14 @@ import org.eclipse.che.security.oauth.OpenShiftOAuthModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfraModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructure;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.PassThroughProxySecureServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxyConfigBuilderFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxyProvisionerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxySecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxyProvisionerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxySecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.metrics.InfrastructureMetricsModule;
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientConfigFactory;
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftInfraModule;
@ -237,10 +242,15 @@ public class WsMasterModule extends AbstractModule {
bindConstant().annotatedWith(Names.named("jndi.datasource.name")).to("java:/comp/env/jdbc/che");
String infrastructure = System.getenv("CHE_INFRASTRUCTURE_ACTIVE");
install(new FactoryModuleBuilder().build(JwtProxyConfigBuilderFactory.class));
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
installDefaultSecureServerExposer(infrastructure);
if (Boolean.valueOf(System.getenv("CHE_MULTIUSER"))) {
configureMultiUserMode(persistenceProperties, infrastructure);
} else {
configureSingleUserMode(persistenceProperties);
configureSingleUserMode(persistenceProperties, infrastructure);
}
install(
@ -278,7 +288,8 @@ public class WsMasterModule extends AbstractModule {
install(new OpenShiftOAuthModule());
}
private void configureSingleUserMode(Map<String, String> persistenceProperties) {
private void configureSingleUserMode(
Map<String, String> persistenceProperties, String infrastructure) {
persistenceProperties.put(
PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS,
"org.eclipse.che.core.db.h2.jpa.eclipselink.H2ExceptionHandler");
@ -306,6 +317,11 @@ public class WsMasterModule extends AbstractModule {
.to(org.eclipse.che.api.workspace.server.DefaultWorkspaceStatusCache.class);
install(new org.eclipse.che.api.workspace.activity.inject.WorkspaceActivityModule());
// In single user mode jwtproxy provisioner isn't actually bound at all, but since
// it is the new default, we need to "fake it" by binding the passthrough provisioner
// as the jwtproxy impl.
configureImpostorJwtProxySecureProvisioner(infrastructure);
}
private void configureMultiUserMode(
@ -414,4 +430,68 @@ public class WsMasterModule extends AbstractModule {
.to(new TypeLiteral<JwtProxySecureServerExposerFactory<OpenShiftEnvironment>>() {});
}
}
private void configureImpostorJwtProxySecureProvisioner(String infrastructure) {
if (KubernetesInfrastructure.NAME.equals(infrastructure)) {
MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<SecureServerExposerFactory<KubernetesEnvironment>>() {})
.addBinding("jwtproxy")
.to(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<KubernetesEnvironment>>() {});
} else {
MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<SecureServerExposerFactory<OpenShiftEnvironment>>() {})
.addBinding("jwtproxy")
.to(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<OpenShiftEnvironment>>() {});
}
}
private void installDefaultSecureServerExposer(String infrastructure) {
if (KubernetesInfrastructure.NAME.equals(infrastructure)) {
MapBinder<String, SecureServerExposerFactory<KubernetesEnvironment>>
secureServerExposerFactories =
MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>() {});
install(
new FactoryModuleBuilder()
.implement(
new TypeLiteral<SecureServerExposer<KubernetesEnvironment>>() {},
new TypeLiteral<PassThroughProxySecureServerExposer<KubernetesEnvironment>>() {})
.build(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<KubernetesEnvironment>>() {}));
secureServerExposerFactories
.addBinding("default")
.to(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<KubernetesEnvironment>>() {});
} else {
MapBinder<String, SecureServerExposerFactory<OpenShiftEnvironment>>
secureServerExposerFactories =
MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>() {});
install(
new FactoryModuleBuilder()
.implement(
new TypeLiteral<SecureServerExposer<OpenShiftEnvironment>>() {},
new TypeLiteral<PassThroughProxySecureServerExposer<OpenShiftEnvironment>>() {})
.build(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<OpenShiftEnvironment>>() {}));
secureServerExposerFactories
.addBinding("default")
.to(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<OpenShiftEnvironment>>() {});
}
}
}

View File

@ -606,7 +606,7 @@ che.workspace.storage.preferred_type=persistent
# So, servers should authenticate requests themselves.
# - 'jwtproxy': jwtproxy will authenticate requests.
# So, servers will receive only authenticated ones.
che.server.secure_exposer=default
che.server.secure_exposer=jwtproxy
# Jwtproxy issuer string, token lifetime and optional auth page path to route unsigned requests to.
che.server.secure_exposer.jwtproxy.token.issuer=wsmaster

View File

@ -78,13 +78,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.Multi
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.MultihostIngressServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ServiceExposureStrategyProvider;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.SingleHostExternalServiceExposureStrategy;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
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.PassThroughProxySecureServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxyConfigBuilderFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxyProvisionerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxySecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.NonTlsDistributedClusterModeNotifier;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.KubernetesPluginsToolingApplier;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.PluginBrokerManager;
@ -205,30 +199,6 @@ public class KubernetesInfraModule extends AbstractModule {
.addBinding(KubernetesEnvironment.TYPE)
.to(KubernetesPluginsToolingApplier.class);
MapBinder<String, SecureServerExposerFactory<KubernetesEnvironment>>
secureServerExposerFactories =
MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<SecureServerExposerFactory<KubernetesEnvironment>>() {});
install(new FactoryModuleBuilder().build(JwtProxyConfigBuilderFactory.class));
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
install(
new FactoryModuleBuilder()
.implement(
new TypeLiteral<SecureServerExposer<KubernetesEnvironment>>() {},
new TypeLiteral<PassThroughProxySecureServerExposer<KubernetesEnvironment>>() {})
.build(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<KubernetesEnvironment>>() {}));
secureServerExposerFactories
.addBinding("default")
.to(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<KubernetesEnvironment>>() {});
bind(BrokerService.class);
bind(new TypeLiteral<BrokerEnvironmentFactory<KubernetesEnvironment>>() {})

View File

@ -18,7 +18,6 @@ import static org.eclipse.che.api.core.model.workspace.config.Command.WORKING_DI
import static org.eclipse.che.api.workspace.shared.Constants.CONTAINER_SOURCE_ATTRIBUTE;
import static org.eclipse.che.api.workspace.shared.Constants.PLUGIN_MACHINE_ATTRIBUTE;
import static org.eclipse.che.api.workspace.shared.Constants.TOOL_CONTAINER_SOURCE;
import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactoryProvider.SECURE_EXPOSER_IMPL_PROPERTY;
import com.google.common.annotations.Beta;
import com.google.common.collect.ArrayListMultimap;
@ -174,12 +173,6 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
}
chePlugins.forEach(chePlugin -> populateWorkspaceEnvVars(chePlugin, k8sEnv));
if (isAuthEnabled) {
// enable per-workspace security with JWT proxy for sidecar based workspaces
// because it is the only workspace security implementation supported for now
k8sEnv.getAttributes().putIfAbsent(SECURE_EXPOSER_IMPL_PROPERTY, "jwtproxy");
}
}
private void addToolingPod(KubernetesEnvironment kubernetesEnvironment) {

View File

@ -789,25 +789,6 @@ public class KubernetesPluginsToolingApplierTest {
applier.apply(runtimeIdentity, internalEnvironment, singletonList(chePlugin));
}
@Test
public void shouldSetJWTServerExposerAttributeIfAuthEnabled() throws Exception {
applier =
new KubernetesPluginsToolingApplier(
TEST_IMAGE_POLICY,
MEMORY_LIMIT_MB,
MEMORY_REQUEST_MB,
CPU_LIMIT,
CPU_REQUEST,
true,
projectsRootEnvVariableProvider,
chePluginsVolumeApplier,
envVars);
applier.apply(runtimeIdentity, internalEnvironment, singletonList(createChePlugin()));
assertEquals(internalEnvironment.getAttributes().get(SECURE_EXPOSER_IMPL_PROPERTY), "jwtproxy");
}
@Test
public void shouldNotSetJWTServerExposerAttributeIfAuthEnabledButAttributeIsPresent()
throws Exception {

View File

@ -77,14 +77,8 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.Exter
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.GatewayServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ServiceExposureStrategyProvider;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.SingleHostExternalServiceExposureStrategy;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
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.CookiePathStrategy;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.PassThroughProxySecureServerExposer;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.JwtProxyConfigBuilderFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxyProvisionerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.jwtproxy.factory.PassThroughProxySecureServerExposerFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.NonTlsDistributedClusterModeNotifier;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.KubernetesPluginsToolingApplier;
import org.eclipse.che.workspace.infrastructure.kubernetes.wsplugins.PluginBrokerManager;
@ -183,28 +177,6 @@ public class OpenShiftInfraModule extends AbstractModule {
bind(SecureServerExposerFactoryProvider.class)
.to(new TypeLiteral<SecureServerExposerFactoryProvider<OpenShiftEnvironment>>() {});
MapBinder<String, SecureServerExposerFactory<OpenShiftEnvironment>>
secureServerExposerFactories =
MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<SecureServerExposerFactory<OpenShiftEnvironment>>() {});
install(new FactoryModuleBuilder().build(JwtProxyConfigBuilderFactory.class));
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
install(
new FactoryModuleBuilder()
.implement(
new TypeLiteral<SecureServerExposer<OpenShiftEnvironment>>() {},
new TypeLiteral<PassThroughProxySecureServerExposer<OpenShiftEnvironment>>() {})
.build(
new TypeLiteral<
PassThroughProxySecureServerExposerFactory<OpenShiftEnvironment>>() {}));
secureServerExposerFactories
.addBinding("default")
.to(new TypeLiteral<PassThroughProxySecureServerExposerFactory<OpenShiftEnvironment>>() {});
bind(BrokerService.class);
bind(new TypeLiteral<BrokerEnvironmentFactory<OpenShiftEnvironment>>() {})