From 8d10816667ceb5798389b95209f1ffd50205ecf5 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Mon, 9 Apr 2018 12:56:40 +0200 Subject: Change package name and class name of Cors filters * Change package name to 'com.yahoo.jdisc.filter.security.cors' * Remove 'Security' from names of Cors class names --- .../jdisc/http/filter/security/cors/CorsLogic.java | 56 +++++++++++ .../security/cors/CorsPreflightRequestFilter.java | 60 +++++++++++ .../security/cors/CorsRequestFilterBase.java | 81 +++++++++++++++ .../filter/security/cors/CorsResponseFilter.java | 36 +++++++ .../http/filter/security/cors/package-info.java | 8 ++ .../yahoo/jdisc/http/filters/cors/CorsLogic.java | 56 ----------- .../cors/CorsPreflightSecurityRequestFilter.java | 61 ----------- .../cors/CorsSecurityRequestFilterBase.java | 81 --------------- .../filters/cors/CorsSecurityResponseFilter.java | 38 ------- .../jdisc/http/filters/cors/package-info.java | 8 -- .../resources/configdefinitions/cors-filter.def | 4 + .../configdefinitions/cors-security-filter.def | 4 - .../cors/CorsPreflightRequestFilterTest.java | 78 ++++++++++++++ .../security/cors/CorsRequestFilterBaseTest.java | 60 +++++++++++ .../security/cors/CorsResponseFilterTest.java | 112 +++++++++++++++++++++ .../CorsPreflightSecurityRequestFilterTest.java | 78 -------------- .../cors/CorsSecurityRequestFilterBaseTest.java | 60 ----------- .../cors/CorsSecurityResponseFilterTest.java | 112 --------------------- 18 files changed, 495 insertions(+), 498 deletions(-) create mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java create mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java create mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBase.java create mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java create mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/package-info.java delete mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsLogic.java delete mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilter.java delete mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBase.java delete mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilter.java delete mode 100644 jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/package-info.java create mode 100644 jdisc-security-filters/src/main/resources/configdefinitions/cors-filter.def delete mode 100644 jdisc-security-filters/src/main/resources/configdefinitions/cors-security-filter.def create mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java create mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBaseTest.java create mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilterTest.java delete mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilterTest.java delete mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBaseTest.java delete mode 100644 jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilterTest.java (limited to 'jdisc-security-filters/src') 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 new file mode 100644 index 00000000000..54f1ee3042f --- /dev/null +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsLogic.java @@ -0,0 +1,56 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.google.common.collect.ImmutableMap; +import com.yahoo.jdisc.HeaderFields; +import com.yahoo.jdisc.Response; + +import java.time.Duration; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * @author bjorncs + */ +class CorsLogic { + private CorsLogic() {} + + static final String CORS_PREFLIGHT_REQUEST_CACHE_TTL = Long.toString(Duration.ofDays(7).getSeconds()); + + static final String ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin"; + + static final Map ACCESS_CONTROL_HEADERS = ImmutableMap.of( + "Access-Control-Max-Age", CORS_PREFLIGHT_REQUEST_CACHE_TTL, + "Access-Control-Allow-Headers", "Origin,Content-Type,Accept,Yahoo-Principal-Auth", + "Access-Control-Allow-Methods", "OPTIONS,GET,PUT,DELETE,POST", + "Access-Control-Allow-Credentials", "true" + ); + + static Map createCorsResponseHeaders(String requestOriginHeader, + Set allowedOrigins) { + if (requestOriginHeader == null) return Collections.emptyMap(); + TreeMap headers = new TreeMap<>(); + allowedOrigins.stream() + .filter(allowedUrl -> matchesRequestOrigin(requestOriginHeader, allowedUrl)) + .findAny() + .ifPresent(allowedOrigin -> headers.put(ALLOW_ORIGIN_HEADER, allowedOrigin)); + ACCESS_CONTROL_HEADERS.forEach(headers::put); + return headers; + } + + static Map createCorsPreflightResponseHeaders(String requestOriginHeader, + Set allowedOrigins) { + TreeMap headers = new TreeMap<>(); + if (allowedOrigins.contains(requestOriginHeader)) + headers.put(ALLOW_ORIGIN_HEADER, requestOriginHeader); + ACCESS_CONTROL_HEADERS.forEach(headers::put); + return headers; + } + + private static boolean matchesRequestOrigin(String requestOrigin, String allowedUrl) { + return allowedUrl.equals("*") || requestOrigin.startsWith(allowedUrl); + } +} 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 new file mode 100644 index 00000000000..6e14cbe8ac2 --- /dev/null +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilter.java @@ -0,0 +1,60 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.google.inject.Inject; +import com.yahoo.jdisc.Response; +import com.yahoo.jdisc.handler.ContentChannel; +import com.yahoo.jdisc.handler.ResponseHandler; +import com.yahoo.jdisc.http.HttpResponse; +import com.yahoo.jdisc.http.filter.DiscFilterRequest; +import com.yahoo.jdisc.http.filter.SecurityRequestFilter; +import com.yahoo.yolean.chain.Provides; + +import java.util.HashSet; +import java.util.Set; + +import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS; + +/** + *

+ * This filter makes sure we respond as quickly as possible to CORS pre-flight requests + * which browsers transmit before the Hosted Vespa dashboard code is allowed to send a "real" request. + *

+ *

+ * An "Access-Control-Max-Age" header is added so that the browser will cache the result of this pre-flight request, + * further improving the responsiveness of the Hosted Vespa dashboard application. + *

+ *

+ * Runs after all standard security request filters, but before BouncerFilter, as the browser does not send + * credentials with pre-flight requests. + *

+ * + * @author andreer + * @author gv + * @author bjorncs + */ +@Provides("CorsPreflightRequestFilter") +public class CorsPreflightRequestFilter implements SecurityRequestFilter { + private final Set allowedUrls; + + @Inject + public CorsPreflightRequestFilter(CorsFilterConfig config) { + this.allowedUrls = new HashSet<>(config.allowedUrls()); + } + + @Override + public void filter(DiscFilterRequest discFilterRequest, ResponseHandler responseHandler) { + String origin = discFilterRequest.getHeader("Origin"); + + if (!discFilterRequest.getMethod().equals(OPTIONS.name())) + return; + + HttpResponse response = HttpResponse.newInstance(Response.Status.OK); + + CorsLogic.createCorsPreflightResponseHeaders(origin, allowedUrls) + .forEach(response.headers()::put); + + ContentChannel cc = responseHandler.handleResponse(response); + cc.close(null); + } +} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBase.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBase.java new file mode 100644 index 00000000000..7bdbd7eddf4 --- /dev/null +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBase.java @@ -0,0 +1,81 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.yahoo.jdisc.Response; +import com.yahoo.jdisc.handler.FastContentWriter; +import com.yahoo.jdisc.handler.ResponseDispatch; +import com.yahoo.jdisc.handler.ResponseHandler; +import com.yahoo.jdisc.http.filter.DiscFilterRequest; +import com.yahoo.jdisc.http.filter.SecurityRequestFilter; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.createCorsResponseHeaders; + +/** + * Security request filters should extend this base class to ensure that CORS header are included in the response of a rejected request. + * This is required as response filter chains are not executed when a request is rejected in a request filter. + * + * @author bjorncs + */ +public abstract class CorsRequestFilterBase implements SecurityRequestFilter { + + private static final ObjectMapper mapper = new ObjectMapper(); + + private final Set allowedUrls; + + protected CorsRequestFilterBase(CorsFilterConfig config) { + this(new HashSet<>(config.allowedUrls())); + } + + protected CorsRequestFilterBase(Set allowedUrls) { + this.allowedUrls = allowedUrls; + } + + @Override + public final void filter(DiscFilterRequest request, ResponseHandler handler) { + filter(request) + .ifPresent(errorResponse -> sendErrorResponse(request, errorResponse, handler)); + } + + protected abstract Optional filter(DiscFilterRequest request); + + private void sendErrorResponse(DiscFilterRequest request, + ErrorResponse errorResponse, + ResponseHandler responseHandler) { + Response response = new Response(errorResponse.statusCode); + addHeaders(request, response); + writeResponse(errorResponse, responseHandler, response); + } + + private void addHeaders(DiscFilterRequest request, Response response) { + createCorsResponseHeaders(request.getHeader("Origin"), allowedUrls) + .forEach(response.headers()::add); + response.headers().add("Content-Type", "application/json"); + } + + private void writeResponse(ErrorResponse errorResponse, ResponseHandler responseHandler, Response response) { + ObjectNode errorMessage = mapper.createObjectNode(); + errorMessage.put("message", errorResponse.message); + try (FastContentWriter writer = ResponseDispatch.newInstance(response).connectFastWriter(responseHandler)) { + writer.write(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorMessage)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + protected static class ErrorResponse { + final int statusCode; + final String message; + + public ErrorResponse(int statusCode, String message) { + this.statusCode = statusCode; + this.message = message; + } + } +} 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 new file mode 100644 index 00000000000..d0b9e4ce7c9 --- /dev/null +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilter.java @@ -0,0 +1,36 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.google.inject.Inject; +import com.yahoo.jdisc.AbstractResource; +import com.yahoo.jdisc.http.filter.DiscFilterResponse; +import com.yahoo.jdisc.http.filter.RequestView; +import com.yahoo.jdisc.http.filter.SecurityResponseFilter; +import com.yahoo.yolean.chain.Provides; + +import java.util.HashSet; +import java.util.Set; + + +/** + * @author gv + * @author Tony Vaagenes + * @author bjorncs + */ +@Provides("CorsResponseFilter") +public class CorsResponseFilter extends AbstractResource implements SecurityResponseFilter { + + private final Set allowedUrls; + + @Inject + public CorsResponseFilter(CorsFilterConfig config) { + this.allowedUrls = new HashSet<>(config.allowedUrls()); + } + + @Override + public void filter(DiscFilterResponse response, RequestView request) { + CorsLogic.createCorsResponseHeaders(request.getFirstHeader("Origin").orElse(null), allowedUrls) + .forEach(response::setHeader); + } + +} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/package-info.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/package-info.java new file mode 100644 index 00000000000..cada3d3fcd8 --- /dev/null +++ b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filter/security/cors/package-info.java @@ -0,0 +1,8 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +/** + * @author bjorncs + */ +@ExportPackage +package com.yahoo.jdisc.http.filter.security.cors; + +import com.yahoo.osgi.annotation.ExportPackage; \ No newline at end of file diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsLogic.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsLogic.java deleted file mode 100644 index 3f1aeff9e95..00000000000 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsLogic.java +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.google.common.collect.ImmutableMap; -import com.yahoo.jdisc.HeaderFields; -import com.yahoo.jdisc.Response; - -import java.time.Duration; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -/** - * @author bjorncs - */ -class CorsLogic { - private CorsLogic() {} - - static final String CORS_PREFLIGHT_REQUEST_CACHE_TTL = Long.toString(Duration.ofDays(7).getSeconds()); - - static final String ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin"; - - static final Map ACCESS_CONTROL_HEADERS = ImmutableMap.of( - "Access-Control-Max-Age", CORS_PREFLIGHT_REQUEST_CACHE_TTL, - "Access-Control-Allow-Headers", "Origin,Content-Type,Accept,Yahoo-Principal-Auth", - "Access-Control-Allow-Methods", "OPTIONS,GET,PUT,DELETE,POST", - "Access-Control-Allow-Credentials", "true" - ); - - static Map createCorsResponseHeaders(String requestOriginHeader, - Set allowedOrigins) { - if (requestOriginHeader == null) return Collections.emptyMap(); - TreeMap headers = new TreeMap<>(); - allowedOrigins.stream() - .filter(allowedUrl -> matchesRequestOrigin(requestOriginHeader, allowedUrl)) - .findAny() - .ifPresent(allowedOrigin -> headers.put(ALLOW_ORIGIN_HEADER, allowedOrigin)); - ACCESS_CONTROL_HEADERS.forEach(headers::put); - return headers; - } - - static Map createCorsPreflightResponseHeaders(String requestOriginHeader, - Set allowedOrigins) { - TreeMap headers = new TreeMap<>(); - if (allowedOrigins.contains(requestOriginHeader)) - headers.put(ALLOW_ORIGIN_HEADER, requestOriginHeader); - ACCESS_CONTROL_HEADERS.forEach(headers::put); - return headers; - } - - private static boolean matchesRequestOrigin(String requestOrigin, String allowedUrl) { - return allowedUrl.equals("*") || requestOrigin.startsWith(allowedUrl); - } -} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilter.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilter.java deleted file mode 100644 index d162fff53b1..00000000000 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilter.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.google.inject.Inject; -import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.handler.ContentChannel; -import com.yahoo.jdisc.handler.ResponseHandler; -import com.yahoo.jdisc.http.HttpResponse; -import com.yahoo.jdisc.http.filter.DiscFilterRequest; -import com.yahoo.jdisc.http.filter.SecurityRequestFilter; -import com.yahoo.yolean.chain.Provides; - -import java.util.HashSet; -import java.util.Set; - -import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS; -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.createCorsPreflightResponseHeaders; - -/** - *

- * This filter makes sure we respond as quickly as possible to CORS pre-flight requests - * which browsers transmit before the Hosted Vespa dashboard code is allowed to send a "real" request. - *

- *

- * An "Access-Control-Max-Age" header is added so that the browser will cache the result of this pre-flight request, - * further improving the responsiveness of the Hosted Vespa dashboard application. - *

- *

- * Runs after all standard security request filters, but before BouncerFilter, as the browser does not send - * credentials with pre-flight requests. - *

- * - * @author andreer - * @author gv - * @author bjorncs - */ -@Provides("CorsPreflightSecurityRequestFilter") -public class CorsPreflightSecurityRequestFilter implements SecurityRequestFilter { - private final Set allowedUrls; - - @Inject - public CorsPreflightSecurityRequestFilter(CorsSecurityFilterConfig config) { - this.allowedUrls = new HashSet<>(config.allowedUrls()); - } - - @Override - public void filter(DiscFilterRequest discFilterRequest, ResponseHandler responseHandler) { - String origin = discFilterRequest.getHeader("Origin"); - - if (!discFilterRequest.getMethod().equals(OPTIONS.name())) - return; - - HttpResponse response = HttpResponse.newInstance(Response.Status.OK); - - createCorsPreflightResponseHeaders(origin, allowedUrls) - .forEach(response.headers()::put); - - ContentChannel cc = responseHandler.handleResponse(response); - cc.close(null); - } -} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBase.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBase.java deleted file mode 100644 index fd64aa37875..00000000000 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBase.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.handler.FastContentWriter; -import com.yahoo.jdisc.handler.ResponseDispatch; -import com.yahoo.jdisc.handler.ResponseHandler; -import com.yahoo.jdisc.http.filter.DiscFilterRequest; -import com.yahoo.jdisc.http.filter.SecurityRequestFilter; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.createCorsResponseHeaders; - -/** - * Security request filters should extend this base class to ensure that CORS header are included in the response of a rejected request. - * This is required as response filter chains are not executed when a request is rejected in a request filter. - * - * @author bjorncs - */ -public abstract class CorsSecurityRequestFilterBase implements SecurityRequestFilter { - - private static final ObjectMapper mapper = new ObjectMapper(); - - private final Set allowedUrls; - - protected CorsSecurityRequestFilterBase(CorsSecurityFilterConfig config) { - this(new HashSet<>(config.allowedUrls())); - } - - protected CorsSecurityRequestFilterBase(Set allowedUrls) { - this.allowedUrls = allowedUrls; - } - - @Override - public final void filter(DiscFilterRequest request, ResponseHandler handler) { - filter(request) - .ifPresent(errorResponse -> sendErrorResponse(request, errorResponse, handler)); - } - - protected abstract Optional filter(DiscFilterRequest request); - - private void sendErrorResponse(DiscFilterRequest request, - ErrorResponse errorResponse, - ResponseHandler responseHandler) { - Response response = new Response(errorResponse.statusCode); - addHeaders(request, response); - writeResponse(errorResponse, responseHandler, response); - } - - private void addHeaders(DiscFilterRequest request, Response response) { - createCorsResponseHeaders(request.getHeader("Origin"), allowedUrls) - .forEach(response.headers()::add); - response.headers().add("Content-Type", "application/json"); - } - - private void writeResponse(ErrorResponse errorResponse, ResponseHandler responseHandler, Response response) { - ObjectNode errorMessage = mapper.createObjectNode(); - errorMessage.put("message", errorResponse.message); - try (FastContentWriter writer = ResponseDispatch.newInstance(response).connectFastWriter(responseHandler)) { - writer.write(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(errorMessage)); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - protected static class ErrorResponse { - final int statusCode; - final String message; - - public ErrorResponse(int statusCode, String message) { - this.statusCode = statusCode; - this.message = message; - } - } -} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilter.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilter.java deleted file mode 100644 index bf288661bc4..00000000000 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.google.inject.Inject; -import com.yahoo.jdisc.AbstractResource; -import com.yahoo.jdisc.http.filter.DiscFilterResponse; -import com.yahoo.jdisc.http.filter.RequestView; -import com.yahoo.jdisc.http.filter.SecurityResponseFilter; -import com.yahoo.yolean.chain.Provides; - -import java.util.HashSet; -import java.util.Set; - -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.createCorsResponseHeaders; - - -/** - * @author gv - * @author Tony Vaagenes - * @author bjorncs - */ -@Provides("CorsSecurityResponseFilter") -public class CorsSecurityResponseFilter extends AbstractResource implements SecurityResponseFilter { - - private final Set allowedUrls; - - @Inject - public CorsSecurityResponseFilter(CorsSecurityFilterConfig config) { - this.allowedUrls = new HashSet<>(config.allowedUrls()); - } - - @Override - public void filter(DiscFilterResponse response, RequestView request) { - createCorsResponseHeaders(request.getFirstHeader("Origin").orElse(null), allowedUrls) - .forEach(response::setHeader); - } - -} diff --git a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/package-info.java b/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/package-info.java deleted file mode 100644 index 6357acc4e99..00000000000 --- a/jdisc-security-filters/src/main/java/com/yahoo/jdisc/http/filters/cors/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @author bjorncs - */ -@ExportPackage -package com.yahoo.jdisc.http.filters.cors; - -import com.yahoo.osgi.annotation.ExportPackage; \ No newline at end of file diff --git a/jdisc-security-filters/src/main/resources/configdefinitions/cors-filter.def b/jdisc-security-filters/src/main/resources/configdefinitions/cors-filter.def new file mode 100644 index 00000000000..a5c69b2db62 --- /dev/null +++ b/jdisc-security-filters/src/main/resources/configdefinitions/cors-filter.def @@ -0,0 +1,4 @@ +# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +namespace=jdisc.http.filter.security.cors + +allowedUrls[] string diff --git a/jdisc-security-filters/src/main/resources/configdefinitions/cors-security-filter.def b/jdisc-security-filters/src/main/resources/configdefinitions/cors-security-filter.def deleted file mode 100644 index 71d4b998b99..00000000000 --- a/jdisc-security-filters/src/main/resources/configdefinitions/cors-security-filter.def +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=jdisc.http.filters.cors - -allowedUrls[] string diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java new file mode 100644 index 00000000000..2486bc444c8 --- /dev/null +++ b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsPreflightRequestFilterTest.java @@ -0,0 +1,78 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.yahoo.jdisc.HeaderFields; +import com.yahoo.jdisc.Response; +import com.yahoo.jdisc.handler.ContentChannel; +import com.yahoo.jdisc.handler.ResponseHandler; +import com.yahoo.jdisc.http.filter.DiscFilterRequest; +import com.yahoo.jdisc.http.filter.SecurityRequestFilter; +import com.yahoo.jdisc.http.filter.security.cors.CorsFilterConfig.Builder; +import org.junit.Test; + +import java.util.Arrays; + +import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS; +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.ACCESS_CONTROL_HEADERS; +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.ALLOW_ORIGIN_HEADER; +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +/** + * @author gjoranv + * @author bjorncs + */ +public class CorsPreflightRequestFilterTest { + + @Test + public void any_options_request_yields_access_control_headers_in_response() { + HeaderFields headers = doFilterRequest(newRequestFilter(), "http://any.origin"); + ACCESS_CONTROL_HEADERS.keySet().forEach( + header -> assertFalse("Empty header: " + header, headers.getFirst(header).isEmpty())); + } + + @Test + public void allowed_request_origin_yields_allow_origin_header_in_response() { + final String ALLOWED_ORIGIN = "http://allowed.origin"; + HeaderFields headers = doFilterRequest(newRequestFilter(ALLOWED_ORIGIN), ALLOWED_ORIGIN); + assertEquals(ALLOWED_ORIGIN, headers.getFirst(ALLOW_ORIGIN_HEADER)); + } + + @Test + public void disallowed_request_origin_does_not_yield_allow_origin_header_in_response() { + HeaderFields headers = doFilterRequest(newRequestFilter("http://allowed.origin"), "http://disallowed.origin"); + assertNull(headers.getFirst(ALLOW_ORIGIN_HEADER)); + } + + private static HeaderFields doFilterRequest(SecurityRequestFilter filter, String originUrl) { + AccessControlResponseHandler responseHandler = new AccessControlResponseHandler(); + filter.filter(newOptionsRequest(originUrl), responseHandler); + return responseHandler.response.headers(); + } + + private static DiscFilterRequest newOptionsRequest(String origin) { + DiscFilterRequest request = mock(DiscFilterRequest.class); + when(request.getHeader("Origin")).thenReturn(origin); + when(request.getMethod()).thenReturn(OPTIONS.name()); + return request; + } + + private static CorsPreflightRequestFilter newRequestFilter(String... allowedOriginUrls) { + Builder builder = new Builder(); + Arrays.asList(allowedOriginUrls).forEach(builder::allowedUrls); + return new CorsPreflightRequestFilter(new CorsFilterConfig(builder)); + } + + private static class AccessControlResponseHandler implements ResponseHandler { + Response response; + + @Override + public ContentChannel handleResponse(Response response) { + this.response = response; + return mock(ContentChannel.class); + } + } + +} diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBaseTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBaseTest.java new file mode 100644 index 00000000000..29d28499a28 --- /dev/null +++ b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsRequestFilterBaseTest.java @@ -0,0 +1,60 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.yahoo.container.jdisc.RequestHandlerTestDriver.MockResponseHandler; +import com.yahoo.jdisc.Response; +import com.yahoo.jdisc.http.filter.DiscFilterRequest; +import org.junit.Test; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.ALLOW_ORIGIN_HEADER; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author bjorncs + */ +public class CorsRequestFilterBaseTest { + + @Test + public void adds_cors_headers_when_filter_reject_request() { + String origin = "http://allowed.origin"; + Set allowedOrigins = Collections.singleton(origin); + int statusCode = 403; + SimpleCorsRequestFilter filter = + new SimpleCorsRequestFilter(allowedOrigins, statusCode, "Forbidden"); + DiscFilterRequest request = mock(DiscFilterRequest.class); + when(request.getHeader("Origin")).thenReturn(origin); + MockResponseHandler responseHandler = new MockResponseHandler(); + filter.filter(request, responseHandler); + + Response response = responseHandler.getResponse(); + assertThat(response, notNullValue()); + assertThat(response.getStatus(), equalTo(statusCode)); + List allowOriginHeader = response.headers().get(ALLOW_ORIGIN_HEADER); + assertThat(allowOriginHeader.size(), equalTo(1)); + assertThat(allowOriginHeader.get(0), equalTo(origin)); + } + + private static class SimpleCorsRequestFilter extends CorsRequestFilterBase { + private final ErrorResponse errorResponse; + + SimpleCorsRequestFilter(Set allowedUrls, int statusCode, String message) { + super(allowedUrls); + this.errorResponse = new ErrorResponse(statusCode, message); + } + + @Override + protected Optional filter(DiscFilterRequest request) { + return Optional.ofNullable(this.errorResponse); + } + } + +} \ No newline at end of file diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilterTest.java new file mode 100644 index 00000000000..2967a7659f5 --- /dev/null +++ b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filter/security/cors/CorsResponseFilterTest.java @@ -0,0 +1,112 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jdisc.http.filter.security.cors; + +import com.yahoo.jdisc.http.Cookie; +import com.yahoo.jdisc.http.filter.DiscFilterResponse; +import com.yahoo.jdisc.http.filter.RequestView; +import com.yahoo.jdisc.http.filter.SecurityResponseFilter; +import com.yahoo.jdisc.http.filter.security.cors.CorsFilterConfig.Builder; +import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpResponse; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.ACCESS_CONTROL_HEADERS; +import static com.yahoo.jdisc.http.filter.security.cors.CorsLogic.ALLOW_ORIGIN_HEADER; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author gjoranv + * @author bjorncs + */ +public class CorsResponseFilterTest { + + @Test + public void any_request_yields_access_control_headers_in_response() { + Map headers = doFilterRequest(newResponseFilter(), "http://any.origin"); + ACCESS_CONTROL_HEADERS.keySet().forEach( + header -> assertFalse("Empty header: " + header, headers.get(header).isEmpty())); + } + + @Test + public void allowed_request_origin_yields_allow_origin_header_in_response() { + final String ALLOWED_ORIGIN = "http://allowed.origin"; + Map headers = doFilterRequest(newResponseFilter(ALLOWED_ORIGIN), ALLOWED_ORIGIN); + assertEquals(ALLOWED_ORIGIN, headers.get(ALLOW_ORIGIN_HEADER)); + } + + @Test + public void disallowed_request_origin_does_not_yield_allow_origin_header_in_response() { + Map headers = doFilterRequest(newResponseFilter("http://allowed.origin"), "http://disallowed.origin"); + assertNull(headers.get(ALLOW_ORIGIN_HEADER)); + } + + @Test + public void any_request_origin_yields_allow_origin_header_in_response_when_wildcard_is_allowed() { + Map headers = doFilterRequest(newResponseFilter("*"), "http://any.origin"); + assertEquals("*", headers.get(ALLOW_ORIGIN_HEADER)); + } + + private static Map doFilterRequest(SecurityResponseFilter filter, String originUrl) { + TestResponse response = new TestResponse(); + filter.filter(response, newRequestView(originUrl)); + return Collections.unmodifiableMap(response.headers); + } + + private static CorsResponseFilter newResponseFilter(String... allowedOriginUrls) { + Builder builder = new Builder(); + Arrays.asList(allowedOriginUrls).forEach(builder::allowedUrls); + return new CorsResponseFilter(new CorsFilterConfig(builder)); + } + + private static RequestView newRequestView(String originUrl) { + RequestView request = mock(RequestView.class); + when(request.getFirstHeader("Origin")).thenReturn(Optional.of(originUrl)); + return request; + } + + private static class TestResponse extends DiscFilterResponse { + Map headers = new HashMap<>(); + + TestResponse() { + super(mock(ServletOrJdiscHttpResponse.class)); + } + + @Override + public void setHeader(String name, String value) { + headers.put(name, value); + } + + @Override + public String getHeader(String name) { + return headers.get(name); + } + + @Override + public void removeHeaders(String s) { throw new UnsupportedOperationException(); } + + @Override + public void setHeaders(String s, String s1) { throw new UnsupportedOperationException(); } + + @Override + public void setHeaders(String s, List list) { throw new UnsupportedOperationException(); } + + @Override + public void addHeader(String s, String s1) { throw new UnsupportedOperationException(); } + + @Override + public void setCookies(List list) { throw new UnsupportedOperationException(); } + + @Override + public void setStatus(int i) { throw new UnsupportedOperationException(); } + } +} diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilterTest.java deleted file mode 100644 index cb934c32bee..00000000000 --- a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsPreflightSecurityRequestFilterTest.java +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.yahoo.jdisc.HeaderFields; -import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.handler.ContentChannel; -import com.yahoo.jdisc.handler.ResponseHandler; -import com.yahoo.jdisc.http.filter.DiscFilterRequest; -import com.yahoo.jdisc.http.filter.SecurityRequestFilter; -import com.yahoo.jdisc.http.filters.cors.CorsSecurityFilterConfig.Builder; -import org.junit.Test; - -import java.util.Arrays; - -import static com.yahoo.jdisc.http.HttpRequest.Method.OPTIONS; -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.ACCESS_CONTROL_HEADERS; -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.ALLOW_ORIGIN_HEADER; -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - - -/** - * @author gjoranv - * @author bjorncs - */ -public class CorsPreflightSecurityRequestFilterTest { - - @Test - public void any_options_request_yields_access_control_headers_in_response() { - HeaderFields headers = doFilterRequest(newRequestFilter(), "http://any.origin"); - ACCESS_CONTROL_HEADERS.keySet().forEach( - header -> assertFalse("Empty header: " + header, headers.getFirst(header).isEmpty())); - } - - @Test - public void allowed_request_origin_yields_allow_origin_header_in_response() { - final String ALLOWED_ORIGIN = "http://allowed.origin"; - HeaderFields headers = doFilterRequest(newRequestFilter(ALLOWED_ORIGIN), ALLOWED_ORIGIN); - assertEquals(ALLOWED_ORIGIN, headers.getFirst(ALLOW_ORIGIN_HEADER)); - } - - @Test - public void disallowed_request_origin_does_not_yield_allow_origin_header_in_response() { - HeaderFields headers = doFilterRequest(newRequestFilter("http://allowed.origin"), "http://disallowed.origin"); - assertNull(headers.getFirst(ALLOW_ORIGIN_HEADER)); - } - - private static HeaderFields doFilterRequest(SecurityRequestFilter filter, String originUrl) { - AccessControlResponseHandler responseHandler = new AccessControlResponseHandler(); - filter.filter(newOptionsRequest(originUrl), responseHandler); - return responseHandler.response.headers(); - } - - private static DiscFilterRequest newOptionsRequest(String origin) { - DiscFilterRequest request = mock(DiscFilterRequest.class); - when(request.getHeader("Origin")).thenReturn(origin); - when(request.getMethod()).thenReturn(OPTIONS.name()); - return request; - } - - private static CorsPreflightSecurityRequestFilter newRequestFilter(String... allowedOriginUrls) { - Builder builder = new Builder(); - Arrays.asList(allowedOriginUrls).forEach(builder::allowedUrls); - return new CorsPreflightSecurityRequestFilter(new CorsSecurityFilterConfig(builder)); - } - - private static class AccessControlResponseHandler implements ResponseHandler { - Response response; - - @Override - public ContentChannel handleResponse(Response response) { - this.response = response; - return mock(ContentChannel.class); - } - } - -} diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBaseTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBaseTest.java deleted file mode 100644 index 65fb78cdbd6..00000000000 --- a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityRequestFilterBaseTest.java +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.yahoo.container.jdisc.RequestHandlerTestDriver.MockResponseHandler; -import com.yahoo.jdisc.Response; -import com.yahoo.jdisc.http.filter.DiscFilterRequest; -import org.junit.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.ALLOW_ORIGIN_HEADER; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author bjorncs - */ -public class CorsSecurityRequestFilterBaseTest { - - @Test - public void adds_cors_headers_when_filter_reject_request() { - String origin = "http://allowed.origin"; - Set allowedOrigins = Collections.singleton(origin); - int statusCode = 403; - SimpleCorsSecurityRequestFilter filter = - new SimpleCorsSecurityRequestFilter(allowedOrigins, statusCode, "Forbidden"); - DiscFilterRequest request = mock(DiscFilterRequest.class); - when(request.getHeader("Origin")).thenReturn(origin); - MockResponseHandler responseHandler = new MockResponseHandler(); - filter.filter(request, responseHandler); - - Response response = responseHandler.getResponse(); - assertThat(response, notNullValue()); - assertThat(response.getStatus(), equalTo(statusCode)); - List allowOriginHeader = response.headers().get(ALLOW_ORIGIN_HEADER); - assertThat(allowOriginHeader.size(), equalTo(1)); - assertThat(allowOriginHeader.get(0), equalTo(origin)); - } - - private static class SimpleCorsSecurityRequestFilter extends CorsSecurityRequestFilterBase { - private final ErrorResponse errorResponse; - - SimpleCorsSecurityRequestFilter(Set allowedUrls, int statusCode, String message) { - super(allowedUrls); - this.errorResponse = new ErrorResponse(statusCode, message); - } - - @Override - protected Optional filter(DiscFilterRequest request) { - return Optional.ofNullable(this.errorResponse); - } - } - -} \ No newline at end of file diff --git a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilterTest.java b/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilterTest.java deleted file mode 100644 index cadc4b217b3..00000000000 --- a/jdisc-security-filters/src/test/java/com/yahoo/jdisc/http/filters/cors/CorsSecurityResponseFilterTest.java +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jdisc.http.filters.cors; - -import com.yahoo.jdisc.http.Cookie; -import com.yahoo.jdisc.http.filter.DiscFilterResponse; -import com.yahoo.jdisc.http.filter.RequestView; -import com.yahoo.jdisc.http.filter.SecurityResponseFilter; -import com.yahoo.jdisc.http.filters.cors.CorsSecurityFilterConfig.Builder; -import com.yahoo.jdisc.http.servlet.ServletOrJdiscHttpResponse; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.ACCESS_CONTROL_HEADERS; -import static com.yahoo.jdisc.http.filters.cors.CorsLogic.ALLOW_ORIGIN_HEADER; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author gjoranv - * @author bjorncs - */ -public class CorsSecurityResponseFilterTest { - - @Test - public void any_request_yields_access_control_headers_in_response() { - Map headers = doFilterRequest(newResponseFilter(), "http://any.origin"); - ACCESS_CONTROL_HEADERS.keySet().forEach( - header -> assertFalse("Empty header: " + header, headers.get(header).isEmpty())); - } - - @Test - public void allowed_request_origin_yields_allow_origin_header_in_response() { - final String ALLOWED_ORIGIN = "http://allowed.origin"; - Map headers = doFilterRequest(newResponseFilter(ALLOWED_ORIGIN), ALLOWED_ORIGIN); - assertEquals(ALLOWED_ORIGIN, headers.get(ALLOW_ORIGIN_HEADER)); - } - - @Test - public void disallowed_request_origin_does_not_yield_allow_origin_header_in_response() { - Map headers = doFilterRequest(newResponseFilter("http://allowed.origin"), "http://disallowed.origin"); - assertNull(headers.get(ALLOW_ORIGIN_HEADER)); - } - - @Test - public void any_request_origin_yields_allow_origin_header_in_response_when_wildcard_is_allowed() { - Map headers = doFilterRequest(newResponseFilter("*"), "http://any.origin"); - assertEquals("*", headers.get(ALLOW_ORIGIN_HEADER)); - } - - private static Map doFilterRequest(SecurityResponseFilter filter, String originUrl) { - TestResponse response = new TestResponse(); - filter.filter(response, newRequestView(originUrl)); - return Collections.unmodifiableMap(response.headers); - } - - private static CorsSecurityResponseFilter newResponseFilter(String... allowedOriginUrls) { - Builder builder = new Builder(); - Arrays.asList(allowedOriginUrls).forEach(builder::allowedUrls); - return new CorsSecurityResponseFilter(new CorsSecurityFilterConfig(builder)); - } - - private static RequestView newRequestView(String originUrl) { - RequestView request = mock(RequestView.class); - when(request.getFirstHeader("Origin")).thenReturn(Optional.of(originUrl)); - return request; - } - - private static class TestResponse extends DiscFilterResponse { - Map headers = new HashMap<>(); - - TestResponse() { - super(mock(ServletOrJdiscHttpResponse.class)); - } - - @Override - public void setHeader(String name, String value) { - headers.put(name, value); - } - - @Override - public String getHeader(String name) { - return headers.get(name); - } - - @Override - public void removeHeaders(String s) { throw new UnsupportedOperationException(); } - - @Override - public void setHeaders(String s, String s1) { throw new UnsupportedOperationException(); } - - @Override - public void setHeaders(String s, List list) { throw new UnsupportedOperationException(); } - - @Override - public void addHeader(String s, String s1) { throw new UnsupportedOperationException(); } - - @Override - public void setCookies(List list) { throw new UnsupportedOperationException(); } - - @Override - public void setStatus(int i) { throw new UnsupportedOperationException(); } - } -} -- cgit v1.2.3