This is an automated email from the ASF dual-hosted git repository. mgrigorov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/wicket.git
commit f8fa5f99eaf44d8614d5bc8f15c0876f3a85b86d Author: Martin Tzvetanov Grigorov <[email protected]> AuthorDate: Sun Mar 8 07:28:01 2020 +0200 WICKET-6747 Rename ContentSecurityPolicyEnforcer to ContentSecurityPolicySettings + some minor improvements in CSP related classes --- .../java/org/apache/wicket/csp/CSPDirective.java | 2 +- .../wicket/csp/CSPDirectiveSandboxValue.java | 8 +- .../apache/wicket/csp/CSPDirectiveSrcValue.java | 12 +- .../apache/wicket/csp/CSPHeaderConfiguration.java | 15 +- .../java/org/apache/wicket/csp/CSPHeaderMode.java | 4 +- .../csp/CSPNonceHeaderResponseDecorator.java | 4 +- .../java/org/apache/wicket/csp/CSPRenderable.java | 10 +- ...cer.java => ContentSecurityPolicySettings.java} | 458 +++++++++++---------- .../java/org/apache/wicket/csp/FixedCSPValue.java | 8 +- .../org/apache/wicket/csp/RelativeURICSPValue.java | 8 +- .../wicket/csp/ReportCSPViolationMapper.java | 11 +- .../org/apache/wicket/mock/MockApplication.java | 2 +- .../wicket/protocol/http/WebApplication.java | 34 +- .../csp/CSPSettingRequestCycleListenerTest.java | 86 ++-- .../head/filter/FilteringHeaderResponseTest.java | 8 +- .../wicket/examples/WicketExampleApplication.java | 7 +- .../MyAuthenticatedWebApplication.java | 10 +- .../wicket/examples/images/ImagesApplication.java | 2 +- .../wicket/examples/media/VideosApplication.java | 6 +- .../examples/websocket/JSR356Application.java | 3 +- .../src/main/asciidoc/security/security_6.adoc | 8 +- 21 files changed, 353 insertions(+), 353 deletions(-) diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java index a73ec66..c998f41 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirective.java @@ -120,7 +120,7 @@ public enum CSPDirective private String value; - private CSPDirective(String value) + CSPDirective(String value) { this.value = value; } diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java index d42d72b..b821040 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSandboxValue.java @@ -30,9 +30,9 @@ public enum CSPDirectiveSandboxValue implements CSPRenderable ALLOW_TOP_NAVIGATION("allow-top-navigation"), EMPTY(""); - private String value; + private final String value; - private CSPDirectiveSandboxValue(String value) + CSPDirectiveSandboxValue(String value) { this.value = value; } @@ -43,8 +43,8 @@ public enum CSPDirectiveSandboxValue implements CSPRenderable } @Override - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return value; } diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java index e897849..b186d8d 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPDirectiveSrcValue.java @@ -33,23 +33,23 @@ public enum CSPDirectiveSrcValue implements CSPRenderable NONCE("'nonce-%1$s'") { @Override - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return String.format(getValue(), listener.getNonce(cycle, currentHandler)); } }; - private String value; + private final String value; - private CSPDirectiveSrcValue(String value) + CSPDirectiveSrcValue(String value) { this.value = value; } @Override - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return value; } diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java index 65ee300..cef5091 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderConfiguration.java @@ -56,7 +56,7 @@ public class CSPHeaderConfiguration { public static final String CSP_VIOLATION_REPORTING_URI = "cspviolation"; - private Map<CSPDirective, List<CSPRenderable>> directives = new EnumMap<>(CSPDirective.class); + private final Map<CSPDirective, List<CSPRenderable>> directives = new EnumMap<>(CSPDirective.class); private boolean addLegacyHeaders = false; @@ -64,10 +64,6 @@ public class CSPHeaderConfiguration private String reportUriMountPath = null; - public CSPHeaderConfiguration() - { - } - /** * Removes all directives from the CSP, returning an empty configuration. * @@ -301,7 +297,7 @@ public class CSPHeaderConfiguration return this; } - private CSPHeaderConfiguration doAddDirective(CSPDirective directive, CSPRenderable value) + private void doAddDirective(CSPDirective directive, CSPRenderable value) { // Add backwards compatible frame-src // see http://caniuse.com/#feat=contentsecuritypolicy2 @@ -313,7 +309,6 @@ public class CSPHeaderConfiguration List<CSPRenderable> values = directives.computeIfAbsent(directive, x -> new ArrayList<>()); directive.checkValueForDirective(value, values); values.add(value); - return this; } /** @@ -321,15 +316,15 @@ public class CSPHeaderConfiguration * in the form {@code "key1 value1a value1b; key2 value2a; key3 value3a value3b value3c"}. * * @param listener - * The {@link ContentSecurityPolicyEnforcer} that renders the header. + * The {@link ContentSecurityPolicySettings} that renders the header. * @param cycle * The current {@link RequestCycle}. * @param currentHandler * The handler that is currently being evaluated or executed. * @return the rendered header. */ - public String renderHeaderValue(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String renderHeaderValue(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return directives.entrySet() .stream() diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java index 48a3a95..8b5e7f3 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPHeaderMode.java @@ -28,7 +28,7 @@ public enum CSPHeaderMode private final String header; - private CSPHeaderMode(String header) + CSPHeaderMode(String header) { this.header = header; } @@ -42,4 +42,4 @@ public enum CSPHeaderMode { return "X-" + getHeader(); } -} \ No newline at end of file +} diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPNonceHeaderResponseDecorator.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPNonceHeaderResponseDecorator.java index 8424182..46f7847 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPNonceHeaderResponseDecorator.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPNonceHeaderResponseDecorator.java @@ -29,9 +29,9 @@ import org.apache.wicket.request.cycle.RequestCycle; */ public class CSPNonceHeaderResponseDecorator extends DecoratingHeaderResponse { - private ContentSecurityPolicyEnforcer listener; + private final ContentSecurityPolicySettings listener; - public CSPNonceHeaderResponseDecorator(IHeaderResponse real, ContentSecurityPolicyEnforcer listener) + public CSPNonceHeaderResponseDecorator(IHeaderResponse real, ContentSecurityPolicySettings listener) { super(real); diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java b/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java index 0663490..4004bfb 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/CSPRenderable.java @@ -34,15 +34,15 @@ public interface CSPRenderable * Renders the value that should be put in the CSP header. * * @param listener - * The {@link ContentSecurityPolicyEnforcer} that renders this value. + * The {@link ContentSecurityPolicySettings} that renders this value. * @param cycle * The current {@link RequestCycle}. * @param currentHandler * The handler that is currently being evaluated or executed. * @return The rendered value. */ - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler); + String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler); /** * Checks if the {@code CSPRenderable} represents a valid value for a {@code -src} directive. By @@ -51,7 +51,7 @@ public interface CSPRenderable * @throws IllegalStateException * when this {@code CSPRenderable} represents an invalid value. */ - public default void checkValidityForSrc() + default void checkValidityForSrc() { } -} \ No newline at end of file +} diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicyEnforcer.java b/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java similarity index 84% rename from wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicyEnforcer.java rename to wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java index 54ca9e5..2c852ad 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicyEnforcer.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java @@ -1,227 +1,231 @@ -/* - * 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.wicket.csp; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Predicate; - -import org.apache.wicket.Application; -import org.apache.wicket.MetaDataKey; -import org.apache.wicket.Page; -import org.apache.wicket.core.request.handler.BufferedResponseRequestHandler; -import org.apache.wicket.core.request.handler.IPageClassRequestHandler; -import org.apache.wicket.core.request.handler.IPageRequestHandler; -import org.apache.wicket.request.IRequestHandler; -import org.apache.wicket.request.IRequestHandlerDelegate; -import org.apache.wicket.request.cycle.IRequestCycleListener; -import org.apache.wicket.request.cycle.RequestCycle; -import org.apache.wicket.request.http.WebResponse; -import org.apache.wicket.settings.SecuritySettings; -import org.apache.wicket.util.lang.Args; - -/** - * An {@link IRequestCycleListener} that adds {@code Content-Security-Policy} and/or - * {@code Content-Security-Policy-Report-Only} headers based on the supplied configuration. - * - * Build the CSP configuration like this: - * - * <pre> - * {@code - * myApplication.getCSP().blocking().clear() - * .add(CSPDirective.DEFAULT_SRC, CSPDirectiveSrcValue.NONE) - * .add(CSPDirective.SCRIPT_SRC, CSPDirectiveSrcValue.SELF) - * .add(CSPDirective.IMG_SRC, CSPDirectiveSrcValue.SELF) - * .add(CSPDirective.FONT_SRC, CSPDirectiveSrcValue.SELF)); - * - * myApplication.getCSP().reporting().strict(); - * } - * </pre> - * - * See {@link CSPHeaderConfiguration} for more details on specifying the configuration. - * - * @see <a href="https://www.w3.org/TR/CSP2/">https://www.w3.org/TR/CSP2</a> - * @see <a href= - * "https://developer.mozilla.org/en-US/docs/Web/Security/CSP">https://developer.mozilla.org/en-US/docs/Web/Security/CSP</a> - * - * @author Sven Haster - * @author Emond Papegaaij - */ -public class ContentSecurityPolicyEnforcer implements IRequestCycleListener -{ - // The number of bytes to use for a nonce, 12 will result in a 16 char nonce. - private static final int NONCE_LENGTH = 12; - - public static MetaDataKey<String> NONCE_KEY = new MetaDataKey<>() - { - private static final long serialVersionUID = 1L; - }; - - private final Application application; - - private Map<CSPHeaderMode, CSPHeaderConfiguration> configs = new HashMap<>(); - - private Predicate<IPageClassRequestHandler> protectedPageFilter = handler -> true; - - public ContentSecurityPolicyEnforcer(Application application) - { - this.application = Args.notNull(application, "application"); - } - - public CSPHeaderConfiguration blocking() - { - return configs.computeIfAbsent(CSPHeaderMode.BLOCKING, x -> new CSPHeaderConfiguration()); - } - - public CSPHeaderConfiguration reporting() - { - return configs.computeIfAbsent(CSPHeaderMode.REPORT_ONLY, x -> new CSPHeaderConfiguration()); - } - - /** - * Sets the predicate that determines which requests must be protected by the CSP. When the - * predicate evaluates to false, the request for the page will not be protected. - * - * @param protectedPageFilter - * The new filter, must not be null. - * @return {@code this} for chaining. - */ - public ContentSecurityPolicyEnforcer - setProtectedPageFilter(Predicate<IPageClassRequestHandler> protectedPageFilter) - { - Args.notNull(protectedPageFilter, "protectedPageFilter"); - this.protectedPageFilter = protectedPageFilter; - return this; - } - - protected boolean mustProtect(IRequestHandler handler) - { - if (handler instanceof IRequestHandlerDelegate) - { - return mustProtect(((IRequestHandlerDelegate) handler).getDelegateHandler()); - } - if (handler instanceof IPageClassRequestHandler) - { - return mustProtectPageRequest((IPageClassRequestHandler) handler); - } - return !(handler instanceof BufferedResponseRequestHandler); - } - - protected boolean mustProtectPageRequest(IPageClassRequestHandler handler) - { - return protectedPageFilter.test(handler); - } - - @Override - public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) - { - if (!mustProtect(handler) || !(cycle.getResponse() instanceof WebResponse)) - { - return; - } - - WebResponse webResponse = (WebResponse) cycle.getResponse(); - if (!webResponse.isHeaderSupported()) - { - return; - } - - configs.entrySet().stream().filter(entry -> entry.getValue().isSet()).forEach(entry -> { - CSPHeaderMode mode = entry.getKey(); - CSPHeaderConfiguration config = entry.getValue(); - String headerValue = config.renderHeaderValue(this, cycle, handler); - webResponse.setHeader(mode.getHeader(), headerValue); - if (config.isAddLegacyHeaders()) - { - webResponse.setHeader(mode.getLegacyHeader(), headerValue); - } - }); - } - - /** - * Returns true if any of the headers includes a directive with a nonce. - * - * @return If a nonce is used in the CSP. - */ - public boolean isNonceEnabled() - { - return configs.values().stream().anyMatch(CSPHeaderConfiguration::isNonceEnabled); - } - - public String getNonce(RequestCycle cycle, IRequestHandler handler) - { - String nonce = cycle.getMetaData(NONCE_KEY); - Page currentPage = getPage(handler); - if (nonce == null) - { - if (currentPage != null) - { - nonce = currentPage.getMetaData(NONCE_KEY); - } - if (nonce == null) - { - nonce = getSecuritySettings().getRandomSupplier().getRandomBase64(NONCE_LENGTH); - } - cycle.setMetaData(NONCE_KEY, nonce); - } - if (currentPage != null) - { - currentPage.setMetaData(NONCE_KEY, nonce); - } - return nonce; - } - - /** - * Resolves a page instance from the request handler iff the page instance is already created - * - * @param handler - * @return page or {@code null} if none - */ - public static Page getPage(IRequestHandler handler) - { - while (handler instanceof IRequestHandlerDelegate) - { - handler = ((IRequestHandlerDelegate) handler).getDelegateHandler(); - } - - if (handler instanceof IPageRequestHandler) - { - IPageRequestHandler pageHandler = (IPageRequestHandler) handler; - if (pageHandler.isPageInstanceCreated()) - { - return (Page) pageHandler.getPage(); - } - } - return null; - } - - private SecuritySettings getSecuritySettings() - { - return application.getSecuritySettings(); - } - - /** - * Returns the CSP configuration per {@link CSPHeaderMode}. - * - * @return the CSP configuration per {@link CSPHeaderMode}. - */ - public Map<CSPHeaderMode, CSPHeaderConfiguration> getConfiguration() - { - return Collections.unmodifiableMap(configs); - } -} +/* + * 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.wicket.csp; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; +import java.util.function.Predicate; + +import org.apache.wicket.Application; +import org.apache.wicket.MetaDataKey; +import org.apache.wicket.Page; +import org.apache.wicket.core.request.handler.BufferedResponseRequestHandler; +import org.apache.wicket.core.request.handler.IPageClassRequestHandler; +import org.apache.wicket.core.request.handler.IPageRequestHandler; +import org.apache.wicket.request.IRequestHandler; +import org.apache.wicket.request.IRequestHandlerDelegate; +import org.apache.wicket.request.cycle.IRequestCycleListener; +import org.apache.wicket.request.cycle.RequestCycle; +import org.apache.wicket.request.http.WebResponse; +import org.apache.wicket.settings.SecuritySettings; +import org.apache.wicket.util.lang.Args; + +/** + * An {@link IRequestCycleListener} that adds {@code Content-Security-Policy} and/or + * {@code Content-Security-Policy-Report-Only} headers based on the supplied configuration. + * + * Build the CSP configuration like this: + * + * <pre> + * {@code + * myApplication.getCspSettings().blocking().clear() + * .add(CSPDirective.DEFAULT_SRC, CSPDirectiveSrcValue.NONE) + * .add(CSPDirective.SCRIPT_SRC, CSPDirectiveSrcValue.SELF) + * .add(CSPDirective.IMG_SRC, CSPDirectiveSrcValue.SELF) + * .add(CSPDirective.FONT_SRC, CSPDirectiveSrcValue.SELF)); + * + * myApplication.getCspSettings().reporting().strict(); + * } + * </pre> + * + * See {@link CSPHeaderConfiguration} for more details on specifying the configuration. + * + * @see <a href="https://www.w3.org/TR/CSP2/">https://www.w3.org/TR/CSP2</a> + * @see <a href= + * "https://developer.mozilla.org/en-US/docs/Web/Security/CSP">https://developer.mozilla.org/en-US/docs/Web/Security/CSP</a> + * + * @author Sven Haster + * @author Emond Papegaaij + */ +public class ContentSecurityPolicySettings implements IRequestCycleListener +{ + // The number of bytes to use for a nonce, 12 will result in a 16 char nonce. + private static final int NONCE_LENGTH = 12; + + public static final MetaDataKey<String> NONCE_KEY = new MetaDataKey<>() + { + private static final long serialVersionUID = 1L; + }; + + private final Application application; + + private final Map<CSPHeaderMode, CSPHeaderConfiguration> configs = new EnumMap<>(CSPHeaderMode.class); + + private Predicate<IPageClassRequestHandler> protectedPageFilter = handler -> true; + + public ContentSecurityPolicySettings(Application application) + { + this.application = Args.notNull(application, "application"); + } + + public CSPHeaderConfiguration blocking() + { + return configs.computeIfAbsent(CSPHeaderMode.BLOCKING, x -> new CSPHeaderConfiguration()); + } + + public CSPHeaderConfiguration reporting() + { + return configs.computeIfAbsent(CSPHeaderMode.REPORT_ONLY, x -> new CSPHeaderConfiguration()); + } + + /** + * Sets the predicate that determines which requests must be protected by the CSP. When the + * predicate evaluates to false, the request for the page will not be protected. + * + * @param protectedPageFilter + * The new filter, must not be null. + * @return {@code this} for chaining. + */ + public ContentSecurityPolicySettings + setProtectedPageFilter(Predicate<IPageClassRequestHandler> protectedPageFilter) + { + Args.notNull(protectedPageFilter, "protectedPageFilter"); + this.protectedPageFilter = protectedPageFilter; + return this; + } + + protected boolean mustProtect(IRequestHandler handler) + { + if (handler instanceof IRequestHandlerDelegate) + { + return mustProtect(((IRequestHandlerDelegate) handler).getDelegateHandler()); + } + if (handler instanceof IPageClassRequestHandler) + { + return mustProtectPageRequest((IPageClassRequestHandler) handler); + } + return !(handler instanceof BufferedResponseRequestHandler); + } + + protected boolean mustProtectPageRequest(IPageClassRequestHandler handler) + { + return protectedPageFilter.test(handler); + } + + @Override + public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) + { + if (!mustProtect(handler) || !(cycle.getResponse() instanceof WebResponse)) + { + return; + } + + WebResponse webResponse = (WebResponse) cycle.getResponse(); + if (!webResponse.isHeaderSupported()) + { + return; + } + + configs.entrySet().stream(). + filter(entry -> entry.getValue().isSet()) + .forEach(entry -> { + CSPHeaderMode mode = entry.getKey(); + CSPHeaderConfiguration config = entry.getValue(); + String headerValue = config.renderHeaderValue(this, cycle, handler); + webResponse.setHeader(mode.getHeader(), headerValue); + if (config.isAddLegacyHeaders()) + { + webResponse.setHeader(mode.getLegacyHeader(), headerValue); + } + }); + } + + /** + * Returns true if any of the headers includes a directive with a nonce. + * + * @return If a nonce is used in the CSP. + */ + public final boolean isNonceEnabled() + { + return configs.values().stream().anyMatch(CSPHeaderConfiguration::isNonceEnabled); + } + + public String getNonce(RequestCycle cycle, IRequestHandler handler) + { + String nonce = cycle.getMetaData(NONCE_KEY); + Page currentPage = getPage(handler); + + if (nonce == null) + { + if (currentPage != null) + { + nonce = currentPage.getMetaData(NONCE_KEY); + } + if (nonce == null) + { + nonce = getSecuritySettings().getRandomSupplier().getRandomBase64(NONCE_LENGTH); + } + cycle.setMetaData(NONCE_KEY, nonce); + } + + if (currentPage != null) + { + currentPage.setMetaData(NONCE_KEY, nonce); + } + return nonce; + } + + /** + * Resolves a page instance from the request handler iff the page instance is already created + * + * @param handler The request handler + * @return page or {@code null} if none + */ + public static Page getPage(IRequestHandler handler) + { + while (handler instanceof IRequestHandlerDelegate) + { + handler = ((IRequestHandlerDelegate) handler).getDelegateHandler(); + } + + if (handler instanceof IPageRequestHandler) + { + IPageRequestHandler pageHandler = (IPageRequestHandler) handler; + if (pageHandler.isPageInstanceCreated()) + { + return (Page) pageHandler.getPage(); + } + } + return null; + } + + private SecuritySettings getSecuritySettings() + { + return application.getSecuritySettings(); + } + + /** + * Returns the CSP configuration per {@link CSPHeaderMode}. + * + * @return the CSP configuration per {@link CSPHeaderMode}. + */ + public Map<CSPHeaderMode, CSPHeaderConfiguration> getConfiguration() + { + return Collections.unmodifiableMap(configs); + } +} diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPValue.java index 2b73f3d..1383bfc 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPValue.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/FixedCSPValue.java @@ -30,7 +30,7 @@ import org.apache.wicket.util.string.Strings; */ public class FixedCSPValue implements CSPRenderable { - private String value; + private final String value; /** * Creates a new {@code FixedCSPValue} for the given value. @@ -48,8 +48,8 @@ public class FixedCSPValue implements CSPRenderable } @Override - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return value; } @@ -85,4 +85,4 @@ public class FixedCSPValue implements CSPRenderable { return value; } -} \ No newline at end of file +} diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/RelativeURICSPValue.java b/wicket-core/src/main/java/org/apache/wicket/csp/RelativeURICSPValue.java index a5feb10..107fe9c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/RelativeURICSPValue.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/RelativeURICSPValue.java @@ -30,7 +30,7 @@ import org.apache.wicket.util.lang.Args; */ public class RelativeURICSPValue implements CSPRenderable { - private String relativeUri; + private final String relativeUri; /** * Creates a new {@code RelativeURICSPValue} for the given relative URI. @@ -45,8 +45,8 @@ public class RelativeURICSPValue implements CSPRenderable } @Override - public String render(ContentSecurityPolicyEnforcer listener, RequestCycle cycle, - IRequestHandler currentHandler) + public String render(ContentSecurityPolicySettings listener, RequestCycle cycle, + IRequestHandler currentHandler) { return cycle.getUrlRenderer().renderContextRelativeUrl(relativeUri); } @@ -69,4 +69,4 @@ public class RelativeURICSPValue implements CSPRenderable { return relativeUri; } -} \ No newline at end of file +} diff --git a/wicket-core/src/main/java/org/apache/wicket/csp/ReportCSPViolationMapper.java b/wicket-core/src/main/java/org/apache/wicket/csp/ReportCSPViolationMapper.java index 1f8205d..eaa240c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/csp/ReportCSPViolationMapper.java +++ b/wicket-core/src/main/java/org/apache/wicket/csp/ReportCSPViolationMapper.java @@ -44,9 +44,9 @@ public class ReportCSPViolationMapper extends AbstractMapper private static final Logger log = LoggerFactory.getLogger(ReportCSPViolationMapper.class); - private ContentSecurityPolicyEnforcer csp; + private final ContentSecurityPolicySettings csp; - public ReportCSPViolationMapper(ContentSecurityPolicyEnforcer csp) + public ReportCSPViolationMapper(ContentSecurityPolicySettings csp) { this.csp = csp; } @@ -65,7 +65,10 @@ public class ReportCSPViolationMapper extends AbstractMapper { HttpServletRequest httpRequest = ((ServletWebRequest) requestCycle.getRequest()).getContainerRequest(); - log.error(reportToString(httpRequest)); + if (log.isErrorEnabled()) + { + log.error(reportToString(httpRequest)); + } } catch (IOException e) { @@ -78,7 +81,7 @@ public class ReportCSPViolationMapper extends AbstractMapper try (StringWriter sw = new StringWriter()) { char[] buffer = new char[MAX_LOG_SIZE]; - int n = 0; + int n; if (-1 != (n = httpRequest.getReader().read(buffer))) { sw.write(buffer, 0, n); diff --git a/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java b/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java index d6bfa00..ecee55c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java +++ b/wicket-core/src/main/java/org/apache/wicket/mock/MockApplication.java @@ -75,6 +75,6 @@ public class MockApplication extends WebApplication // and isn't needed, because the markup isn't rendered by a browser getResourceSettings().disableWicketCoreCSS(); // disable nonces, CSP is not needed anyway during tests - getCsp().blocking().disabled(); + getCspSettings().blocking().disabled(); } } diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java index d00b7f4..1eda219 100644 --- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java +++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java @@ -41,7 +41,7 @@ import org.apache.wicket.core.request.mapper.ResourceMapper; import org.apache.wicket.core.util.file.WebApplicationPath; import org.apache.wicket.core.util.resource.ClassPathResourceFinder; import org.apache.wicket.csp.CSPHeaderConfiguration; -import org.apache.wicket.csp.ContentSecurityPolicyEnforcer; +import org.apache.wicket.csp.ContentSecurityPolicySettings; import org.apache.wicket.csp.ReportCSPViolationMapper; import org.apache.wicket.csp.CSPNonceHeaderResponseDecorator; import org.apache.wicket.markup.MarkupType; @@ -149,7 +149,7 @@ public abstract class WebApplication extends Application */ private RuntimeConfigurationType configurationType; - private ContentSecurityPolicyEnforcer cspEnforcer; + private ContentSecurityPolicySettings cspSettings; /** * Covariant override for easy getting the current {@link WebApplication} without having to cast @@ -750,12 +750,12 @@ public abstract class WebApplication extends Application getResourceSettings().setFileCleaner(new FileCleaner()); - cspEnforcer = newCspEnforcer(); - getRequestCycleListeners().add(getCsp()); + cspSettings = newCspEnforcer(); + getRequestCycleListeners().add(getCspSettings()); getHeaderResponseDecorators() - .add(response -> new CSPNonceHeaderResponseDecorator(response, getCsp())); - mount(new ReportCSPViolationMapper(getCsp())); - getCsp().blocking().strict(); + .add(response -> new CSPNonceHeaderResponseDecorator(response, getCspSettings())); + mount(new ReportCSPViolationMapper(getCspSettings())); + getCspSettings().blocking().strict(); if (getConfigurationType() == RuntimeConfigurationType.DEVELOPMENT) { @@ -765,7 +765,7 @@ public abstract class WebApplication extends Application { getResourceSettings().getResourceFinders().add(new Path(resourceFolder)); } - getCsp().blocking().reportBack(); + getCspSettings().blocking().reportBack(); } setPageRendererProvider(WebPageRenderer::new); setSessionStoreProvider(HttpSessionStore::new); @@ -1092,28 +1092,28 @@ public abstract class WebApplication extends Application } /** - * Builds the {@link ContentSecurityPolicyEnforcer} to be used for this application. Override + * Builds the {@link ContentSecurityPolicySettings} to be used for this application. Override * this method to provider your own implementation. * * @return The newly created CSP enforcer. */ - protected ContentSecurityPolicyEnforcer newCspEnforcer() + protected ContentSecurityPolicySettings newCspEnforcer() { - return new ContentSecurityPolicyEnforcer(this); + return new ContentSecurityPolicySettings(this); } /** - * Returns the {@link ContentSecurityPolicyEnforcer} for this application. See - * {@link ContentSecurityPolicyEnforcer} and {@link CSPHeaderConfiguration} for instructions on + * Returns the {@link ContentSecurityPolicySettings} for this application. See + * {@link ContentSecurityPolicySettings} and {@link CSPHeaderConfiguration} for instructions on * configuring the CSP for your specific needs. * - * @return The {@link ContentSecurityPolicyEnforcer} for this application. - * @see ContentSecurityPolicyEnforcer + * @return The {@link ContentSecurityPolicySettings} for this application. + * @see ContentSecurityPolicySettings * @see CSPHeaderConfiguration */ - public ContentSecurityPolicyEnforcer getCsp() + public ContentSecurityPolicySettings getCspSettings() { - return cspEnforcer; + return cspSettings; } /** diff --git a/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java b/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java index c64fe9b..e0d4123 100644 --- a/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/csp/CSPSettingRequestCycleListenerTest.java @@ -56,8 +56,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testNullSrcInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, (String) null); }); @@ -66,8 +66,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testEmptySrcInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, ""); }); @@ -80,8 +80,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testInvalidSrcInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, "abc?^()-_\'xyz"); }); @@ -94,8 +94,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSrcInputWithNoneIsRejected1() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, SELF, NONE); }); @@ -108,8 +108,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSrcInputWithNoneIsRejected2() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, NONE, SELF); }); @@ -122,8 +122,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSrcInputWithStarIsRejected1() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(DEFAULT_SRC, SELF); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, WILDCARD); @@ -137,8 +137,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSrcInputWithStarIsRejected2() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(DEFAULT_SRC, WILDCARD); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, SELF); @@ -148,8 +148,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testWrongSrcInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(DEFAULT_SRC, ALLOW_FORMS); }); @@ -158,8 +158,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testWrongSandboxInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(SANDBOX, SELF); }); @@ -168,8 +168,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testNullSandboxInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(SANDBOX, (String) null); }); @@ -178,16 +178,16 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testEmptySandboxInputIsAccepted() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(SANDBOX, CSPDirectiveSandboxValue.EMPTY); } @Test public void testInvalidSandboxInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(SANDBOX, "abcxyz"); }); @@ -196,8 +196,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSandboxInputWithEmptyStringIsRejected1() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(SANDBOX, ALLOW_FORMS); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(SANDBOX, EMPTY); @@ -207,8 +207,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testMultipleSandboxInputWithEmptyStringIsRejected2() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(SANDBOX, EMPTY); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(SANDBOX, ALLOW_FORMS); @@ -218,8 +218,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testNullReportUriInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(REPORT_URI, (String) null); }); @@ -228,8 +228,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testEmptyReportUriInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(REPORT_URI, ""); }); @@ -238,8 +238,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testInvalidReportUriInputIsRejected() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); Assertions.assertThrows(IllegalArgumentException.class, () -> { cspListener.blocking().add(REPORT_URI, "abc?^()-_\'xyz"); }); @@ -248,8 +248,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testAllCSPSrcDefaultEnumsAreSetCorrectly() throws NoSuchAlgorithmException { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); final int cspDirectiveCount = CSPDirective.values().length; final int cspDirectiveSrcValueCount = CSPDirectiveSrcValue.values().length; @@ -278,8 +278,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testCSPReportUriDirectiveSetCorrectly() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(REPORT_URI, "http://report.example.com"); cspListener.reporting().add(REPORT_URI, "/example-report-uri"); @@ -294,8 +294,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testCSPSandboxDirectiveSetCorrectly() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); final int cspSandboxDirectiveValueCount = CSPDirectiveSandboxValue.values().length; for (int i = 0; i < cspSandboxDirectiveValueCount; i++) { @@ -322,8 +322,8 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase @Test public void testChildSrcDirectiveAlsoSetsFrameSrcDirective() { - ContentSecurityPolicyEnforcer cspListener = - new ContentSecurityPolicyEnforcer(tester.getApplication()); + ContentSecurityPolicySettings cspListener = + new ContentSecurityPolicySettings(tester.getApplication()); cspListener.blocking().add(CHILD_SRC, SELF); cspListener.reporting().add(CHILD_SRC, SELF); List<String> headerErrors = checkHeaders(cspListener); @@ -334,7 +334,7 @@ public class CSPSettingRequestCycleListenerTest extends WicketTestCase } } - private List<String> checkHeaders(ContentSecurityPolicyEnforcer cspListener) + private List<String> checkHeaders(ContentSecurityPolicySettings cspListener) { List<String> headerErrors = new ArrayList<>(); wicketTester.getRequestCycle().getListeners().add(cspListener); diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java index 0463fab..da38317 100644 --- a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Collections; -import org.apache.wicket.csp.ContentSecurityPolicyEnforcer; +import org.apache.wicket.csp.ContentSecurityPolicySettings; import org.apache.wicket.markup.head.StringHeaderItem; import org.apache.wicket.markup.head.internal.HeaderResponse; import org.apache.wicket.mock.MockApplication; @@ -45,9 +45,9 @@ class FilteringHeaderResponseTest extends WicketTestCase return new MockApplication() { @Override - protected ContentSecurityPolicyEnforcer newCspEnforcer() + protected ContentSecurityPolicySettings newCspEnforcer() { - return new ContentSecurityPolicyEnforcer(this) + return new ContentSecurityPolicySettings(this) { @Override public String getNonce(RequestCycle cycle, IRequestHandler currentHandler) @@ -117,7 +117,7 @@ class FilteringHeaderResponseTest extends WicketTestCase @Test void nonce() throws Exception { - tester.getApplication().getCsp().blocking().strict(); + tester.getApplication().getCspSettings().blocking().strict(); executeTest(CspNoncePage.class, "CspNoncePageExpected.html"); } } diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java index 526c24f..2303b34 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/WicketExampleApplication.java @@ -20,7 +20,6 @@ import org.apache.wicket.csp.CSPDirective; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.cycle.IRequestCycleListener; import org.apache.wicket.request.cycle.RequestCycle; -import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.request.http.WebResponse; import org.apache.wicket.resource.CssUrlReplacer; import org.apache.wicket.settings.SecuritySettings; @@ -64,10 +63,10 @@ public abstract class WicketExampleApplication extends WebApplication getDebugSettings().setDevelopmentUtilitiesEnabled(true); getResourceSettings().setCssCompressor(new CssUrlReplacer()); - getCsp().blocking().strict().reportBack() - .add(CSPDirective.STYLE_SRC, + getCspSettings().blocking().strict().reportBack() + .add(CSPDirective.STYLE_SRC, "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css") - .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com"); + .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com"); getRequestCycleListeners().add(new IRequestCycleListener() { diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MyAuthenticatedWebApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MyAuthenticatedWebApplication.java index 089c88e..d01c1a1 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MyAuthenticatedWebApplication.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/authentication3/MyAuthenticatedWebApplication.java @@ -54,11 +54,11 @@ public class MyAuthenticatedWebApplication extends AuthenticatedWebApplication super.init(); getDebugSettings().setDevelopmentUtilitiesEnabled(true); - getCsp().blocking() - .strict() - .reportBack() - .add(CSPDirective.STYLE_SRC, + getCspSettings().blocking() + .strict() + .reportBack() + .add(CSPDirective.STYLE_SRC, "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css") - .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com"); + .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com"); } } diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/images/ImagesApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/images/ImagesApplication.java index bcfbebf..4487be6 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/images/ImagesApplication.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/images/ImagesApplication.java @@ -41,7 +41,7 @@ public class ImagesApplication extends WicketExampleApplication super.init(); getSharedResources().add("cancelButton", new DefaultButtonImageResource("Cancel")); - getCsp().blocking().add(CSPDirective.IMG_SRC, "data:"); + getCspSettings().blocking().add(CSPDirective.IMG_SRC, "data:"); } } diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java index 18bbdae..59dd0a3 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java @@ -49,9 +49,9 @@ public class VideosApplication extends WicketExampleApplication guard.addPattern("+*.mp4"); } - getCsp().blocking() - .add(CSPDirective.MEDIA_SRC, CSPDirectiveSrcValue.SELF) - .add(CSPDirective.MEDIA_SRC, "https://w3c-test.org/media/movie_300.mp4"); + getCspSettings().blocking() + .add(CSPDirective.MEDIA_SRC, CSPDirectiveSrcValue.SELF) + .add(CSPDirective.MEDIA_SRC, "https://w3c-test.org/media/movie_300.mp4"); } } diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java index 53d7dee..b8c68cf 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java @@ -16,7 +16,6 @@ */ package org.apache.wicket.examples.websocket; -import org.apache.wicket.csp.CSPDirective; import org.apache.wicket.examples.WicketExampleApplication; import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource; import org.apache.wicket.protocol.http.WebApplication; @@ -66,7 +65,7 @@ public class JSR356Application extends WicketExampleApplication // The websocket example loads JS from ajax.googleapis.com, which is not allowed by the CSP. // This now serves as an example on how to disable CSP - getCsp().blocking().disabled(); + getCspSettings().blocking().disabled(); } @Override diff --git a/wicket-user-guide/src/main/asciidoc/security/security_6.adoc b/wicket-user-guide/src/main/asciidoc/security/security_6.adoc index d762384..bb85f8c 100644 --- a/wicket-user-guide/src/main/asciidoc/security/security_6.adoc +++ b/wicket-user-guide/src/main/asciidoc/security/security_6.adoc @@ -12,7 +12,7 @@ In developer mode, the CSP is extended with a reporting directive that reports v === Configuring the Content Security Policy -The Content Security Policy is managed by the _ContentSecurityPolicyEnforcer_ that can be accessed via _WebApplication.getCSP()_. This class maintains two instances of _CSPHeaderConfiguration_, each of which contains the directives for the CSP HTTP headers _Content-Security-Policy_ and _Content-Security-Policy-Report-Only_. The first header defines the policies that are actually enforced by the browser, whereas the second header defines a policy for which the browser will only report vio [...] +The Content Security Policy is managed by the _ContentSecurityPolicyEnforcer_ that can be accessed via _WebApplication.getCspSettings()_. This class maintains two instances of _CSPHeaderConfiguration_, each of which contains the directives for the CSP HTTP headers _Content-Security-Policy_ and _Content-Security-Policy-Report-Only_. The first header defines the policies that are actually enforced by the browser, whereas the second header defines a policy for which the browser will only re [...] For applications that cannot adhere to a CSP, the CSP can be disabled with the following call in your _Application_ class: @@ -21,7 +21,7 @@ For applications that cannot adhere to a CSP, the CSP can be disabled with the f @Override protected void init() { super.init(); - getCSP().blocking().disable(); + getCspSettings().blocking().disable(); // ... } ---- @@ -30,7 +30,7 @@ As mentioned before, Wicket uses a very strict CSP by default. This preset can b [source,java] ---- - getCSP().blocking().strict(); + getCspSettings().blocking().strict(); ---- A thrid preset is available that allows unsafe inline Javascript and styling and the use of unsafe _eval_. As can be inferred from the names, use of _unsafe_ is not recommended. It removes the most important protection offered by CSP. However, older applications may not be ready to apply a strict CSP. For those applications, _CSPHeaderConfiguration.unsafeInline()_ can be a starting point for the path to a strict CSP. @@ -39,7 +39,7 @@ _CSPHeaderConfiguration_ defines several methods to tune the Content Security Po [source,java] ---- - getCSP().blocking() + getCspSettings().blocking() .add(CSPDirective.IMG_SRC, "data:") .add(CSPDirective.FONT_SRC, "https://maxcdn.bootstrapcdn.com") .add(CSPDirective.STYLE_SRC,
