apply Spring's actuator

This commit is contained in:
anhefti 2019-05-09 11:26:11 +02:00
parent 5032e39352
commit e2b93e5529
5 changed files with 74 additions and 14 deletions

View file

@ -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();
}

View file

@ -23,7 +23,7 @@ import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
@Configuration
@GuiProfile
@Order(4)
@Order(5)
public class GuiWebsecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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