YARN-4009. CORS support for ResourceManager REST API. ( Varun Vasudev via jeagles)

This commit is contained in:
Jonathan Eagles 2015-10-23 10:34:08 -05:00
parent 35a303dfbe
commit f8adeb712d
16 changed files with 282 additions and 80 deletions

View File

@ -0,0 +1,74 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.security;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.http.FilterContainer;
import org.apache.hadoop.http.FilterInitializer;
import org.apache.hadoop.security.http.CrossOriginFilter;
public class HttpCrossOriginFilterInitializer extends FilterInitializer {
public static final String PREFIX = "hadoop.http.cross-origin.";
public static final String ENABLED_SUFFIX = "enabled";
private static final Log LOG =
LogFactory.getLog(HttpCrossOriginFilterInitializer.class);
@Override
public void initFilter(FilterContainer container, Configuration conf) {
String key = getEnabledConfigKey();
boolean enabled = conf.getBoolean(key, false);
if (enabled) {
container.addGlobalFilter("Cross Origin Filter",
CrossOriginFilter.class.getName(),
getFilterParameters(conf, getPrefix()));
} else {
LOG.info("CORS filter not enabled. Please set " + key
+ " to 'true' to enable it");
}
}
protected static Map<String, String> getFilterParameters(Configuration conf,
String prefix) {
Map<String, String> filterParams = new HashMap<String, String>();
for (Map.Entry<String, String> entry : conf.getValByRegex(prefix)
.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
name = name.substring(prefix.length());
filterParams.put(name, value);
}
return filterParams;
}
protected String getPrefix() {
return HttpCrossOriginFilterInitializer.PREFIX;
}
protected String getEnabledConfigKey() {
return getPrefix() + HttpCrossOriginFilterInitializer.ENABLED_SUFFIX;
}
}

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.apache.hadoop.yarn.server.timeline.webapp;
package org.apache.hadoop.security.http;
import java.io.IOException;
import java.util.ArrayList;
@ -246,7 +246,7 @@ public class CrossOriginFilter implements Filter {
if (accessControlRequestHeaders == null) {
return true;
}
String headers[] = accessControlRequestHeaders.trim().split("\\s*,\\s*");
String[] headers = accessControlRequestHeaders.trim().split("\\s*,\\s*");
return allowedHeaders.containsAll(Arrays.asList(headers));
}

View File

@ -1404,6 +1404,42 @@ for ldap providers in the same way as above does.
</description>
</property>
<!-- HTTP CORS support -->
<property>
<description>Enable/disable the cross-origin (CORS) filter.</description>
<name>hadoop.http.cross-origin.enabled</name>
<value>false</value>
</property>
<property>
<description>Comma separated list of origins that are allowed for web
services needing cross-origin (CORS) support. Wildcards (*) and patterns
allowed</description>
<name>hadoop.http.cross-origin.allowed-origins</name>
<value>*</value>
</property>
<property>
<description>Comma separated list of methods that are allowed for web
services needing cross-origin (CORS) support.</description>
<name>hadoop.http.cross-origin.allowed-methods</name>
<value>GET,POST,HEAD</value>
</property>
<property>
<description>Comma separated list of headers that are allowed for web
services needing cross-origin (CORS) support.</description>
<name>hadoop.http.cross-origin.allowed-headers</name>
<value>X-Requested-With,Content-Type,Accept,Origin</value>
</property>
<property>
<description>The number of seconds a pre-flighted request can be cached
for web services needing cross-origin (CORS) support.</description>
<name>hadoop.http.cross-origin.max-age</name>
<value>1800</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value></value>

View File

