diff --git a/src/main/java/com/github/microcatalog/config/CSPProperties.java b/src/main/java/com/github/microcatalog/config/CSPProperties.java new file mode 100644 index 0000000..1a93e54 --- /dev/null +++ b/src/main/java/com/github/microcatalog/config/CSPProperties.java @@ -0,0 +1,19 @@ +package com.github.microcatalog.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "csp", ignoreUnknownFields = false) +public class CSPProperties { + private String imageSrc = "'self' data:"; + + public CSPProperties() { + } + + public String getImageSrc() { + return imageSrc; + } + + public void setImageSrc(String imageSrc) { + this.imageSrc = imageSrc; + } +} diff --git a/src/main/java/com/github/microcatalog/config/SecurityConfiguration.java b/src/main/java/com/github/microcatalog/config/SecurityConfiguration.java index 9c4ce9e..1ebe78b 100644 --- a/src/main/java/com/github/microcatalog/config/SecurityConfiguration.java +++ b/src/main/java/com/github/microcatalog/config/SecurityConfiguration.java @@ -1,8 +1,9 @@ package com.github.microcatalog.config; -import com.github.microcatalog.security.*; -import com.github.microcatalog.security.jwt.*; - +import com.github.microcatalog.security.AuthoritiesConstants; +import com.github.microcatalog.security.jwt.JWTConfigurer; +import com.github.microcatalog.security.jwt.TokenProvider; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.http.HttpMethod; @@ -22,17 +23,18 @@ @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @Import(SecurityProblemSupport.class) +@EnableConfigurationProperties(CSPProperties.class) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { - + private final CSPProperties cspProperties; private final TokenProvider tokenProvider; - private final CorsFilter corsFilter; private final SecurityProblemSupport problemSupport; - public SecurityConfiguration(TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) { + public SecurityConfiguration(TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport, CSPProperties cspProperties) { this.tokenProvider = tokenProvider; this.corsFilter = corsFilter; this.problemSupport = problemSupport; + this.cspProperties = cspProperties; } @Bean @@ -60,22 +62,23 @@ public void configure(HttpSecurity http) throws Exception { .disable() .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) .exceptionHandling() - .authenticationEntryPoint(problemSupport) - .accessDeniedHandler(problemSupport) - .and() + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport) + .and() .headers() - .contentSecurityPolicy("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src *; font-src 'self' data:") - .and() + .contentSecurityPolicy( + String.format("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src %s; font-src 'self' data:", cspProperties.getImageSrc())) + .and() .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN) - .and() + .and() .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'") - .and() + .and() .frameOptions() .deny() - .and() + .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() + .and() .authorizeRequests() .antMatchers("/api/authenticate").permitAll() .antMatchers("/api/register").permitAll() @@ -87,9 +90,9 @@ public void configure(HttpSecurity http) throws Exception { .antMatchers("/management/info").permitAll() .antMatchers("/management/prometheus").permitAll() .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN) - .and() + .and() .httpBasic() - .and() + .and() .apply(securityConfigurerAdapter()); // @formatter:on } diff --git a/src/main/resources/config/application-heroku.yml b/src/main/resources/config/application-heroku.yml index a2568de..1d7e7b4 100644 --- a/src/main/resources/config/application-heroku.yml +++ b/src/main/resources/config/application-heroku.yml @@ -16,6 +16,9 @@ eureka: non-secure-port: 80 prefer-ip-address: false +csp: + image-src: '*' + spring: datasource: type: com.zaxxer.hikari.HikariDataSource