diff --git a/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java b/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java index 32dd818e..40422848 100644 --- a/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/WebSecurityConfig.java @@ -32,7 +32,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpHeaders; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; @@ -45,7 +45,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.filter.CharacterEncodingFilter; -import ch.ethz.seb.sebserver.gbl.api.API; import ch.ethz.seb.sebserver.gbl.profile.DevGuiProfile; import ch.ethz.seb.sebserver.gbl.profile.DevWebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; @@ -59,13 +58,13 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @WebServiceProfile @GuiProfile @RestController -@Order(6) +@Order(7) public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ErrorController { private static final Logger log = LoggerFactory.getLogger(WebSecurityConfig.class); - @Value("${sebserver.webservice.api.admin.endpoint}") - private String adminEndpoint; +// @Value("${sebserver.webservice.api.admin.endpoint}") +// private String adminEndpoint; @Value("${sebserver.webservice.api.redirect.unauthorized}") private String unauthorizedRedirect; @@ -101,13 +100,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E web .ignoring() .antMatchers("/error") - .antMatchers(this.adminEndpoint + API.INFO_ENDPOINT + "/**"); + // TODO this may not be necessary, test with separated GUI and webservice server + //.antMatchers(this.adminEndpoint + API.INFO_ENDPOINT + "/**") + ; } @RequestMapping("/error") public void handleError(final HttpServletResponse response) throws IOException { - response.setStatus(HttpStatus.NOT_FOUND.value()); - response.sendRedirect(this.unauthorizedRedirect); + response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); + response.setHeader(HttpHeaders.LOCATION, this.unauthorizedRedirect); + response.flushBuffer(); } @Override @@ -123,7 +125,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements E @DevGuiProfile @DevWebServiceProfile public ClientHttpRequestFactory clientHttpRequestFactory() { + log.info("Initialize with insecure ClientHttpRequestFactory for development"); + return new DevClientHttpRequestFactory(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java b/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java index 392d9f78..018a7a61 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/GuiWebsecurityConfig.java @@ -23,7 +23,7 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; @Configuration @GuiProfile -@Order(4) +@Order(5) public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter { @Autowired diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/WebServiceSecurityConfig.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/WebServiceSecurityConfig.java index 25f7af7a..27eb4941 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/WebServiceSecurityConfig.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/WebServiceSecurityConfig.java @@ -24,7 +24,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -43,6 +43,7 @@ import org.springframework.security.oauth2.provider.token.UserAuthenticationConv import org.springframework.security.web.AuthenticationEntryPoint; import ch.ethz.seb.sebserver.WebSecurityConfig; +import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebClientDetailsService; import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebserviceResourceConfiguration; @@ -64,9 +65,8 @@ import ch.ethz.seb.sebserver.webservice.weblayer.oauth.WebserviceResourceConfigu * and is by default set to "/exam-api/**" */ @WebServiceProfile @Configuration -//@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableWebSecurity -@Order(5) +@Order(6) @Import(DataSourceAutoConfiguration.class) public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { @@ -89,6 +89,8 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { private String adminAPIEndpoint; @Value("${sebserver.webservice.api.exam.endpoint}") private String examAPIEndpoint; + @Value("${management.endpoints.web.base-path}") + private String actuatorEndpoint; @Value("${sebserver.webservice.api.redirect.unauthorized}") private String unauthorizedRedirect; @@ -154,6 +156,16 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { this.examAPIEndpoint); } + @Bean + protected ResourceServerConfiguration sebServerActuatorResources() throws Exception { + return new ActuatorResourceServerConfiguration( + this.tokenStore, + this.webServiceClientDetails, + authenticationManagerBean(), + this.actuatorEndpoint, + this.unauthorizedRedirect); + } + // NOTE: We need two different class types here to support Spring configuration for different // ResourceServerConfiguration. There is a class type now for the Admin API as well as for the Exam API private static final class AdminAPIResourceServerConfiguration extends WebserviceResourceConfiguration { @@ -191,6 +203,7 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { tokenStore, webServiceClientDetails, authenticationManager, + // TODO create a proper error handling here with also documentation on SEB Binding Specification (request, response, exception) -> { response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); @@ -205,6 +218,36 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { } } + private static final class ActuatorResourceServerConfiguration extends WebserviceResourceConfiguration { + + public ActuatorResourceServerConfiguration( + final TokenStore tokenStore, + final WebClientDetailsService webServiceClientDetails, + final AuthenticationManager authenticationManager, + final String apiEndpoint, + final String redirect) { + + super( + tokenStore, + webServiceClientDetails, + authenticationManager, + new LoginRedirectOnUnauthorized(redirect), + ADMIN_API_RESOURCE_ID, + apiEndpoint, + true, + 4); + } + + @Override + protected void addConfiguration(final String apiEndpoint, final HttpSecurity http) throws Exception { + http.antMatcher(apiEndpoint + "/**") + .authorizeRequests() + .anyRequest() + .hasAuthority(UserRole.SEB_SERVER_ADMIN.name()); + } + + } + private static class LoginRedirectOnUnauthorized implements AuthenticationEntryPoint { private final String redirect; @@ -222,8 +265,9 @@ public class WebServiceSecurityConfig extends WebSecurityConfigurerAdapter { log.warn("Unauthorized Request: {} : Redirect to login after unauthorized request", request.getRequestURI()); - response.setStatus(HttpStatus.UNAUTHORIZED.value()); - response.sendRedirect(this.redirect); + response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); + response.setHeader(HttpHeaders.LOCATION, this.redirect); + response.flushBuffer(); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java index b96097c4..4ef3d338 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/oauth/WebserviceResourceConfiguration.java @@ -43,6 +43,7 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf super(); final ConfigurerAdapter configurerAdapter = new ConfigurerAdapter( + this, tokenStore, webServiceClientDetails, authenticationManager, @@ -61,8 +62,13 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf super.setConfigurers(configurers); } + protected void addConfiguration(final String apiEndpoint, final HttpSecurity http) throws Exception { + // To override of additional configuration is needed + } + private static final class ConfigurerAdapter extends ResourceServerConfigurerAdapter { + private final WebserviceResourceConfiguration webserviceResourceConfiguration; private final TokenStore tokenStore; private final WebClientDetailsService webServiceClientDetails; private final AuthenticationManager authenticationManager; @@ -72,6 +78,7 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf private final boolean supportRefreshToken; public ConfigurerAdapter( + final WebserviceResourceConfiguration webserviceResourceConfiguration, final TokenStore tokenStore, final WebClientDetailsService webServiceClientDetails, final AuthenticationManager authenticationManager, @@ -81,6 +88,7 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf final boolean supportRefreshToken) { super(); + this.webserviceResourceConfiguration = webserviceResourceConfiguration; this.tokenStore = tokenStore; this.webServiceClientDetails = webServiceClientDetails; this.authenticationManager = authenticationManager; @@ -121,6 +129,8 @@ public abstract class WebserviceResourceConfiguration extends ResourceServerConf .headers().frameOptions().disable() .and() .csrf().disable(); + + this.webserviceResourceConfiguration.addConfiguration(this.apiEndpoint, http); } } diff --git a/src/main/resources/config/application-dev-ws.properties b/src/main/resources/config/application-dev-ws.properties index 5c0a42a8..de070111 100644 --- a/src/main/resources/config/application-dev-ws.properties +++ b/src/main/resources/config/application-dev-ws.properties @@ -17,5 +17,7 @@ sebserver.webservice.api.exam.endpoint=/exam-api/v1 sebserver.webservice.api.exam.accessTokenValiditySeconds=1800 sebserver.webservice.api.exam.refreshTokenValiditySeconds=-1 +management.endpoints.web.base-path=/actuator + sebserver.webservice.api.pagination.maxPageSize=500