@ -60,3 +60,17 @@ IMPORTANT: when using IP addresses, browsers ignore cookies with domain settings
`hadoop.http.authentication.kerberos.principal`: Indicates the Kerberos principal to be used for HTTP endpoint when using 'kerberos' authentication. The principal short name must be `HTTP` per Kerberos HTTP SPNEGO specification. The default value is `HTTP/_HOST@$LOCALHOST`, where `_HOST` -if present- is replaced with bind address of the HTTP server.
`hadoop.http.authentication.kerberos.keytab`: Location of the keytab file with the credentials for the Kerberos principal used for the HTTP endpoint. The default value is `$user.home/hadoop.keytab`.i
CORS
----
To enable cross-origin support (CORS), please set the following configuration parameters:
Add org.apache.hadoop.security.HttpCrossOriginFilterInitializer to hadoop.http.filter.initializers in core-site.xml. You will also need to set the following properties in core-site.xml -
| Property | Default Value | Description |
|:---- |:---- |:---- |:---- |
| hadoop.http.cross-origin.enabled | false | Enables cross origin support for all web-services |
| hadoop.http.cross-origin.allowed-origins | \* | Comma separated list of origins that are allowed, wildcards (\*) and patterns allowed |
| hadoop.http.cross-origin.allowed-methods | GET,POST,HEAD | Comma separated list of methods that are allowed |
| hadoop.http.cross-origin.allowed-headers | X-Requested-With,Content-Type,Accept,Origin | Comma separated list of headers that are allowed |
| hadoop.http.cross-origin.max-age | 1800 | Number of seconds a pre-flighted request can be cached |

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.apache.hadoop.yarn.server.timeline.webapp;
package org.apache.hadoop.security;
import java.util.Map;
@ -25,21 +25,22 @@ import org.apache.hadoop.conf.Configuration;
import org.junit.Assert;
import org.junit.Test;
public class TestCrossOriginFilterInitializer {
public class TestHttpCrossOriginFilterInitializer {
@Test
public void testGetFilterParameters() {
// Initialize configuration object
Configuration conf = new Configuration();
conf.set(CrossOriginFilterInitializer.PREFIX + "rootparam", "rootvalue");
conf.set(CrossOriginFilterInitializer.PREFIX + "nested.param",
conf.set(HttpCrossOriginFilterInitializer.PREFIX + "rootparam",
"rootvalue");
conf.set(HttpCrossOriginFilterInitializer.PREFIX + "nested.param",
"nestedvalue");
conf.set("outofscopeparam", "outofscopevalue");
// call function under test
Map<String, String> filterParameters =
CrossOriginFilterInitializer.getFilterParameters(conf);
Map<String, String> filterParameters = HttpCrossOriginFilterInitializer
.getFilterParameters(conf, HttpCrossOriginFilterInitializer.PREFIX);
// retrieve values
String rootvalue = filterParameters.get("rootparam");

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.apache.hadoop.yarn.server.timeline.webapp;
package org.apache.hadoop.security.http;
import java.io.IOException;
import java.util.Collections;
@ -31,13 +31,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.hadoop.security.http.CrossOriginFilter;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
public class TestCrossOriginFilter {
@ -50,20 +50,20 @@ public class TestCrossOriginFilter {
FilterConfig filterConfig = new FilterConfigTest(conf);
// Origin is not specified for same origin requests
HttpServletRequest mockReq = mock(HttpServletRequest.class);
when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn(null);
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
Mockito.when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn(null);
// Objects to verify interactions based on request
HttpServletResponse mockRes = mock(HttpServletResponse.class);
FilterChain mockChain = mock(FilterChain.class);
HttpServletResponse mockRes = Mockito.mock(HttpServletResponse.class);
FilterChain mockChain = Mockito.mock(FilterChain.class);
// Object under test
CrossOriginFilter filter = new CrossOriginFilter();
filter.init(filterConfig);
filter.doFilter(mockReq, mockRes, mockChain);
verifyZeroInteractions(mockRes);
verify(mockChain).doFilter(mockReq, mockRes);
Mockito.verifyZeroInteractions(mockRes);
Mockito.verify(mockChain).doFilter(mockReq, mockRes);
}
@Test
@ -91,11 +91,12 @@ public class TestCrossOriginFilter {
String encodedResponseSplitOrigin =
CrossOriginFilter.encodeHeader(httpResponseSplitOrigin);
Assert.assertEquals("Http response split origin should be protected against",
validOrigin, encodedResponseSplitOrigin);
validOrigin, encodedResponseSplitOrigin);
// Test Origin List
String validOriginList = "http://foo.example.com:12345 http://bar.example.com:12345";
String encodedValidOriginList = CrossOriginFilter.encodeHeader(validOriginList);
String encodedValidOriginList = CrossOriginFilter
.encodeHeader(validOriginList);
Assert.assertEquals("Valid origin list encoding should match exactly",
validOriginList, encodedValidOriginList);
}
@ -135,20 +136,20 @@ public class TestCrossOriginFilter {
FilterConfig filterConfig = new FilterConfigTest(conf);
// Origin is not specified for same origin requests
HttpServletRequest mockReq = mock(HttpServletRequest.class);
when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.org");
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
Mockito.when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.org");
// Objects to verify interactions based on request
HttpServletResponse mockRes = mock(HttpServletResponse.class);
FilterChain mockChain = mock(FilterChain.class);
HttpServletResponse mockRes = Mockito.mock(HttpServletResponse.class);
FilterChain mockChain = Mockito.mock(FilterChain.class);
// Object under test
CrossOriginFilter filter = new CrossOriginFilter();
filter.init(filterConfig);
filter.doFilter(mockReq, mockRes, mockChain);
verifyZeroInteractions(mockRes);
verify(mockChain).doFilter(mockReq, mockRes);
Mockito.verifyZeroInteractions(mockRes);
Mockito.verify(mockChain).doFilter(mockReq, mockRes);
}
@Test
@ -160,22 +161,23 @@ public class TestCrossOriginFilter {
FilterConfig filterConfig = new FilterConfigTest(conf);
// Origin is not specified for same origin requests
HttpServletRequest mockReq = mock(HttpServletRequest.class);
when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
Mockito.when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
Mockito.when(
mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
.thenReturn("DISALLOWED_METHOD");
// Objects to verify interactions based on request
HttpServletResponse mockRes = mock(HttpServletResponse.class);
FilterChain mockChain = mock(FilterChain.class);
HttpServletResponse mockRes = Mockito.mock(HttpServletResponse.class);
FilterChain mockChain = Mockito.mock(FilterChain.class);
// Object under test
CrossOriginFilter filter = new CrossOriginFilter();
filter.init(filterConfig);
filter.doFilter(mockReq, mockRes, mockChain);
verifyZeroInteractions(mockRes);
verify(mockChain).doFilter(mockReq, mockRes);
Mockito.verifyZeroInteractions(mockRes);
Mockito.verify(mockChain).doFilter(mockReq, mockRes);
}
@Test
@ -187,24 +189,26 @@ public class TestCrossOriginFilter {
FilterConfig filterConfig = new FilterConfigTest(conf);
// Origin is not specified for same origin requests
HttpServletRequest mockReq = mock(HttpServletRequest.class);
when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
Mockito.when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
Mockito.when(
mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
.thenReturn("GET");
when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
Mockito.when(
mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
.thenReturn("Disallowed-Header");
// Objects to verify interactions based on request
HttpServletResponse mockRes = mock(HttpServletResponse.class);
FilterChain mockChain = mock(FilterChain.class);
HttpServletResponse mockRes = Mockito.mock(HttpServletResponse.class);
FilterChain mockChain = Mockito.mock(FilterChain.class);
// Object under test
CrossOriginFilter filter = new CrossOriginFilter();
filter.init(filterConfig);
filter.doFilter(mockReq, mockRes, mockChain);
verifyZeroInteractions(mockRes);
verify(mockChain).doFilter(mockReq, mockRes);
Mockito.verifyZeroInteractions(mockRes);
Mockito.verify(mockChain).doFilter(mockReq, mockRes);
}
@Test
@ -216,32 +220,34 @@ public class TestCrossOriginFilter {
FilterConfig filterConfig = new FilterConfigTest(conf);
// Origin is not specified for same origin requests
HttpServletRequest mockReq = mock(HttpServletRequest.class);
when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
HttpServletRequest mockReq = Mockito.mock(HttpServletRequest.class);
Mockito.when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
Mockito.when(
mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
.thenReturn("GET");
when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
Mockito.when(
mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
.thenReturn("X-Requested-With");
// Objects to verify interactions based on request
HttpServletResponse mockRes = mock(HttpServletResponse.class);
FilterChain mockChain = mock(FilterChain.class);
HttpServletResponse mockRes = Mockito.mock(HttpServletResponse.class);
FilterChain mockChain = Mockito.mock(FilterChain.class);
// Object under test
CrossOriginFilter filter = new CrossOriginFilter();
filter.init(filterConfig);
filter.doFilter(mockReq, mockRes, mockChain);
verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN,
Mockito.verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN,
"example.com");
verify(mockRes).setHeader(
Mockito.verify(mockRes).setHeader(
CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS,
Boolean.TRUE.toString());
verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_METHODS,
Mockito.verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_METHODS,
filter.getAllowedMethodsHeader());
verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_HEADERS,
Mockito.verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_HEADERS,
filter.getAllowedHeadersHeader());
verify(mockChain).doFilter(mockReq, mockRes);
Mockito.verify(mockChain).doFilter(mockReq, mockRes);
}
@Test

View File

@ -988,6 +988,8 @@ Release 2.7.2 - UNRELEASED
IMPROVEMENTS
YARN-4009. CORS support for ResourceManager REST API. ( Varun Vasudev via jeagles)
YARN-3170. YARN architecture document needs updating. (Brahma Reddy Battula
via ozawa)

View File

@ -337,6 +337,11 @@ public class YarnConfiguration extends Configuration {
public static final boolean DEFAULT_RM_WEBAPP_DELEGATION_TOKEN_AUTH_FILTER =
true;
/** Enable cross origin (CORS) support. **/
public static final String RM_WEBAPP_ENABLE_CORS_FILTER =
RM_PREFIX + "webapp.cross-origin.enabled";
public static final boolean DEFAULT_RM_WEBAPP_ENABLE_CORS_FILTER = false;
/** How long to wait until a container is considered dead.*/
public static final String RM_CONTAINER_ALLOC_EXPIRY_INTERVAL_MS =
RM_PREFIX + "rm.container-allocation.expiry-interval-ms";
@ -974,6 +979,11 @@ public class YarnConfiguration extends Configuration {
public static final String DEFAULT_NM_WEBAPP_HTTPS_ADDRESS = "0.0.0.0:"
+ DEFAULT_NM_WEBAPP_HTTPS_PORT;
/** Enable/disable CORS filter. */
public static final String NM_WEBAPP_ENABLE_CORS_FILTER =
NM_PREFIX + "webapp.cross-origin.enabled";
public static final boolean DEFAULT_NM_WEBAPP_ENABLE_CORS_FILTER = false;
/** How often to monitor resource in a node.*/
public static final String NM_RESOURCE_MON_INTERVAL_MS =
NM_PREFIX + "resource-monitor.interval-ms";

View File

@ -254,6 +254,14 @@
<value>true</value>
</property>
<property>
<description>Flag to enable cross-origin (CORS) support in the RM. This flag
requires the CORS filter initializer to be added to the filter initializers
list in core-site.xml.</description>
<name>yarn.resourcemanager.webapp.cross-origin.enabled</name>
<value>false</value>
</property>
<property>
<description>How long to wait until a node manager is considered dead.</description>
<name>yarn.nm.liveness-monitor.expiry-interval-ms</name>
@ -2317,6 +2325,14 @@
<value>false</value>
</property>
<property>
<description>Flag to enable cross-origin (CORS) support in the NM. This flag
requires the CORS filter initializer to be added to the filter initializers
list in core-site.xml.</description>
<name>yarn.nodemanager.webapp.cross-origin.enabled</name>
<value>false</value>
</property>
<property>
<description>
Defines maximum application priority in a cluster.

View File

@ -30,6 +30,7 @@ import org.apache.hadoop.http.HttpServer2;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.source.JvmMetrics;
import org.apache.hadoop.security.AuthenticationFilterInitializer;
import org.apache.hadoop.security.HttpCrossOriginFilterInitializer;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.service.CompositeService;
import org.apache.hadoop.service.Service;
@ -252,10 +253,17 @@ public class ApplicationHistoryServer extends CompositeService {
if(conf.getBoolean(YarnConfiguration
.TIMELINE_SERVICE_HTTP_CROSS_ORIGIN_ENABLED, YarnConfiguration
.TIMELINE_SERVICE_HTTP_CROSS_ORIGIN_ENABLED_DEFAULT)) {
if (initializers.length() != 0) {
initializers += ",";
if (initializers.contains(HttpCrossOriginFilterInitializer.class.getName())) {
initializers =
initializers.replaceAll(HttpCrossOriginFilterInitializer.class.getName(),
CrossOriginFilterInitializer.class.getName());
}
else {
if (initializers.length() != 0) {
initializers += ",";
}
initializers += CrossOriginFilterInitializer.class.getName();
}
initializers += CrossOriginFilterInitializer.class.getName();
modifiedInitializers = true;
}
}

View File

@ -18,35 +18,35 @@
package org.apache.hadoop.yarn.server.timeline.webapp;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.http.FilterContainer;
import org.apache.hadoop.http.FilterInitializer;
import org.apache.hadoop.security.HttpCrossOriginFilterInitializer;
import org.apache.hadoop.security.http.CrossOriginFilter;
public class CrossOriginFilterInitializer extends FilterInitializer {
import java.util.Map;
public class CrossOriginFilterInitializer extends HttpCrossOriginFilterInitializer {
public static final String PREFIX =
"yarn.timeline-service.http-cross-origin.";
@Override
protected String getPrefix() {
return PREFIX;
}
@Override
public void initFilter(FilterContainer container, Configuration conf) {
container.addGlobalFilter("Cross Origin Filter",
CrossOriginFilter.class.getName(), getFilterParameters(conf));
}
// setup the filter
// use the keys with "yarn.timeline-service.http-cross-origin" prefix to
// override the ones with the "hadoop.http.cross-origin" prefix.
static Map<String, String> getFilterParameters(Configuration conf) {
Map<String, String> filterParams =
new HashMap<String, String>();
for (Map.Entry<String, String> entry : conf.getValByRegex(PREFIX)
.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
name = name.substring(PREFIX.length());
filterParams.put(name, value);
}
return filterParams;
Map<String, String> filterParameters =
getFilterParameters(conf, HttpCrossOriginFilterInitializer.PREFIX);
filterParameters.putAll(getFilterParameters(conf, getPrefix()));
container.addGlobalFilter("Cross Origin Filter",
CrossOriginFilter.class.getName(), filterParameters);
}
}
}

View File

@ -81,6 +81,11 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>

View File

@ -22,6 +22,7 @@ import static org.apache.hadoop.yarn.util.StringHelper.pajoin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.security.HttpCrossOriginFilterInitializer;
import org.apache.hadoop.service.AbstractService;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
@ -59,7 +60,14 @@ public class WebServer extends AbstractService {
String bindAddress = WebAppUtils.getWebAppBindURL(getConfig(),
YarnConfiguration.NM_BIND_HOST,
WebAppUtils.getNMWebAppURLWithoutScheme(getConfig()));
boolean enableCors = getConfig()
.getBoolean(YarnConfiguration.NM_WEBAPP_ENABLE_CORS_FILTER,
YarnConfiguration.DEFAULT_NM_WEBAPP_ENABLE_CORS_FILTER);
if (enableCors) {
getConfig().setBoolean(HttpCrossOriginFilterInitializer.PREFIX
+ HttpCrossOriginFilterInitializer.ENABLED_SUFFIX, true);
}
LOG.info("Instantiating NMWebApp at " + bindAddress);
try {
this.webApp =

View File

@ -28,10 +28,7 @@ import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
import org.apache.hadoop.http.lib.StaticUserWebFilter;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.source.JvmMetrics;
import org.apache.hadoop.security.AuthenticationFilterInitializer;
import org.apache.hadoop.security.Groups;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.*;
import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.service.AbstractService;
@ -866,6 +863,9 @@ public class ResourceManager extends CompositeService implements Recoverable {
// 4. hadoop.http.filter.initializers container AuthenticationFilterInitializer
Configuration conf = getConfig();
boolean enableCorsFilter =
conf.getBoolean(YarnConfiguration.RM_WEBAPP_ENABLE_CORS_FILTER,
YarnConfiguration.DEFAULT_RM_WEBAPP_ENABLE_CORS_FILTER);
boolean useYarnAuthenticationFilter =
conf.getBoolean(
YarnConfiguration.RM_WEBAPP_DELEGATION_TOKEN_AUTH_FILTER,
@ -877,6 +877,12 @@ public class ResourceManager extends CompositeService implements Recoverable {
Class<?>[] initializersClasses =
conf.getClasses(filterInitializerConfKey);
// setup CORS
if (enableCorsFilter) {
conf.setBoolean(HttpCrossOriginFilterInitializer.PREFIX
+ HttpCrossOriginFilterInitializer.ENABLED_SUFFIX, true);
}
boolean hasHadoopAuthFilterInitializer = false;
boolean hasRMAuthFilterInitializer = false;
if (initializersClasses != null) {

View File

@ -16,6 +16,7 @@ NodeManager REST API's
=======================
* [Overview](#Overview)
* [Enabling CORS support](#Enabling_CORS_support)
* [NodeManager Information API](#NodeManager_Information_API)
* [Applications API](#Applications_API)
* [Application API](#Application_API)
@ -27,6 +28,13 @@ Overview
The NodeManager REST API's allow the user to get status on the node and information about applications and containers running on that node.
Enabling CORS support
---------------------
To enable cross-origin support (CORS) for the NM only(without enabling it for the RM), please set the following configuration parameters:
In core-site.xml, add org.apache.hadoop.security.HttpCrossOriginFilterInitializer to hadoop.http.filter.initializers.
In yarn-site.xml, set yarn.nodemanager.webapp.cross-origin.enabled to true.
NodeManager Information API
---------------------------
@ -540,4 +548,4 @@ Response Body:
<containerLogsLink>http://host.domain.com:8042/node/containerlogs/container_1326121700862_0007_01_000001/user1</containerLogsLink>
<nodeId>host.domain.com:8041</nodeId>
</container>
```
```

View File

@ -16,6 +16,7 @@ ResourceManager REST API's.
===========================
* [Overview](#Overview)
* [Enabling CORS support](#Enabling_CORS_support)
* [Cluster Information API](#Cluster_Information_API)
* [Cluster Metrics API](#Cluster_Metrics_API)
* [Cluster Scheduler API](#Cluster_Scheduler_API)
@ -38,6 +39,13 @@ Overview
The ResourceManager REST API's allow the user to get information about the cluster - status on the cluster, metrics on the cluster, scheduler information, information about nodes in the cluster, and information about applications on the cluster.
Enabling CORS support
---------------------
To enable cross-origin support (CORS) for the RM only(without enabling it for the NM), please set the following configuration parameters:
In core-site.xml, add org.apache.hadoop.security.HttpCrossOriginFilterInitializer to hadoop.http.filter.initializers.
In yarn-site.xml, set yarn.resourcemanager.webapp.cross-origin.enabled to true.
Cluster Information API
-----------------------