Add ability to change CORS configuration on Che Server through env vars (#12046)
parent
f6f0d69755
commit
3d366a1c19
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
package org.eclipse.che.api.deploy;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static com.google.inject.matcher.Matchers.subclassesOf;
|
||||
import static org.eclipse.che.inject.Matchers.names;
|
||||
import static org.eclipse.che.multiuser.api.permission.server.SystemDomain.SYSTEM_DOMAIN_ACTIONS;
|
||||
|
|
@ -61,6 +62,7 @@ import org.eclipse.che.api.workspace.server.spi.provision.env.JavaOptsEnvVariabl
|
|||
import org.eclipse.che.api.workspace.server.spi.provision.env.MachineTokenEnvVarProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.MavenOptsEnvVariableProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.ProjectsRootEnvVariableProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceAgentCorsAllowedOriginsEnvVarProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceAgentJavaOptsEnvVariableProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceIdEnvVarProvider;
|
||||
import org.eclipse.che.api.workspace.server.spi.provision.env.WorkspaceMavenServerJavaOptsEnvVariableProvider;
|
||||
|
|
@ -187,6 +189,12 @@ public class WsMasterModule extends AbstractModule {
|
|||
envVarProviders.addBinding().to(WorkspaceAgentJavaOptsEnvVariableProvider.class);
|
||||
envVarProviders.addBinding().to(WorkspaceMavenServerJavaOptsEnvVariableProvider.class);
|
||||
|
||||
// propagate CORS allowed origin evn variable to WS agent only if corresponding env variable
|
||||
// is defined on master
|
||||
if (!isNullOrEmpty(System.getenv("CHE_WSAGENT_CORS_ALLOWED__ORIGINS"))) {
|
||||
envVarProviders.addBinding().to(WorkspaceAgentCorsAllowedOriginsEnvVarProvider.class);
|
||||
}
|
||||
|
||||
bind(org.eclipse.che.api.workspace.server.bootstrap.InstallerService.class);
|
||||
bind(org.eclipse.che.api.workspace.server.event.WorkspaceJsonRpcMessenger.class)
|
||||
.asEagerSingleton();
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@
|
|||
package org.eclipse.che.api.deploy;
|
||||
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.catalina.filters.CorsFilter;
|
||||
import org.eclipse.che.api.core.cors.CheCorsFilter;
|
||||
import org.eclipse.che.commons.logback.filter.RequestIdLoggerFilter;
|
||||
import org.eclipse.che.inject.DynaModule;
|
||||
import org.eclipse.che.multiuser.keycloak.server.deploy.KeycloakServletModule;
|
||||
|
|
@ -31,25 +28,10 @@ public class WsMasterServletModule extends ServletModule {
|
|||
if (Boolean.valueOf(System.getenv("CHE_TRACING_ENABLED"))) {
|
||||
install(new org.eclipse.che.core.tracing.web.TracingWebModule());
|
||||
}
|
||||
if (isCheCorsEnabled()) {
|
||||
filter("/*").through(CheCorsFilter.class);
|
||||
}
|
||||
|
||||
final Map<String, String> corsFilterParams = new HashMap<>();
|
||||
corsFilterParams.put("cors.allowed.origins", "*");
|
||||
corsFilterParams.put(
|
||||
"cors.allowed.methods", "GET," + "POST," + "HEAD," + "OPTIONS," + "PUT," + "DELETE");
|
||||
corsFilterParams.put(
|
||||
"cors.allowed.headers",
|
||||
"Content-Type,"
|
||||
+ "X-Requested-With,"
|
||||
+ "accept,"
|
||||
+ "Origin,"
|
||||
+ "Access-Control-Request-Method,"
|
||||
+ "Access-Control-Request-Headers");
|
||||
corsFilterParams.put("cors.support.credentials", "true");
|
||||
// preflight cache is available for 10 minutes
|
||||
corsFilterParams.put("cors.preflight.maxage", "10");
|
||||
bind(CorsFilter.class).in(Singleton.class);
|
||||
|
||||
filter("/*").through(CorsFilter.class, corsFilterParams);
|
||||
filter("/*").through(RequestIdLoggerFilter.class);
|
||||
|
||||
// Matching group SHOULD contain forward slash.
|
||||
|
|
@ -67,6 +49,16 @@ public class WsMasterServletModule extends ServletModule {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isCheCorsEnabled() {
|
||||
String cheCorsEnabledEnvVar = System.getenv("CHE_CORS_ENABLED");
|
||||
if (cheCorsEnabledEnvVar == null) {
|
||||
// by default CORS should be enabled
|
||||
return true;
|
||||
} else {
|
||||
return Boolean.valueOf(cheCorsEnabledEnvVar);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureSingleUserMode() {
|
||||
filter("/*").through(org.eclipse.che.api.local.filters.EnvironmentInitializationFilter.class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -553,3 +553,16 @@ che.core.jsonrpc.processor_max_pool_size=100
|
|||
|
||||
## Port the the http server endpoint that would be exposed with Prometheus metrics
|
||||
che.metrics.port=8087
|
||||
|
||||
# CORS settings
|
||||
# CORS filter on WS Master is turned on by default.
|
||||
# Use environment variable "CHE_CORS_ENABLED=false" to turn it off
|
||||
# "cors.allowed.origins" indicates which request origins are allowed
|
||||
che.cors.allowed_origins=*
|
||||
# "cors.support.credentials" indicates if it allows processing of requests with credentials
|
||||
# (in cookies, headers, TLS client certificates)
|
||||
che.cors.allow_credentials=true
|
||||
# This property is used to provide value for WS Agent CORS allowed origins env variable from WS Master,
|
||||
# as it allows the automated initialization of preferred CORS configuration, if property value is
|
||||
# set to WS Master domain.
|
||||
che.wsagent.cors.allowed_origins=
|
||||
|
|
|
|||
|
|
@ -11,46 +11,44 @@
|
|||
*/
|
||||
package org.eclipse.che.api.core.cors;
|
||||
|
||||
import static org.apache.catalina.filters.CorsFilter.DEFAULT_ALLOWED_ORIGINS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_HEADERS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_METHODS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_ORIGINS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_EXPOSED_HEADERS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_PREFLIGHT_MAXAGE;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_SUPPORT_CREDENTIALS;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.catalina.filters.CorsFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The special filter which provides filtering requests in according to settings which are set to
|
||||
* {@link CorsFilter}. More information about filter and parameters you can find in documentation.
|
||||
* The class contains business logic which allows to get allowed origin from any endpoint as it is
|
||||
* used by export workspace.
|
||||
* {@link CorsFilter}. Uses {@link CheCorsFilterConfig} for providing configuration.
|
||||
*
|
||||
* @author Dmitry Shnurenko
|
||||
* @author Mykhailo Kuznietsov
|
||||
*/
|
||||
@Singleton
|
||||
public class CheCorsFilter implements Filter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CheCorsFilter.class);
|
||||
|
||||
private CorsFilter corsFilter;
|
||||
|
||||
@Inject private CheCorsFilterConfig cheCorsFilterConfig;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
corsFilter = new CorsFilter();
|
||||
|
||||
corsFilter.init(new CheCorsFilterConfig());
|
||||
corsFilter.init(cheCorsFilterConfig);
|
||||
LOG.debug(
|
||||
"CORS initialized with parameters: 'cors.support.credentials': '{}', 'cors.allowed.origins': '{}'",
|
||||
cheCorsFilterConfig.getInitParameter("cors.support.credentials"),
|
||||
cheCorsFilterConfig.getInitParameter("cors.allowed.origins"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -64,50 +62,4 @@ public class CheCorsFilter implements Filter {
|
|||
public void destroy() {
|
||||
corsFilter.destroy();
|
||||
}
|
||||
|
||||
private class CheCorsFilterConfig implements FilterConfig {
|
||||
|
||||
private final Map<String, String> filterParams;
|
||||
|
||||
public CheCorsFilterConfig() {
|
||||
filterParams = new HashMap<>();
|
||||
filterParams.put(PARAM_CORS_ALLOWED_ORIGINS, DEFAULT_ALLOWED_ORIGINS);
|
||||
filterParams.put(
|
||||
PARAM_CORS_ALLOWED_METHODS, "GET," + "POST," + "HEAD," + "OPTIONS," + "PUT," + "DELETE");
|
||||
filterParams.put(
|
||||
PARAM_CORS_ALLOWED_HEADERS,
|
||||
"Content-Type,"
|
||||
+ "X-Requested-With,"
|
||||
+ "X-Oauth-Token,"
|
||||
+ "accept,"
|
||||
+ "Origin,"
|
||||
+ "Authorization,"
|
||||
+ "Access-Control-Request-Method,"
|
||||
+ "Access-Control-Request-Headers");
|
||||
filterParams.put(PARAM_CORS_EXPOSED_HEADERS, "JAXRS-Body-Provided");
|
||||
filterParams.put(PARAM_CORS_SUPPORT_CREDENTIALS, "true");
|
||||
// preflight cache is available for 10 minutes
|
||||
filterParams.put(PARAM_CORS_PREFLIGHT_MAXAGE, "10");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterName() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
throw new UnsupportedOperationException("The method does not supported in " + getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String key) {
|
||||
return filterParams.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
throw new UnsupportedOperationException("The method does not supported in " + getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.api.core.cors;
|
||||
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_HEADERS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_METHODS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_ALLOWED_ORIGINS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_EXPOSED_HEADERS;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_PREFLIGHT_MAXAGE;
|
||||
import static org.apache.catalina.filters.CorsFilter.PARAM_CORS_SUPPORT_CREDENTIALS;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
/**
|
||||
* Basic configuration for {@link CheCorsFilter}. Allowed origings and credentials support are
|
||||
* configurable through properties.
|
||||
*
|
||||
* @author Mykhailo Kuznietsov
|
||||
*/
|
||||
public class CheCorsFilterConfig implements FilterConfig {
|
||||
|
||||
private final Map<String, String> filterParams;
|
||||
|
||||
@Inject
|
||||
public CheCorsFilterConfig(
|
||||
@Named("che.cors.allow_credentials") boolean allowCredentials,
|
||||
@Named("che.cors.allowed_origins") String allowedOrigins) {
|
||||
filterParams = new HashMap<>();
|
||||
filterParams.put(PARAM_CORS_ALLOWED_ORIGINS, allowedOrigins);
|
||||
filterParams.put(
|
||||
PARAM_CORS_ALLOWED_METHODS, "GET," + "POST," + "HEAD," + "OPTIONS," + "PUT," + "DELETE");
|
||||
filterParams.put(
|
||||
PARAM_CORS_ALLOWED_HEADERS,
|
||||
"Content-Type,"
|
||||
+ "X-Requested-With,"
|
||||
+ "X-Oauth-Token,"
|
||||
+ "accept,"
|
||||
+ "Origin,"
|
||||
+ "Authorization,"
|
||||
+ "Access-Control-Request-Method,"
|
||||
+ "Access-Control-Request-Headers");
|
||||
filterParams.put(PARAM_CORS_EXPOSED_HEADERS, "JAXRS-Body-Provided");
|
||||
filterParams.put(PARAM_CORS_SUPPORT_CREDENTIALS, String.valueOf(allowCredentials));
|
||||
// preflight cache is available for 10 minutes
|
||||
filterParams.put(PARAM_CORS_PREFLIGHT_MAXAGE, "10");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterName() {
|
||||
return CheCorsFilter.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
throw new UnsupportedOperationException(
|
||||
"The method is not supported in " + CheCorsFilter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String key) {
|
||||
return filterParams.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
throw new UnsupportedOperationException(
|
||||
"The method is not supported in " + CheCorsFilter.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -86,3 +86,7 @@ data:
|
|||
{{- if .Values.workspaceSidecarDefaultRamLimit }}
|
||||
CHE_WORKSPACE_SIDECAR_DEFAULT__MEMORY__LIMIT__MB: {{ .Values.workspaceSidecarDefaultRamLimit }}
|
||||
{{- end }}
|
||||
CHE_CORS_ENABLED: "true"
|
||||
CHE_CORS_ALLOW__CREDENTIALS: "true"
|
||||
CHE_CORS_ALLOWED__ORIGINS: "*"
|
||||
CHE_WSAGENT_CORS_ALLOWED__ORIGINS: ""
|
||||
|
|
|
|||
|
|
@ -270,6 +270,26 @@ spec:
|
|||
configMapKeyRef:
|
||||
key: CHE_WORKSPACE_NO__PROXY
|
||||
name: che
|
||||
- name: CHE_CORS_ALLOW__CREDENTIALS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: CHE_CORS_ALLOW__CREDENTIALS
|
||||
name: che
|
||||
- name: CHE_CORS_ALLOWED__ORIGINS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: CHE_CORS_ALLOWED__ORIGINS
|
||||
name: che
|
||||
- name: CHE_CORS_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: CHE_CORS_ENABLED
|
||||
name: che
|
||||
- name: CHE_WSAGENT_CORS_ALLOWED__ORIGINS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: CHE_WSAGENT_CORS_ALLOWED__ORIGINS
|
||||
name: che
|
||||
{{- if .Values.workspaceDefaultRamRequest }}
|
||||
- name: CHE_WORKSPACE_DEFAULT_MEMORY_REQUEST_MB
|
||||
valueFrom:
|
||||
|
|
|
|||
|
|
@ -161,6 +161,14 @@ objects:
|
|||
value: "${CHE_TRACING_ENABLED}"
|
||||
- name: CHE_METRICS_ENABLED
|
||||
value: "false"
|
||||
- name: CHE_CORS_ENABLED
|
||||
value: "${CHE_CORS_ENABLED}"
|
||||
- name: CHE_CORS_ALLOW__CREDENTIALS
|
||||
value: "${CHE_CORS_ALLOW__CREDENTIALS}"
|
||||
- name: CHE_CORS_ALLOWED__ORIGINS
|
||||
value: "${CHE_CORS_ALLOWED__ORIGINS}"
|
||||
- name: CHE_WSAGENT_CORS_ALLOWED__ORIGINS
|
||||
value: "${CHE_WSAGENT_CORS_ALLOWED__ORIGINS}"
|
||||
image: ${IMAGE_CHE}:${CHE_VERSION}
|
||||
imagePullPolicy: "${PULL_POLICY}"
|
||||
livenessProbe:
|
||||
|
|
@ -309,6 +317,22 @@ parameters:
|
|||
displayName: Eclipse Che tracing
|
||||
description: Enable or disable tracing in Eclipse Che
|
||||
value: 'false'
|
||||
- name: CHE_CORS_ENABLED
|
||||
displayName: CORS filter for WS Master
|
||||
description: Enable or disable CORS filter for Eclipse Che WS Master
|
||||
value: 'true'
|
||||
- name: CHE_CORS_ALLOW__CREDENTIALS
|
||||
displayName: CORS credentials support for WS Master
|
||||
description: Allow requests with credentials for CORS filter
|
||||
value: 'true'
|
||||
- name: CHE_CORS_ALLOWED__ORIGINS
|
||||
displayName: CORS allowed origins for WS Master
|
||||
description: defines allowed origins in requests for CORS filter
|
||||
value: '*'
|
||||
- name: CHE_WSAGENT_CORS_ALLOWED__ORIGINS
|
||||
displayName: CORS allowed origins for WS Agent
|
||||
description: defines allowed origins in requests for CORS filter, that will be propagated as corresponding env variable on WS Agent. Only if its value is not null or empty
|
||||
value: ''
|
||||
labels:
|
||||
app: che
|
||||
template: che
|
||||
|
|
|
|||
|
|
@ -62,3 +62,10 @@ workspace.activity.schedule_period_s=60
|
|||
# Maximum size of the json processing pool
|
||||
# in case if pool size would be exceeded message execution will be rejected
|
||||
che.core.jsonrpc.processor_max_pool_size=100
|
||||
|
||||
# CORS settings
|
||||
# "cors.allowed.origins" indicates which request origins are allowed
|
||||
che.cors.allowed_origins=*
|
||||
# "cors.support.credentials" indicates if it allows processing of requests with credentials
|
||||
# (in cookies, headers, TLS client certificates)
|
||||
che.cors.allow_credentials=true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.api.workspace.server.spi.provision.env;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.commons.lang.Pair;
|
||||
|
||||
/**
|
||||
* Add environment variable that defines allowed origins for {@link CheCorsFilterConfig} of WS Agent
|
||||
*
|
||||
* @author Mykhailo Kuznietsov
|
||||
*/
|
||||
public class WorkspaceAgentCorsAllowedOriginsEnvVarProvider implements EnvVarProvider {
|
||||
|
||||
private String wsAgentCorsAllowedOrigins;
|
||||
|
||||
@Inject
|
||||
public WorkspaceAgentCorsAllowedOriginsEnvVarProvider(
|
||||
@Named("che.wsagent.cors.allowed_origins") String cheWsMasterAllowedOrigins) {
|
||||
this.wsAgentCorsAllowedOrigins = cheWsMasterAllowedOrigins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, String> get(RuntimeIdentity runtimeIdentity) throws InfrastructureException {
|
||||
return Pair.of("CHE_CORS_ALLOWED__ORIGINS", wsAgentCorsAllowedOrigins);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue