HADOOP-14908. CrossOriginFilter should trigger regex on more input (Johannes Alberti via aw)
This commit is contained in:
parent
4111e6c781
commit
4d5dd75b60
@ -37,6 +37,7 @@
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -66,6 +67,7 @@ public class CrossOriginFilter implements Filter {
|
||||
// Filter configuration
|
||||
public static final String ALLOWED_ORIGINS = "allowed-origins";
|
||||
public static final String ALLOWED_ORIGINS_DEFAULT = "*";
|
||||
public static final String ALLOWED_ORIGINS_REGEX_PREFIX = "regex:";
|
||||
public static final String ALLOWED_METHODS = "allowed-methods";
|
||||
public static final String ALLOWED_METHODS_DEFAULT = "GET,POST,HEAD";
|
||||
public static final String ALLOWED_HEADERS = "allowed-headers";
|
||||
@ -194,6 +196,12 @@ private void initializeAllowedOrigins(FilterConfig filterConfig) {
|
||||
allowAllOrigins = allowedOrigins.contains("*");
|
||||
LOG.info("Allowed Origins: " + StringUtils.join(allowedOrigins, ','));
|
||||
LOG.info("Allow All Origins: " + allowAllOrigins);
|
||||
List<String> discouragedAllowedOrigins = allowedOrigins.stream()
|
||||
.filter(s -> s.length() > 1 && s.contains("*"))
|
||||
.collect(Collectors.toList());
|
||||
for (String discouragedAllowedOrigin : discouragedAllowedOrigins) {
|
||||
LOG.warn("Allowed Origin pattern '" + discouragedAllowedOrigin + "' is discouraged, use the 'regex:' prefix and use a Java regular expression instead.");
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeMaxAge(FilterConfig filterConfig) {
|
||||
@ -228,13 +236,18 @@ boolean areOriginsAllowed(String originsList) {
|
||||
String[] origins = originsList.trim().split("\\s+");
|
||||
for (String origin : origins) {
|
||||
for (String allowedOrigin : allowedOrigins) {
|
||||
if (allowedOrigin.contains("*")) {
|
||||
Pattern regexPattern = null;
|
||||
if (allowedOrigin.startsWith(ALLOWED_ORIGINS_REGEX_PREFIX)) {
|
||||
String regex = allowedOrigin.substring(ALLOWED_ORIGINS_REGEX_PREFIX.length());
|
||||
regexPattern = Pattern.compile(regex);
|
||||
} else if (allowedOrigin.contains("*")) {
|
||||
String regex = allowedOrigin.replace(".", "\\.").replace("*", ".*");
|
||||
Pattern p = Pattern.compile(regex);
|
||||
Matcher m = p.matcher(origin);
|
||||
if (m.matches()) {
|
||||
return true;
|
||||
regexPattern = Pattern.compile(regex);
|
||||
}
|
||||
|
||||
if (regexPattern != null
|
||||
&& regexPattern.matcher(origin).matches()) {
|
||||
return true;
|
||||
} else if (allowedOrigin.equals(origin)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1861,9 +1861,15 @@
|
||||
<property>
|
||||
<name>hadoop.http.cross-origin.allowed-origins</name>
|
||||
<value>*</value>
|
||||
<description>Comma separated list of origins that are allowed for web
|
||||
services needing cross-origin (CORS) support. Wildcards (*) and patterns
|
||||
allowed</description>
|
||||
<description>Comma separated list of origins that are allowed for web services
|
||||
needing cross-origin (CORS) support. If a value in the list contains an
|
||||
asterix (*), a regex pattern, escaping any dots ('.' -> '\.') and replacing
|
||||
the asterix such that it captures any characters ('*' -> '.*'), is generated.
|
||||
Values prefixed with 'regex:' are interpreted directly as regular expressions,
|
||||
e.g. use the expression 'regex:https?:\/\/foo\.bar:([0-9]+)?' to allow any
|
||||
origin using the 'http' or 'https' protocol in the domain 'foo.bar' on any
|
||||
port. The use of simple wildcards ('*') is discouraged, and only available for
|
||||
backward compatibility.</description>
|
||||
</property>
|
||||
|
||||
<property>
|
||||
|
@ -60,7 +60,7 @@ Add org.apache.hadoop.security.HttpCrossOriginFilterInitializer to hadoop.http.f
|
||||
| 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-origins | `*` | Comma separated list of origins that are allowed. Values prefixed with `regex:` are interpreted as regular expressions. Values containing wildcards (`*`) are possible as well, here a regular expression is generated, the use is discouraged and support is only available for backward compatibility. |
|
||||
| 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 |
|
||||
|
@ -127,6 +127,85 @@ public void testPatternMatchingOrigins() throws ServletException, IOException {
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo.nomatch1.com foo.nomatch2.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexPatternMatchingOrigins() throws ServletException, IOException {
|
||||
|
||||
// Setup the configuration settings of the server
|
||||
Map<String, String> conf = new HashMap<String, String>();
|
||||
conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "regex:.*[.]example[.]com");
|
||||
FilterConfig filterConfig = new FilterConfigTest(conf);
|
||||
|
||||
// Object under test
|
||||
CrossOriginFilter filter = new CrossOriginFilter();
|
||||
filter.init(filterConfig);
|
||||
|
||||
// match multiple sub-domains
|
||||
Assert.assertFalse(filter.areOriginsAllowed("example.com"));
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo:example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.bar.example.com"));
|
||||
|
||||
// First origin is allowed
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.example.com foo.nomatch.com"));
|
||||
// Second origin is allowed
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.nomatch.com foo.example.com"));
|
||||
// No origin in list is allowed
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo.nomatch1.com foo.nomatch2.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexRegexPatternMatchingOrigins() throws ServletException, IOException {
|
||||
|
||||
// Setup the configuration settings of the server
|
||||
Map<String, String> conf = new HashMap<String, String>();
|
||||
conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "regex:https?:\\/\\/sub1[.]example[.]com(:[0-9]+)?");
|
||||
FilterConfig filterConfig = new FilterConfigTest(conf);
|
||||
|
||||
// Object under test
|
||||
CrossOriginFilter filter = new CrossOriginFilter();
|
||||
filter.init(filterConfig);
|
||||
|
||||
Assert.assertTrue(filter.areOriginsAllowed("http://sub1.example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("https://sub1.example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("http://sub1.example.com:1234"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("https://sub1.example.com:8080"));
|
||||
|
||||
// No origin in list is allowed
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo.nomatch1.com foo.nomatch2.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedRegexPatternMatchingOrigins() throws ServletException, IOException {
|
||||
|
||||
// Setup the configuration settings of the server
|
||||
Map<String, String> conf = new HashMap<String, String>();
|
||||
conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "regex:https?:\\/\\/sub1[.]example[.]com(:[0-9]+)?, "
|
||||
+ "*.example2.com");
|
||||
FilterConfig filterConfig = new FilterConfigTest(conf);
|
||||
|
||||
// Object under test
|
||||
CrossOriginFilter filter = new CrossOriginFilter();
|
||||
filter.init(filterConfig);
|
||||
|
||||
Assert.assertTrue(filter.areOriginsAllowed("http://sub1.example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("https://sub1.example.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("http://sub1.example.com:1234"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("https://sub1.example.com:8080"));
|
||||
|
||||
// match multiple sub-domains
|
||||
Assert.assertFalse(filter.areOriginsAllowed("example2.com"));
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo:example2.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.example2.com"));
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.bar.example2.com"));
|
||||
|
||||
// First origin is allowed
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.example2.com foo.nomatch.com"));
|
||||
// Second origin is allowed
|
||||
Assert.assertTrue(filter.areOriginsAllowed("foo.nomatch.com foo.example2.com"));
|
||||
// No origin in list is allowed
|
||||
Assert.assertFalse(filter.areOriginsAllowed("foo.nomatch1.com foo.nomatch2.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisallowedOrigin() throws ServletException, IOException {
|
||||
|
||||
|
@ -156,7 +156,7 @@ and cluster operators.
|
||||
| `yarn.timeline-service.webapp.https.address` | The https address of the Timeline service web application. Defaults to `${yarn.timeline-service.hostname}:8190`. |
|
||||
| `yarn.timeline-service.bind-host` | The actual address the server will bind to. If this optional address is set, the RPC and webapp servers will bind to this address and the port specified in `yarn.timeline-service.address` and `yarn.timeline-service.webapp.address`, respectively. This is most useful for making the service listen on all interfaces by setting to `0.0.0.0`. |
|
||||
| `yarn.timeline-service.http-cross-origin.enabled` | Enables cross-origin support (CORS) for web services where cross-origin web response headers are needed. For example, javascript making a web services request to the timeline server. Defaults to `false`. |
|
||||
| `yarn.timeline-service.http-cross-origin.allowed-origins` | Comma separated list of origins that are allowed for web services needing cross-origin (CORS) support. Wildcards `(*)` and patterns allowed. Defaults to `*`. |
|
||||
| `yarn.timeline-service.http-cross-origin.allowed-origins` | Comma separated list of origins that are allowed. Values prefixed with `regex:` are interpreted as regular expressions. Values containing wildcards (`*`) are possible as well, here a regular expression is generated, the use is discouraged and support is only available for backward compatibility. Defaults to `*`. |
|
||||
| `yarn.timeline-service.http-cross-origin.allowed-methods` | Comma separated list of methods that are allowed for web services needing cross-origin (CORS) support. Defaults to `GET,POST,HEAD`. |
|
||||
| `yarn.timeline-service.http-cross-origin.allowed-headers` | Comma separated list of headers that are allowed for web services needing cross-origin (CORS) support. Defaults to `X-Requested-With,Content-Type,Accept,Origin`. |
|
||||
| `yarn.timeline-service.http-cross-origin.max-age` | The number of seconds a pre-flighted request can be cached for web services needing cross-origin (CORS) support. Defaults to `1800`. |
|
||||
|
Loading…
Reference in New Issue
Block a user