aboutsummaryrefslogtreecommitdiffstats
path: root/jdisc-security-filters/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'jdisc-security-filters/src/main/java')
-rw-r--r--jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java48
-rw-r--r--jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java9
-rw-r--r--jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java9
3 files changed, 45 insertions, 21 deletions
diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java
index e261f420e1c..f24778d1241 100644
--- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java
+++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java
@@ -2,15 +2,19 @@
package com.yahoo.jdisc.http.filter.security.cors;
import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.regex.Pattern;
/**
* @author bjorncs
*/
class CorsLogic {
- private CorsLogic() {}
static final String CORS_PREFLIGHT_REQUEST_CACHE_TTL = Long.toString(Duration.ofDays(7).getSeconds());
@@ -25,23 +29,49 @@ class CorsLogic {
"Vary", "*"
);
- static Map<String, String> createCorsResponseHeaders(String requestOriginHeader,
- Set<String> allowedOrigins) {
+ private final boolean allowAnyOrigin;
+ private final Set<String> allowedOrigins;
+ private final List<Pattern> allowedOriginPatterns;
+ private CorsLogic(boolean allowAnyOrigin, Set<String> allowedOrigins, List<Pattern> allowedOriginPatterns) {
+ this.allowAnyOrigin = allowAnyOrigin;
+ this.allowedOrigins = Set.copyOf(allowedOrigins);
+ this.allowedOriginPatterns = List.copyOf(allowedOriginPatterns);
+ }
+
+ boolean originMatches(String origin) {
+ if (allowAnyOrigin) return true;
+ if (allowedOrigins.contains(origin)) return true;
+ return allowedOriginPatterns.stream().anyMatch(pattern -> pattern.matcher(origin).matches());
+ }
+
+ Map<String, String> createCorsResponseHeaders(String requestOriginHeader) {
if (requestOriginHeader == null) return Map.of();
TreeMap<String, String> headers = new TreeMap<>();
- if (requestOriginMatchesAnyAllowed(requestOriginHeader, allowedOrigins))
+ if (originMatches(requestOriginHeader))
headers.put(ALLOW_ORIGIN_HEADER, requestOriginHeader);
headers.putAll(ACCESS_CONTROL_HEADERS);
return headers;
}
- static Map<String, String> createCorsPreflightResponseHeaders(String requestOriginHeader,
- Set<String> allowedOrigins) {
- return createCorsResponseHeaders(requestOriginHeader, allowedOrigins);
+ Map<String, String> preflightResponseHeaders(String requestOriginHeader) {
+ return createCorsResponseHeaders(requestOriginHeader);
}
- private static boolean requestOriginMatchesAnyAllowed(String requestOrigin, Set<String> allowedUrls) {
- return allowedUrls.stream().anyMatch(requestOrigin::equals) || allowedUrls.contains("*");
+ static CorsLogic forAllowedOrigins(Collection<String> allowedOrigins) {
+ Set<String> allowedOriginsVerbatim = new HashSet<>();
+ List<Pattern> allowedOriginPatterns = new ArrayList<>();
+ for (String allowedOrigin : allowedOrigins) {
+ if (allowedOrigin.isBlank()) continue;
+ if (allowedOrigin.length() > 0) {
+ if ("*".equals(allowedOrigin))
+ return new CorsLogic(true, Set.of(), List.of());
+ else if (allowedOrigin.contains("*"))
+ allowedOriginPatterns.add(Pattern.compile(allowedOrigin.replace(".", "\\.").replace("*", ".*")));
+ else
+ allowedOriginsVerbatim.add(allowedOrigin);
+ }
+ }
+ return new CorsLogic(false, allowedOriginsVerbatim, allowedOriginPatterns);
}
}
diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java
index e2efd2d220c..935e738b5e3 100644
--- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java
+++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java
@@ -10,8 +10,6 @@ import com.yahoo.jdisc.http.filter.DiscFilterRequest;
import com.yahoo.jdisc.http.filter.SecurityRequestFilter;
import com.yahoo.yolean.chain.Provides;
-import java.util.Set;
-
import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS;
/**
@@ -33,11 +31,11 @@ import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS;
*/
@Provides("CorsPreflightRequestFilter")
public class CorsPreflightRequestFilter implements SecurityRequestFilter {
- private final Set<String> allowedUrls;
+ private final CorsLogic cors;
@Inject
public CorsPreflightRequestFilter(CorsFilterConfig config) {
- this.allowedUrls = Set.copyOf(config.allowedUrls());
+ this.cors = CorsLogic.forAllowedOrigins(config.allowedUrls());
}
@Override
@@ -46,8 +44,7 @@ public class CorsPreflightRequestFilter implements SecurityRequestFilter {
return;
HttpResponse response = HttpResponse.newInstance(Response.Status.OK);
- String origin = discFilterRequest.getHeader("Origin");
- CorsLogic.createCorsPreflightResponseHeaders(origin, allowedUrls)
+ cors.preflightResponseHeaders(discFilterRequest.getHeader("Origin"))
.forEach(response.headers()::put);
ContentChannel cc = responseHandler.handleResponse(response);
diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java
index f56965ea6a8..4b6c7211d11 100644
--- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java
+++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java
@@ -8,9 +8,6 @@ import com.yahoo.jdisc.http.filter.RequestView;
import com.yahoo.jdisc.http.filter.SecurityResponseFilter;
import com.yahoo.yolean.chain.Provides;
-import java.util.Set;
-
-
/**
* @author gv
* @author Tony Vaagenes
@@ -19,16 +16,16 @@ import java.util.Set;
@Provides("CorsResponseFilter")
public class CorsResponseFilter extends AbstractResource implements SecurityResponseFilter {
- private final Set<String> allowedUrls;
+ private final CorsLogic cors;
@Inject
public CorsResponseFilter(CorsFilterConfig config) {
- this.allowedUrls = Set.copyOf(config.allowedUrls());
+ this.cors = CorsLogic.forAllowedOrigins(config.allowedUrls());
}
@Override
public void filter(DiscFilterResponse response, RequestView request) {
- CorsLogic.createCorsResponseHeaders(request.getFirstHeader("Origin").orElse(null), allowedUrls)
+ cors.createCorsResponseHeaders(request.getFirstHeader("Origin").orElse(null))
.forEach(response::setHeader);
}