diff --git a/src/main/java/ru/mystamps/web/support/spring/boot/ApplicationBootstrap.java b/src/main/java/ru/mystamps/web/support/spring/boot/ApplicationBootstrap.java index 237016733b..f65fffcf5d 100755 --- a/src/main/java/ru/mystamps/web/support/spring/boot/ApplicationBootstrap.java +++ b/src/main/java/ru/mystamps/web/support/spring/boot/ApplicationBootstrap.java @@ -19,6 +19,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Import; import org.togglz.core.context.StaticFeatureManagerProvider; @@ -30,6 +32,7 @@ // CheckStyle: I cannot declare the constructor as private because app won't start. @SuppressWarnings({ "PMD.UseUtilityClass", "checkstyle:hideutilityclassconstructor" }) @EnableAutoConfiguration +@EnableConfigurationProperties(H2ConsoleProperties.class) @Import({ ApplicationContext.class, DispatcherServletContext.class, diff --git a/src/main/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriter.java b/src/main/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriter.java index 9879788120..a917b5d08f 100644 --- a/src/main/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriter.java +++ b/src/main/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriter.java @@ -18,6 +18,7 @@ package ru.mystamps.web.support.spring.security; import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties; import org.springframework.security.web.header.HeaderWriter; import ru.mystamps.web.feature.collection.CollectionUrl; import ru.mystamps.web.feature.series.SeriesUrl; @@ -46,9 +47,6 @@ class ContentSecurityPolicyHeaderWriter implements HeaderWriter { private static final String ADD_IMAGE_PAGE_PATTERN = "/series/(add|\\d+|\\d+/(ask|image))"; - // see also spring.h2.console.path in application-test.properties and SecurityConfig - private static final String H2_CONSOLE_PATTERN = "/console/"; - // default policy prevents loading resources from any source private static final String DEFAULT_SRC = "default-src 'none'"; @@ -156,6 +154,8 @@ class ContentSecurityPolicyHeaderWriter implements HeaderWriter { private final boolean useSingleHost; private final boolean hasH2Console; private final String host; + private final H2ConsoleProperties h2ConsoleProperties; + @Override public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { @@ -168,7 +168,7 @@ public void writeHeaders(HttpServletRequest request, HttpServletResponse respons protected String constructDirectives(String uri) { boolean onCollectionInfoPage = uri.startsWith(COLLECTION_INFO_PAGE_PATTERN); boolean onAddSeriesPage = uri.equals(SeriesUrl.ADD_SERIES_PAGE); - boolean onH2ConsolePage = hasH2Console && uri.startsWith(H2_CONSOLE_PATTERN); + boolean onH2ConsolePage = hasH2Console && uri.startsWith(h2ConsoleProperties.getPath()); StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/ru/mystamps/web/support/spring/security/SecurityConfig.java b/src/main/java/ru/mystamps/web/support/spring/security/SecurityConfig.java index beca50cb19..313ef07fa9 100644 --- a/src/main/java/ru/mystamps/web/support/spring/security/SecurityConfig.java +++ b/src/main/java/ru/mystamps/web/support/spring/security/SecurityConfig.java @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter; import org.springframework.context.ApplicationListener; @@ -72,6 +73,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SiteService siteService; + @Autowired + private H2ConsoleProperties h2ConsoleProperties; + @Override @SuppressWarnings("PMD.SignatureDeclareThrowsException") public void configure(WebSecurity web) throws Exception { @@ -90,7 +94,7 @@ protected void configure(HttpSecurity http) throws Exception { String hostname = usePublicHostname ? SiteUrl.PUBLIC_URL : SiteUrl.SITE; ContentSecurityPolicyHeaderWriter cspWriter = - new ContentSecurityPolicyHeaderWriter(useCdn, useSingleHost, hasH2Console, hostname); + new ContentSecurityPolicyHeaderWriter(useCdn, useSingleHost, hasH2Console, hostname, h2ConsoleProperties); http .authorizeRequests() @@ -141,7 +145,7 @@ protected void configure(HttpSecurity http) throws Exception { // Allow unsecured requests to H2 consoles. // See also spring.h2.console.path in application-test.properties and // ContentSecurityPolicyHeaderWriter.H2_CONSOLE_PATTERN - .ignoringAntMatchers("/console/**", SiteUrl.CSP_REPORTS_HANDLER) + .ignoringAntMatchers(h2ConsoleProperties.getPath() + "/**", SiteUrl.CSP_REPORTS_HANDLER) .and() .rememberMe() // FIXME: GH #27 diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 4140c9da2b..df700eef23 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -7,7 +7,7 @@ spring.datasource.driver-class-name: org.h2.Driver spring.datasource.initialization-mode: NEVER spring.h2.console.enabled: true -# see also SecurityConfig and ContentSecurityPolicyHeaderWriter.H2_CONSOLE_PATTERN +# see also SecurityConfig spring.h2.console.path: /console # required for using /console with CSP because we have many hashes as a workaround diff --git a/src/test/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriterTest.java b/src/test/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriterTest.java index 0f3ed8b4d7..f4095e90d3 100644 --- a/src/test/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriterTest.java +++ b/src/test/java/ru/mystamps/web/support/spring/security/ContentSecurityPolicyHeaderWriterTest.java @@ -18,8 +18,10 @@ package ru.mystamps.web.support.spring.security; import org.assertj.core.api.WithAssertions; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.togglz.junit.TogglzRule; @@ -38,10 +40,16 @@ public class ContentSecurityPolicyHeaderWriterTest implements WithAssertions { private static final int NUMBER_OF_DIRECTIVES_ON_ADD_SERIES_PAGE = 7; private static final int NUMBER_OF_DIRECTIVES_ON_INFO_SERIES_PAGE = 7; private static final int NUMBER_OF_DIRECTIVES_ON_H2_CONSOLE_PAGE = 7; - + private static final H2ConsoleProperties H2_CONSOLE_PROPERTIES = new H2ConsoleProperties(); + @Rule public TogglzRule togglz = TogglzRule.allEnabled(Features.class); + @BeforeClass + public static void setupClass() { + H2_CONSOLE_PROPERTIES.setPath("/console/"); + } + // // Tests for writeHeaders() // @@ -50,7 +58,13 @@ public class ContentSecurityPolicyHeaderWriterTest implements WithAssertions { public void writeContentSecurityPolicyHeader() { // given ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(bool(), bool(), bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + bool(), + bool(), + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); HttpServletRequest request = new MockHttpServletRequest(); HttpServletResponse response = new MockHttpServletResponse(); @@ -77,7 +91,7 @@ public void writeContentSecurityPolicyHeader() { @Test public void onIndexPageWithLocalResources() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(false, true, bool(), SiteUrl.SITE); + new ContentSecurityPolicyHeaderWriter(false, true, bool(), SiteUrl.SITE, H2_CONSOLE_PROPERTIES); String[] directives = writer.constructDirectives("/").split(";"); assertThat(directives) @@ -95,7 +109,12 @@ public void onIndexPageWithLocalResources() { @Test public void onIndexPageWithResourcesFromCdn() { ContentSecurityPolicyHeaderWriter writer - = new ContentSecurityPolicyHeaderWriter(true, false, bool(), SiteUrl.PUBLIC_URL); + = new ContentSecurityPolicyHeaderWriter( + true, + false, + bool(), + SiteUrl.PUBLIC_URL, H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/").split(";"); assertThat(directives) @@ -126,7 +145,13 @@ public void onIndexPageWithResourcesFromCdn() { @Test public void onCollectionInfoPageWithLocalResources() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(false, true, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + false, + true, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/collection/user").split(";"); // test only the directives that differ from the index page @@ -153,7 +178,13 @@ public void onCollectionInfoPageWithLocalResources() { @Test public void onCollectionInfoPageWithResourcesFromCdn() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(true, false, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + true, + false, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/collection/user").split(";"); // test only the directives that differ from the index page @@ -183,7 +214,13 @@ public void onCollectionInfoPageWithResourcesFromCdn() { @Test public void onSeriesAddImagePageWithLocalResources() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(false, true, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + false, + true, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); for (String page : new String[]{"/series/11", "/series/12/ask", "/series/13/image"}) { String[] directives = writer.constructDirectives(page).split(";"); @@ -206,7 +243,13 @@ public void onSeriesAddImagePageWithLocalResources() { @Test public void onSeriesAddImagePageWithResourcesFromCdn() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(true, false, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + true, + false, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); for (String page : new String[]{"/series/11", "/series/12/ask", "/series/13/image"}) { String[] directives = writer.constructDirectives(page).split(";"); @@ -239,7 +282,13 @@ public void onSeriesAddImagePageWithResourcesFromCdn() { @Test public void onSeriesAddPageWithLocalResources() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(false, true, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + false, + true, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/series/add").split(";"); // test only the directives that differ from the index page @@ -267,7 +316,13 @@ public void onSeriesAddPageWithLocalResources() { @Test public void onSeriesAddPageWithResourcesFromCdn() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(true, false, bool(), Random.host()); + new ContentSecurityPolicyHeaderWriter( + true, + false, + bool(), + Random.host(), + H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/series/add").split(";"); // test only the directives that differ from the index page @@ -298,7 +353,7 @@ public void onSeriesAddPageWithResourcesFromCdn() { @Test public void onH2ConsoleWithLocalResources() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(false, true, true, Random.host()); + new ContentSecurityPolicyHeaderWriter(false, true, true, Random.host(), H2_CONSOLE_PROPERTIES); String[] directives = writer.constructDirectives("/console/").split(";"); // test only the directives that are differ from the index page @@ -326,7 +381,13 @@ public void onH2ConsoleWithLocalResources() { @Test public void onH2ConsoleWithResourcesFromCdn() { ContentSecurityPolicyHeaderWriter writer = - new ContentSecurityPolicyHeaderWriter(true, false, false, Random.host()); + new ContentSecurityPolicyHeaderWriter( + true, + false, + false, + Random.host(), + H2_CONSOLE_PROPERTIES + ); String[] directives = writer.constructDirectives("/console/").split(";"); assertThat(directives)