Commit 2c97d3a5 authored by Phillip Webb's avatar Phillip Webb

Polish

parent b02edd2e
...@@ -26,6 +26,8 @@ import org.springframework.context.annotation.Conditional; ...@@ -26,6 +26,8 @@ import org.springframework.context.annotation.Conditional;
/** /**
* {@link Conditional} that matches based on the configuration of the management port. * {@link Conditional} that matches based on the configuration of the management port.
*
* @since 2.0.0
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD }) @Target({ ElementType.TYPE, ElementType.METHOD })
......
...@@ -35,6 +35,10 @@ import org.springframework.context.annotation.Import; ...@@ -35,6 +35,10 @@ import org.springframework.context.annotation.Import;
@Import(ManagementContextConfigurationImportSelector.class) @Import(ManagementContextConfigurationImportSelector.class)
@interface EnableManagementContext { @interface EnableManagementContext {
/**
* The management context type that should be enabled.
* @return the management context type
*/
ManagementContextType value(); ManagementContextType value();
} }
...@@ -37,6 +37,7 @@ import org.springframework.core.env.ConfigurableEnvironment; ...@@ -37,6 +37,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext; import org.springframework.web.context.ConfigurableWebApplicationContext;
/** /**
...@@ -58,7 +59,7 @@ public class ManagementContextAutoConfiguration { ...@@ -58,7 +59,7 @@ public class ManagementContextAutoConfiguration {
@Bean @Bean
public ManagementServletContext managementServletContext( public ManagementServletContext managementServletContext(
final ManagementServerProperties properties) { ManagementServerProperties properties) {
return () -> properties.getContextPath(); return () -> properties.getContextPath();
} }
...@@ -86,12 +87,11 @@ public class ManagementContextAutoConfiguration { ...@@ -86,12 +87,11 @@ public class ManagementContextAutoConfiguration {
} }
private void verifySslConfiguration() { private void verifySslConfiguration() {
if (this.environment.getProperty("management.ssl.enabled", Boolean.class, Boolean enabled = this.environment.getProperty("management.ssl.enabled",
false)) { Boolean.class, false);
throw new IllegalStateException( Assert.state(!enabled,
"Management-specific SSL cannot be configured as the management " "Management-specific SSL cannot be configured as the management "
+ "server is not listening on a separate port"); + "server is not listening on a separate port");
}
} }
private void verifyContextPathConfiguration() { private void verifyContextPathConfiguration() {
...@@ -112,6 +112,7 @@ public class ManagementContextAutoConfiguration { ...@@ -112,6 +112,7 @@ public class ManagementContextAutoConfiguration {
ConfigurableEnvironment environment) { ConfigurableEnvironment environment) {
environment.getPropertySources() environment.getPropertySources()
.addLast(new PropertySource<Object>("Management Server") { .addLast(new PropertySource<Object>("Management Server") {
@Override @Override
public Object getProperty(String name) { public Object getProperty(String name) {
if ("local.management.port".equals(name)) { if ("local.management.port".equals(name)) {
...@@ -119,6 +120,7 @@ public class ManagementContextAutoConfiguration { ...@@ -119,6 +120,7 @@ public class ManagementContextAutoConfiguration {
} }
return null; return null;
} }
}); });
} }
......
...@@ -122,8 +122,8 @@ class ManagementContextConfigurationImportSelector ...@@ -122,8 +122,8 @@ class ManagementContextConfigurationImportSelector
Map<String, Object> annotationAttributes = annotationMetadata Map<String, Object> annotationAttributes = annotationMetadata
.getAnnotationAttributes( .getAnnotationAttributes(
ManagementContextConfiguration.class.getName()); ManagementContextConfiguration.class.getName());
return annotationAttributes == null ? ManagementContextType.ANY return (annotationAttributes == null ? ManagementContextType.ANY
: (ManagementContextType) annotationAttributes.get("value"); : (ManagementContextType) annotationAttributes.get("value"));
} }
private int readOrder(AnnotationMetadata annotationMetadata) { private int readOrder(AnnotationMetadata annotationMetadata) {
......
...@@ -27,7 +27,13 @@ import org.springframework.context.ConfigurableApplicationContext; ...@@ -27,7 +27,13 @@ import org.springframework.context.ConfigurableApplicationContext;
*/ */
interface ManagementContextFactory { interface ManagementContextFactory {
/**
* Create the management application context.
* @param parent the parent context
* @param configurationClasses the configuration classes
* @return a configured application context
*/
ConfigurableApplicationContext createManagementContext(ApplicationContext parent, ConfigurableApplicationContext createManagementContext(ApplicationContext parent,
Class<?>... configClasses); Class<?>... configurationClasses);
} }
...@@ -18,6 +18,12 @@ package org.springframework.boot.actuate.autoconfigure; ...@@ -18,6 +18,12 @@ package org.springframework.boot.actuate.autoconfigure;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
/**
* Port types that can be used to control how the management server is started.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
public enum ManagementPortType { public enum ManagementPortType {
/** /**
......
...@@ -78,8 +78,8 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping; ...@@ -78,8 +78,8 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Meang Akira Tanaka * @author Meang Akira Tanaka
* @author Ben Hale * @author Ben Hale
* @since 2.0.0
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0
*/ */
@Configuration @Configuration
@AutoConfigureAfter({ FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class }) @AutoConfigureAfter({ FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class })
......
...@@ -20,8 +20,8 @@ import org.springframework.boot.actuate.autoconfigure.web.ManagementServerProper ...@@ -20,8 +20,8 @@ import org.springframework.boot.actuate.autoconfigure.web.ManagementServerProper
import org.springframework.boot.endpoint.EndpointPathResolver; import org.springframework.boot.endpoint.EndpointPathResolver;
/** /**
* {@link EndpointPathResolver} implementation for resolving * {@link EndpointPathResolver} implementation for resolving actuator endpoint paths based
* actuator endpoint paths based on the endpoint id and management.context-path. * on the endpoint id and management.context-path.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
...@@ -38,5 +38,5 @@ public class ManagementEndpointPathResolver implements EndpointPathResolver { ...@@ -38,5 +38,5 @@ public class ManagementEndpointPathResolver implements EndpointPathResolver {
public String resolvePath(String endpointId) { public String resolvePath(String endpointId) {
return this.contextPath + "/" + endpointId; return this.contextPath + "/" + endpointId;
} }
}
}
...@@ -51,9 +51,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory { ...@@ -51,9 +51,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
@Override @Override
public ObjectName generate(EndpointMBean mBean) throws MalformedObjectNameException { public ObjectName generate(EndpointMBean mBean) throws MalformedObjectNameException {
String baseObjectName = this.properties.getDomain() + String baseObjectName = this.properties.getDomain() + ":type=Endpoint" + ",name="
":type=Endpoint" + + StringUtils.capitalize(mBean.getEndpointId());
",name=" + StringUtils.capitalize(mBean.getEndpointId());
StringBuilder builder = new StringBuilder(baseObjectName); StringBuilder builder = new StringBuilder(baseObjectName);
if (this.mBeanServer != null && hasMBean(baseObjectName)) { if (this.mBeanServer != null && hasMBean(baseObjectName)) {
builder.append(",context=").append(this.contextId); builder.append(",context=").append(this.contextId);
...@@ -76,7 +75,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory { ...@@ -76,7 +75,8 @@ class DefaultEndpointObjectNameFactory implements EndpointObjectNameFactory {
} }
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (Map.Entry<Object, Object> name : this.properties.getStaticNames().entrySet()) { for (Map.Entry<Object, Object> name : this.properties.getStaticNames()
.entrySet()) {
builder.append(",").append(name.getKey()).append("=").append(name.getValue()); builder.append(",").append(name.getKey()).append("=").append(name.getValue());
} }
return builder.toString(); return builder.toString();
......
...@@ -71,17 +71,20 @@ public class EndpointInfrastructureAutoConfiguration { ...@@ -71,17 +71,20 @@ public class EndpointInfrastructureAutoConfiguration {
@Bean @Bean
public OperationParameterMapper operationParameterMapper() { public OperationParameterMapper operationParameterMapper() {
DefaultConversionService conversionService = new DefaultConversionService(); DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(String.class, Date.class, (string) -> { conversionService.addConverter(String.class, Date.class, this::convertToDate);
if (StringUtils.hasLength(string)) {
OffsetDateTime offsetDateTime = OffsetDateTime.parse(string,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return new Date(offsetDateTime.toEpochSecond() * 1000);
}
return null;
});
return new ConversionServiceOperationParameterMapper(conversionService); return new ConversionServiceOperationParameterMapper(conversionService);
} }
private Date convertToDate(String value) {
if (StringUtils.hasLength(value)) {
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value,
DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return new Date(offsetDateTime.toEpochSecond() * 1000);
}
return null;
}
@Bean @Bean
public CachingConfigurationFactory cacheConfigurationFactory() { public CachingConfigurationFactory cacheConfigurationFactory() {
return new CachingConfigurationFactory(this.applicationContext.getEnvironment()); return new CachingConfigurationFactory(this.applicationContext.getEnvironment());
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -61,8 +61,9 @@ public class EndpointEnablementProvider { ...@@ -61,8 +61,9 @@ public class EndpointEnablementProvider {
public EndpointEnablement getEndpointEnablement(String endpointId, public EndpointEnablement getEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) { boolean enabledByDefault, EndpointExposure exposure) {
Assert.hasText(endpointId, "Endpoint id must have a value"); Assert.hasText(endpointId, "Endpoint id must have a value");
Assert.isTrue(!endpointId.equals("default"), "Endpoint id 'default' is a reserved " Assert.isTrue(!endpointId.equals("default"),
+ "value and cannot be used by an endpoint"); "Endpoint id 'default' is a reserved "
+ "value and cannot be used by an endpoint");
EndpointEnablement result = findEnablement(endpointId, exposure); EndpointEnablement result = findEnablement(endpointId, exposure);
if (result != null) { if (result != null) {
return result; return result;
...@@ -76,8 +77,7 @@ public class EndpointEnablementProvider { ...@@ -76,8 +77,7 @@ public class EndpointEnablementProvider {
if (!enabledByDefault) { if (!enabledByDefault) {
return getDefaultEndpointEnablement(endpointId, false, exposure); return getDefaultEndpointEnablement(endpointId, false, exposure);
} }
return getGlobalEndpointEnablement(endpointId, enabledByDefault, return getGlobalEndpointEnablement(endpointId, enabledByDefault, exposure);
exposure);
} }
private EndpointEnablement findEnablement(String endpointId, private EndpointEnablement findEnablement(String endpointId,
...@@ -98,12 +98,10 @@ public class EndpointEnablementProvider { ...@@ -98,12 +98,10 @@ public class EndpointEnablementProvider {
if (result != null) { if (result != null) {
return result; return result;
} }
return getDefaultEndpointEnablement(endpointId, enabledByDefault, return getDefaultEndpointEnablement(endpointId, enabledByDefault, exposure);
exposure);
} }
private EndpointEnablement findGlobalEndpointEnablement( private EndpointEnablement findGlobalEndpointEnablement(EndpointExposure exposure) {
EndpointExposure exposure) {
if (exposure != null) { if (exposure != null) {
EndpointEnablement result = findEnablement(getKey("default", exposure)); EndpointEnablement result = findEnablement(getKey("default", exposure));
if (result != null) { if (result != null) {
...@@ -136,8 +134,8 @@ public class EndpointEnablementProvider { ...@@ -136,8 +134,8 @@ public class EndpointEnablementProvider {
private EndpointEnablement getDefaultEndpointEnablement(String endpointId, private EndpointEnablement getDefaultEndpointEnablement(String endpointId,
boolean enabledByDefault, EndpointExposure exposure) { boolean enabledByDefault, EndpointExposure exposure) {
return new EndpointEnablement(enabledByDefault, createDefaultEnablementMessage( return new EndpointEnablement(enabledByDefault,
endpointId, enabledByDefault, exposure)); createDefaultEnablementMessage(endpointId, enabledByDefault, exposure));
} }
private String createDefaultEnablementMessage(String endpointId, private String createDefaultEnablementMessage(String endpointId,
...@@ -145,8 +143,7 @@ public class EndpointEnablementProvider { ...@@ -145,8 +143,7 @@ public class EndpointEnablementProvider {
StringBuilder message = new StringBuilder(); StringBuilder message = new StringBuilder();
message.append(String.format("endpoint '%s' ", endpointId)); message.append(String.format("endpoint '%s' ", endpointId));
if (exposure != null) { if (exposure != null) {
message.append( message.append(String.format("(%s) ", exposure.name().toLowerCase()));
String.format("(%s) ", exposure.name().toLowerCase()));
} }
message.append(String.format("is %s by default", message.append(String.format("is %s by default",
(enabledByDefault ? "enabled" : "disabled"))); (enabledByDefault ? "enabled" : "disabled")));
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -32,12 +32,10 @@ import org.springframework.web.servlet.mvc.ServletWrappingController; ...@@ -32,12 +32,10 @@ import org.springframework.web.servlet.mvc.ServletWrappingController;
/** /**
* {@link ManagementContextConfiguration} for embedding Jolokia, a JMX-HTTP bridge giving * {@link ManagementContextConfiguration} for embedding Jolokia, a JMX-HTTP bridge giving
* an alternative to JSR-160 connectors. * an alternative to JSR-160 connectors.
*
* <p> * <p>
* This configuration will get automatically enabled as soon as the Jolokia * This configuration will get automatically enabled as soon as the Jolokia
* {@link AgentServlet} is on the classpath. To disable it set * {@link AgentServlet} is on the classpath. To disable it set
* {@code management.jolokia.enabled=false}. * {@code management.jolokia.enabled=false}.
*
* <p> * <p>
* Additional configuration parameters for Jolokia can be provided by specifying * Additional configuration parameters for Jolokia can be provided by specifying
* {@code management.jolokia.config.*} properties. See the * {@code management.jolokia.config.*} properties. See the
......
...@@ -31,6 +31,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe ...@@ -31,6 +31,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
* Security configuration for management endpoints. * Security configuration for management endpoints.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0
*/ */
@Configuration @Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
...@@ -39,9 +40,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe ...@@ -39,9 +40,9 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
public class ManagementWebSecurityAutoConfiguration { public class ManagementWebSecurityAutoConfiguration {
@Bean @Bean
public EndpointPathResolver managementEndpointPathResolver(ManagementServerProperties properties) { public EndpointPathResolver managementEndpointPathResolver(
ManagementServerProperties properties) {
return new ManagementEndpointPathResolver(properties); return new ManagementEndpointPathResolver(properties);
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -66,32 +66,33 @@ public class CloudFoundryActuatorAutoConfiguration { ...@@ -66,32 +66,33 @@ public class CloudFoundryActuatorAutoConfiguration {
@Bean @Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping( public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
EndpointProvider<WebEndpointOperation> provider, EndpointProvider<WebEndpointOperation> provider, Environment environment,
Environment environment, RestTemplateBuilder builder) { RestTemplateBuilder builder) {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = new CloudFoundryWebEndpointServletHandlerMapping( return new CloudFoundryWebEndpointServletHandlerMapping(
"/cloudfoundryapplication", provider.getEndpoints(), "/cloudfoundryapplication", provider.getEndpoints(),
getCorsConfiguration(), getSecurityInterceptor(builder, environment)); getCorsConfiguration(), getSecurityInterceptor(builder, environment));
return handlerMapping;
} }
private CloudFoundrySecurityInterceptor getSecurityInterceptor( private CloudFoundrySecurityInterceptor getSecurityInterceptor(
RestTemplateBuilder restTemplateBuilder, Environment environment) { RestTemplateBuilder restTemplateBuilder, Environment environment) {
CloudFoundrySecurityService cloudfoundrySecurityService = getCloudFoundrySecurityService( CloudFoundrySecurityService cloudfoundrySecurityService = getCloudFoundrySecurityService(
restTemplateBuilder, environment); restTemplateBuilder, environment);
TokenValidator tokenValidator = new TokenValidator(cloudfoundrySecurityService); TokenValidator tokenValidator = new TokenValidator(
return new CloudFoundrySecurityInterceptor( cloudfoundrySecurityService);
tokenValidator, cloudfoundrySecurityService, return new CloudFoundrySecurityInterceptor(tokenValidator,
cloudfoundrySecurityService,
environment.getProperty("vcap.application.application_id")); environment.getProperty("vcap.application.application_id"));
} }
private CloudFoundrySecurityService getCloudFoundrySecurityService( private CloudFoundrySecurityService getCloudFoundrySecurityService(
RestTemplateBuilder restTemplateBuilder, Environment environment) { RestTemplateBuilder restTemplateBuilder, Environment environment) {
String cloudControllerUrl = environment.getProperty("vcap.application.cf_api"); String cloudControllerUrl = environment
.getProperty("vcap.application.cf_api");
boolean skipSslValidation = environment.getProperty( boolean skipSslValidation = environment.getProperty(
"management.cloudfoundry.skip-ssl-validation", Boolean.class, false); "management.cloudfoundry.skip-ssl-validation", Boolean.class, false);
return cloudControllerUrl == null ? null return (cloudControllerUrl == null ? null
: new CloudFoundrySecurityService(restTemplateBuilder, cloudControllerUrl, : new CloudFoundrySecurityService(restTemplateBuilder,
skipSslValidation); cloudControllerUrl, skipSslValidation));
} }
private CorsConfiguration getCorsConfiguration() { private CorsConfiguration getCorsConfiguration() {
...@@ -107,9 +108,9 @@ public class CloudFoundryActuatorAutoConfiguration { ...@@ -107,9 +108,9 @@ public class CloudFoundryActuatorAutoConfiguration {
} }
/** /**
* {@link WebSecurityConfigurer} to tell Spring Security to * {@link WebSecurityConfigurer} to tell Spring Security to ignore cloudfoundry
* ignore cloudfoundry specific paths. The Cloud foundry endpoints * specific paths. The Cloud foundry endpoints are protected by their own security
* are protected by their own security interceptor. * interceptor.
*/ */
@ConditionalOnClass(WebSecurity.class) @ConditionalOnClass(WebSecurity.class)
@Order(SecurityProperties.IGNORED_ORDER) @Order(SecurityProperties.IGNORED_ORDER)
...@@ -119,7 +120,8 @@ public class CloudFoundryActuatorAutoConfiguration { ...@@ -119,7 +120,8 @@ public class CloudFoundryActuatorAutoConfiguration {
@Override @Override
public void init(WebSecurity builder) throws Exception { public void init(WebSecurity builder) throws Exception {
builder.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**")); builder.ignoring().requestMatchers(
new AntPathRequestMatcher("/cloudfoundryapplication/**"));
} }
@Override @Override
......
...@@ -52,18 +52,19 @@ class CloudFoundrySecurityInterceptor { ...@@ -52,18 +52,19 @@ class CloudFoundrySecurityInterceptor {
this.applicationId = applicationId; this.applicationId = applicationId;
} }
SecurityResponse preHandle(HttpServletRequest request, SecurityResponse preHandle(HttpServletRequest request, String endpointId) {
String endpointId) {
if (CorsUtils.isPreFlightRequest(request)) { if (CorsUtils.isPreFlightRequest(request)) {
return SecurityResponse.success(); return SecurityResponse.success();
} }
try { try {
if (!StringUtils.hasText(this.applicationId)) { if (!StringUtils.hasText(this.applicationId)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE, throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
"Application id is not available"); "Application id is not available");
} }
if (this.cloudFoundrySecurityService == null) { if (this.cloudFoundrySecurityService == null) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE, throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.SERVICE_UNAVAILABLE,
"Cloud controller URL is not available"); "Cloud controller URL is not available");
} }
if (HttpMethod.OPTIONS.matches(request.getMethod())) { if (HttpMethod.OPTIONS.matches(request.getMethod())) {
...@@ -75,21 +76,23 @@ class CloudFoundrySecurityInterceptor { ...@@ -75,21 +76,23 @@ class CloudFoundrySecurityInterceptor {
logger.error(ex); logger.error(ex);
if (ex instanceof CloudFoundryAuthorizationException) { if (ex instanceof CloudFoundryAuthorizationException) {
CloudFoundryAuthorizationException cfException = (CloudFoundryAuthorizationException) ex; CloudFoundryAuthorizationException cfException = (CloudFoundryAuthorizationException) ex;
return new SecurityResponse(cfException.getStatusCode(), "{\"security_error\":\"" + cfException.getMessage() + "\"}"); return new SecurityResponse(cfException.getStatusCode(),
"{\"security_error\":\"" + cfException.getMessage() + "\"}");
} }
return new SecurityResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage()); return new SecurityResponse(HttpStatus.INTERNAL_SERVER_ERROR,
ex.getMessage());
} }
return SecurityResponse.success(); return SecurityResponse.success();
} }
private void check(HttpServletRequest request, String path) private void check(HttpServletRequest request, String path) throws Exception {
throws Exception {
Token token = getToken(request); Token token = getToken(request);
this.tokenValidator.validate(token); this.tokenValidator.validate(token);
AccessLevel accessLevel = this.cloudFoundrySecurityService AccessLevel accessLevel = this.cloudFoundrySecurityService
.getAccessLevel(token.toString(), this.applicationId); .getAccessLevel(token.toString(), this.applicationId);
if (!accessLevel.isAccessAllowed(path)) { if (!accessLevel.isAccessAllowed(path)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.ACCESS_DENIED, throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.ACCESS_DENIED,
"Access denied"); "Access denied");
} }
accessLevel.put(request); accessLevel.put(request);
...@@ -100,7 +103,8 @@ class CloudFoundrySecurityInterceptor { ...@@ -100,7 +103,8 @@ class CloudFoundrySecurityInterceptor {
String bearerPrefix = "bearer "; String bearerPrefix = "bearer ";
if (authorization == null if (authorization == null
|| !authorization.toLowerCase().startsWith(bearerPrefix)) { || !authorization.toLowerCase().startsWith(bearerPrefix)) {
throw new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.MISSING_AUTHORIZATION, throw new CloudFoundryAuthorizationException(
CloudFoundryAuthorizationException.Reason.MISSING_AUTHORIZATION,
"Authorization header is missing or invalid"); "Authorization header is missing or invalid");
} }
return new Token(authorization.substring(bearerPrefix.length())); return new Token(authorization.substring(bearerPrefix.length()));
...@@ -116,7 +120,7 @@ class CloudFoundrySecurityInterceptor { ...@@ -116,7 +120,7 @@ class CloudFoundrySecurityInterceptor {
private final String message; private final String message;
SecurityResponse(HttpStatus status) { SecurityResponse(HttpStatus status) {
this (status, null); this(status, null);
} }
SecurityResponse(HttpStatus status, String message) { SecurityResponse(HttpStatus status, String message) {
...@@ -135,7 +139,7 @@ class CloudFoundrySecurityInterceptor { ...@@ -135,7 +139,7 @@ class CloudFoundrySecurityInterceptor {
static SecurityResponse success() { static SecurityResponse success() {
return new SecurityResponse(HttpStatus.OK); return new SecurityResponse(HttpStatus.OK);
} }
} }
} }
...@@ -50,18 +50,20 @@ import org.springframework.web.servlet.HandlerMapping; ...@@ -50,18 +50,20 @@ import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
/** /**
* A custom {@link RequestMappingInfoHandlerMapping} that makes web endpoints available * A custom {@link RequestMappingInfoHandlerMapping} that makes web endpoints available on
* on Cloudfoundry specific URLS over HTTP using Spring MVC. * Cloudfoundry specific URLS over HTTP using Spring MVC.
* *
* @author Madhura Bhave * @author Madhura Bhave
*/ */
class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointServletHandlerMapping { class CloudFoundryWebEndpointServletHandlerMapping
extends AbstractWebEndpointServletHandlerMapping {
private final Method handle = ReflectionUtils.findMethod(OperationHandler.class, private final Method handle = ReflectionUtils.findMethod(OperationHandler.class,
"handle", HttpServletRequest.class, Map.class); "handle", HttpServletRequest.class, Map.class);
private final Method links = ReflectionUtils.findMethod( private final Method links = ReflectionUtils.findMethod(
CloudFoundryWebEndpointServletHandlerMapping.class, "links", HttpServletRequest.class, HttpServletResponse.class); CloudFoundryWebEndpointServletHandlerMapping.class, "links",
HttpServletRequest.class, HttpServletResponse.class);
private static final Log logger = LogFactory private static final Log logger = LogFactory
.getLog(CloudFoundryWebEndpointServletHandlerMapping.class); .getLog(CloudFoundryWebEndpointServletHandlerMapping.class);
...@@ -70,7 +72,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -70,7 +72,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
private final EndpointLinksResolver endpointLinksResolver = new EndpointLinksResolver(); private final EndpointLinksResolver endpointLinksResolver = new EndpointLinksResolver();
CloudFoundryWebEndpointServletHandlerMapping(String endpointPath, Collection<EndpointInfo<WebEndpointOperation>> webEndpoints, CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor) { CloudFoundryWebEndpointServletHandlerMapping(String endpointPath,
Collection<EndpointInfo<WebEndpointOperation>> webEndpoints,
CorsConfiguration corsConfiguration,
CloudFoundrySecurityInterceptor securityInterceptor) {
super(endpointPath, webEndpoints, corsConfiguration); super(endpointPath, webEndpoints, corsConfiguration);
this.securityInterceptor = securityInterceptor; this.securityInterceptor = securityInterceptor;
} }
...@@ -81,27 +86,32 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -81,27 +86,32 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
} }
@ResponseBody @ResponseBody
private Map<String, Map<String, Link>> links(HttpServletRequest request, HttpServletResponse response) { private Map<String, Map<String, Link>> links(HttpServletRequest request,
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor.preHandle(request, ""); HttpServletResponse response) {
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor
.preHandle(request, "");
if (!securityResponse.getStatus().equals(HttpStatus.OK)) { if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
sendFailureResponse(response, securityResponse); sendFailureResponse(response, securityResponse);
} }
AccessLevel accessLevel = AccessLevel.get(request); AccessLevel accessLevel = AccessLevel.get(request);
Map<String, Link> links = this.endpointLinksResolver Map<String, Link> links = this.endpointLinksResolver.resolveLinks(getEndpoints(),
.resolveLinks(getEndpoints(), request.getRequestURL().toString()); request.getRequestURL().toString());
Map<String, Link> filteredLinks = new LinkedHashMap<>(); Map<String, Link> filteredLinks = new LinkedHashMap<>();
if (accessLevel == null) { if (accessLevel == null) {
return Collections.singletonMap("_links", filteredLinks); return Collections.singletonMap("_links", filteredLinks);
} }
filteredLinks = links.entrySet().stream() filteredLinks = links.entrySet().stream()
.filter(e -> e.getKey().equals("self") || accessLevel.isAccessAllowed(e.getKey())) .filter(e -> e.getKey().equals("self")
|| accessLevel.isAccessAllowed(e.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return Collections.singletonMap("_links", filteredLinks); return Collections.singletonMap("_links", filteredLinks);
} }
private void sendFailureResponse(HttpServletResponse response, CloudFoundrySecurityInterceptor.SecurityResponse securityResponse) { private void sendFailureResponse(HttpServletResponse response,
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse) {
try { try {
response.sendError(securityResponse.getStatus().value(), securityResponse.getMessage()); response.sendError(securityResponse.getStatus().value(),
securityResponse.getMessage());
} }
catch (Exception ex) { catch (Exception ex) {
logger.debug("Failed to send error response", ex); logger.debug("Failed to send error response", ex);
...@@ -111,7 +121,9 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -111,7 +121,9 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
@Override @Override
protected void registerMappingForOperation(WebEndpointOperation operation) { protected void registerMappingForOperation(WebEndpointOperation operation) {
registerMapping(createRequestMappingInfo(operation), registerMapping(createRequestMappingInfo(operation),
new OperationHandler(operation.getInvoker(), operation.getId(), this.securityInterceptor), this.handle); new OperationHandler(operation.getInvoker(), operation.getId(),
this.securityInterceptor),
this.handle);
} }
/** /**
...@@ -125,7 +137,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -125,7 +137,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
private final CloudFoundrySecurityInterceptor securityInterceptor; private final CloudFoundrySecurityInterceptor securityInterceptor;
OperationHandler(OperationInvoker operationInvoker, String id, CloudFoundrySecurityInterceptor securityInterceptor) { OperationHandler(OperationInvoker operationInvoker, String id,
CloudFoundrySecurityInterceptor securityInterceptor) {
this.operationInvoker = operationInvoker; this.operationInvoker = operationInvoker;
this.endpointId = id; this.endpointId = id;
this.securityInterceptor = securityInterceptor; this.securityInterceptor = securityInterceptor;
...@@ -135,7 +148,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -135,7 +148,8 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
@ResponseBody @ResponseBody
public Object handle(HttpServletRequest request, public Object handle(HttpServletRequest request,
@RequestBody(required = false) Map<String, String> body) { @RequestBody(required = false) Map<String, String> body) {
CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor.preHandle(request, this.endpointId); CloudFoundrySecurityInterceptor.SecurityResponse securityResponse = this.securityInterceptor
.preHandle(request, this.endpointId);
if (!securityResponse.getStatus().equals(HttpStatus.OK)) { if (!securityResponse.getStatus().equals(HttpStatus.OK)) {
return failureResponse(securityResponse); return failureResponse(securityResponse);
} }
...@@ -155,8 +169,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -155,8 +169,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
} }
} }
private Object failureResponse(CloudFoundrySecurityInterceptor.SecurityResponse response) { private Object failureResponse(
return handleResult(new WebEndpointResponse<>(response.getMessage(), response.getStatus().value())); CloudFoundrySecurityInterceptor.SecurityResponse response) {
return handleResult(new WebEndpointResponse<>(response.getMessage(),
response.getStatus().value()));
} }
private Object handleResult(Object result) { private Object handleResult(Object result) {
...@@ -179,4 +195,3 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe ...@@ -179,4 +195,3 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebEndpointSe
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -91,4 +91,3 @@ class SkipSslVerificationHttpRequestFactory extends SimpleClientHttpRequestFacto ...@@ -91,4 +91,3 @@ class SkipSslVerificationHttpRequestFactory extends SimpleClientHttpRequestFacto
} }
} }
...@@ -123,4 +123,3 @@ class Token { ...@@ -123,4 +123,3 @@ class Token {
}; };
} }
...@@ -139,4 +139,3 @@ class TokenValidator { ...@@ -139,4 +139,3 @@ class TokenValidator {
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -32,7 +32,7 @@ import java.util.regex.PatternSyntaxException; ...@@ -32,7 +32,7 @@ import java.util.regex.PatternSyntaxException;
* @author Phillip Webb * @author Phillip Webb
* @author Sergei Egorov * @author Sergei Egorov
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 2.0.0 * @author Dylian Bego
*/ */
abstract class NamePatternFilter<T> { abstract class NamePatternFilter<T> {
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -16,7 +16,9 @@ ...@@ -16,7 +16,9 @@
package org.springframework.boot.actuate.endpoint.web; package org.springframework.boot.actuate.endpoint.web;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
...@@ -206,12 +208,7 @@ public class HeapDumpWebEndpoint { ...@@ -206,12 +208,7 @@ public class HeapDumpWebEndpoint {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
try { closeThenDeleteFile(readableChannel);
readableChannel.close();
}
finally {
deleteFile();
}
} }
@Override @Override
...@@ -224,62 +221,25 @@ public class HeapDumpWebEndpoint { ...@@ -224,62 +221,25 @@ public class HeapDumpWebEndpoint {
@Override @Override
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
InputStream delegate = super.getInputStream(); return new FilterInputStream(super.getInputStream()) {
return new InputStream() {
@Override
public int read() throws IOException {
return delegate.read();
}
@Override
public int read(byte[] b) throws IOException {
return delegate.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return delegate.read(b, off, len);
}
@Override
public long skip(long n) throws IOException {
return delegate.skip(n);
}
@Override
public int available() throws IOException {
return delegate.available();
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
try { closeThenDeleteFile(this.in);
delegate.close();
}
finally {
deleteFile();
}
}
@Override
public synchronized void mark(int readlimit) {
delegate.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
delegate.reset();
}
@Override
public boolean markSupported() {
return delegate.markSupported();
} }
}; };
} }
private void closeThenDeleteFile(Closeable closeable) throws IOException {
try {
closeable.close();
}
finally {
deleteFile();
}
}
private void deleteFile() { private void deleteFile() {
try { try {
Files.delete(getFile().toPath()); Files.delete(getFile().toPath());
......
...@@ -35,8 +35,7 @@ public class HealthIndicatorFactory { ...@@ -35,8 +35,7 @@ public class HealthIndicatorFactory {
* @return a {@link HealthIndicator} that delegates to the specified * @return a {@link HealthIndicator} that delegates to the specified
* {@code healthIndicators}. * {@code healthIndicators}.
*/ */
public HealthIndicator createHealthIndicator( public HealthIndicator createHealthIndicator(HealthAggregator healthAggregator,
HealthAggregator healthAggregator,
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
Assert.notNull(healthAggregator, "HealthAggregator must not be null"); Assert.notNull(healthAggregator, "HealthAggregator must not be null");
Assert.notNull(healthIndicators, "HealthIndicators must not be null"); Assert.notNull(healthIndicators, "HealthIndicators must not be null");
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -118,10 +118,9 @@ public class ConditionalOnEnabledEndpointTests { ...@@ -118,10 +118,9 @@ public class ConditionalOnEnabledEndpointTests {
@Test @Test
public void disabledEvenWithEnabledGeneralProperties() { public void disabledEvenWithEnabledGeneralProperties() {
this.contextRunner.withUserConfiguration(FooConfig.class) this.contextRunner.withUserConfiguration(FooConfig.class).withPropertyValues(
.withPropertyValues("endpoints.default.enabled=true", "endpoints.default.enabled=true", "endpoints.default.web.enabled=true",
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false")
"endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean("foo")); .run((context) -> assertThat(context).doesNotHaveBean("foo"));
} }
......
...@@ -41,7 +41,8 @@ public class DefaultEndpointObjectNameFactoryTests { ...@@ -41,7 +41,8 @@ public class DefaultEndpointObjectNameFactoryTests {
private final MockEnvironment environment = new MockEnvironment(); private final MockEnvironment environment = new MockEnvironment();
private final JmxEndpointExporterProperties properties = new JmxEndpointExporterProperties(this.environment); private final JmxEndpointExporterProperties properties = new JmxEndpointExporterProperties(
this.environment);
private final MBeanServer mBeanServer = mock(MBeanServer.class); private final MBeanServer mBeanServer = mock(MBeanServer.class);
...@@ -50,23 +51,23 @@ public class DefaultEndpointObjectNameFactoryTests { ...@@ -50,23 +51,23 @@ public class DefaultEndpointObjectNameFactoryTests {
@Test @Test
public void generateObjectName() { public void generateObjectName() {
ObjectName objectName = generateObjectName(endpoint("Test")); ObjectName objectName = generateObjectName(endpoint("Test"));
assertThat(objectName.toString()).isEqualTo( assertThat(objectName.toString())
"org.springframework.boot:type=Endpoint,name=Test"); .isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
} }
@Test @Test
public void generateObjectNameWithCapitalizedId() { public void generateObjectNameWithCapitalizedId() {
ObjectName objectName = generateObjectName(endpoint("test")); ObjectName objectName = generateObjectName(endpoint("test"));
assertThat(objectName.toString()).isEqualTo( assertThat(objectName.toString())
"org.springframework.boot:type=Endpoint,name=Test"); .isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
} }
@Test @Test
public void generateObjectNameWithCustomDomain() { public void generateObjectNameWithCustomDomain() {
this.properties.setDomain("com.example.acme"); this.properties.setDomain("com.example.acme");
ObjectName objectName = generateObjectName(endpoint("test")); ObjectName objectName = generateObjectName(endpoint("test"));
assertThat(objectName.toString()).isEqualTo( assertThat(objectName.toString())
"com.example.acme:type=Endpoint,name=Test"); .isEqualTo("com.example.acme:type=Endpoint,name=Test");
} }
@Test @Test
...@@ -86,17 +87,18 @@ public class DefaultEndpointObjectNameFactoryTests { ...@@ -86,17 +87,18 @@ public class DefaultEndpointObjectNameFactoryTests {
ObjectName objectName = generateObjectName(endpoint("test")); ObjectName objectName = generateObjectName(endpoint("test"));
assertThat(objectName.getKeyProperty("counter")).isEqualTo("42"); assertThat(objectName.getKeyProperty("counter")).isEqualTo("42");
assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar"); assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar");
assertThat(objectName.toString()).startsWith( assertThat(objectName.toString())
"org.springframework.boot:type=Endpoint,name=Test,"); .startsWith("org.springframework.boot:type=Endpoint,name=Test,");
} }
@Test @Test
public void generateObjectNameWithDuplicate() throws MalformedObjectNameException { public void generateObjectNameWithDuplicate() throws MalformedObjectNameException {
this.contextId = "testContext"; this.contextId = "testContext";
given(this.mBeanServer.queryNames(new ObjectName( given(this.mBeanServer.queryNames(
"org.springframework.boot:type=Endpoint,name=Test,*"), null)) new ObjectName("org.springframework.boot:type=Endpoint,name=Test,*"),
.willReturn(Collections.singleton( null)).willReturn(
new ObjectName("org.springframework.boot:type=Endpoint,name=Test"))); Collections.singleton(new ObjectName(
"org.springframework.boot:type=Endpoint,name=Test")));
ObjectName objectName = generateObjectName(endpoint("test")); ObjectName objectName = generateObjectName(endpoint("test"));
assertThat(objectName.toString()).isEqualTo( assertThat(objectName.toString()).isEqualTo(
"org.springframework.boot:type=Endpoint,name=Test,context=testContext"); "org.springframework.boot:type=Endpoint,name=Test,context=testContext");
......
...@@ -57,25 +57,18 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests { ...@@ -57,25 +57,18 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests {
@Test @Test
public void webEndpointsAreDisabledByDefault() { public void webEndpointsAreDisabledByDefault() {
this.contextRunner.run(context -> { this.contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig")) assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops")) assertThat(isExposed(mvc, HttpMethod.GET, "env")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "health")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "info")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health")) assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse(); assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings")) assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace")).isFalse();
}); });
} }
...@@ -84,60 +77,45 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests { ...@@ -84,60 +77,45 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests {
WebApplicationContextRunner contextRunner = this.contextRunner WebApplicationContextRunner contextRunner = this.contextRunner
.withPropertyValues("endpoints.default.web.enabled=true"); .withPropertyValues("endpoints.default.web.enabled=true");
contextRunner.run(context -> { contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig")) assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isTrue();
.isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")) assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isTrue();
.isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "env")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops")) assertThat(isExposed(mvc, HttpMethod.GET, "health")).isTrue();
.isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "info")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health")) assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isTrue();
.isTrue(); assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings")) assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isTrue();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace"))
.isTrue();
}); });
} }
@Test @Test
public void singleWebEndpointCanBeEnabled() { public void singleWebEndpointCanBeEnabled() {
WebApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues( WebApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
"endpoints.default.web.enabled=false", "endpoints.beans.web.enabled=true"); "endpoints.default.web.enabled=false",
"endpoints.beans.web.enabled=true");
contextRunner.run((context) -> { contextRunner.run((context) -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig")) assertThat(isExposed(mvc, HttpMethod.GET, "autoconfig")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "beans")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isTrue(); assertThat(isExposed(mvc, HttpMethod.GET, "configprops")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops")) assertThat(isExposed(mvc, HttpMethod.GET, "env")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "health")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "info")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health")) assertThat(isExposed(mvc, HttpMethod.GET, "mappings")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "metrics")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse(); assertThat(isExposed(mvc, HttpMethod.POST, "shutdown")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings")) assertThat(isExposed(mvc, HttpMethod.GET, "threaddump")).isFalse();
.isFalse(); assertThat(isExposed(mvc, HttpMethod.GET, "trace")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace"))
.isFalse();
}); });
} }
private boolean isExposed(MockMvc mockMvc, HttpMethod method, String path) private boolean isExposed(MockMvc mockMvc, HttpMethod method, String path)
throws Exception { throws Exception {
path = "/application/" + path;
MvcResult mvcResult = mockMvc.perform(request(method, path)).andReturn(); MvcResult mvcResult = mockMvc.perform(request(method, path)).andReturn();
int status = mvcResult.getResponse().getStatus(); int status = mvcResult.getResponse().getStatus();
if (status == HttpStatus.SC_OK) { if (status == HttpStatus.SC_OK) {
......
...@@ -254,9 +254,8 @@ public class EndpointEnablementProviderTests { ...@@ -254,9 +254,8 @@ public class EndpointEnablementProviderTests {
@Test @Test
public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() { public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() {
validate( validate(getEndpointEnablement("foo", true, EndpointExposure.JMX,
getEndpointEnablement("foo", true, EndpointExposure.JMX, "endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
"endpoints.default.enabled=false", "endpoints.default.web.enabled=true"),
false, "found property endpoints.default.enabled"); false, "found property endpoints.default.enabled");
} }
...@@ -264,8 +263,8 @@ public class EndpointEnablementProviderTests { ...@@ -264,8 +263,8 @@ public class EndpointEnablementProviderTests {
public void specificDisabledWithEndpointPropertyEvenWithEnabledGeneralProperties() { public void specificDisabledWithEndpointPropertyEvenWithEnabledGeneralProperties() {
EndpointEnablement enablement = getEndpointEnablement("foo", true, EndpointEnablement enablement = getEndpointEnablement("foo", true,
EndpointExposure.WEB, "endpoints.default.enabled=true", EndpointExposure.WEB, "endpoints.default.enabled=true",
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true", "endpoints.default.web.enabled=true",
"endpoints.foo.enabled=false"); "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=false");
validate(enablement, false, "found property endpoints.foo.enabled"); validate(enablement, false, "found property endpoints.foo.enabled");
} }
...@@ -273,8 +272,9 @@ public class EndpointEnablementProviderTests { ...@@ -273,8 +272,9 @@ public class EndpointEnablementProviderTests {
public void specificDisabledWithTechPropertyEvenWithEnabledGeneralProperties() { public void specificDisabledWithTechPropertyEvenWithEnabledGeneralProperties() {
EndpointEnablement enablement = getEndpointEnablement("foo", true, EndpointEnablement enablement = getEndpointEnablement("foo", true,
EndpointExposure.WEB, "endpoints.default.enabled=true", EndpointExposure.WEB, "endpoints.default.enabled=true",
"endpoints.default.web.enabled=true", "endpoints.default.jmx.enabled=true", "endpoints.default.web.enabled=true",
"endpoints.foo.enabled=true", "endpoints.foo.web.enabled=false"); "endpoints.default.jmx.enabled=true", "endpoints.foo.enabled=true",
"endpoints.foo.web.enabled=false");
validate(enablement, false, "found property endpoints.foo.web.enabled"); validate(enablement, false, "found property endpoints.foo.web.enabled");
} }
......
...@@ -73,9 +73,7 @@ public class WebEndpointManagementContextConfigurationTests { ...@@ -73,9 +73,7 @@ public class WebEndpointManagementContextConfigurationTests {
contextRunner.run((context) -> { contextRunner.run((context) -> {
HealthWebEndpointExtension extension = context HealthWebEndpointExtension extension = context
.getBean(HealthWebEndpointExtension.class); .getBean(HealthWebEndpointExtension.class);
@SuppressWarnings("unchecked") Map<String, Integer> statusMappings = getStatusMapping(extension);
Map<String, Integer> statusMappings = ((HealthStatusHttpMapper) ReflectionTestUtils
.getField(extension, "statusHttpMapper")).getStatusMapping();
assertThat(statusMappings).containsEntry("DOWN", 503); assertThat(statusMappings).containsEntry("DOWN", 503);
assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503); assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503);
assertThat(statusMappings).containsEntry("CUSTOM", 500); assertThat(statusMappings).containsEntry("CUSTOM", 500);
...@@ -102,9 +100,7 @@ public class WebEndpointManagementContextConfigurationTests { ...@@ -102,9 +100,7 @@ public class WebEndpointManagementContextConfigurationTests {
contextRunner.run((context) -> { contextRunner.run((context) -> {
StatusWebEndpointExtension extension = context StatusWebEndpointExtension extension = context
.getBean(StatusWebEndpointExtension.class); .getBean(StatusWebEndpointExtension.class);
@SuppressWarnings("unchecked") Map<String, Integer> statusMappings = getStatusMapping(extension);
Map<String, Integer> statusMappings = ((HealthStatusHttpMapper) ReflectionTestUtils
.getField(extension, "statusHttpMapper")).getStatusMapping();
assertThat(statusMappings).containsEntry("DOWN", 503); assertThat(statusMappings).containsEntry("DOWN", 503);
assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503); assertThat(statusMappings).containsEntry("OUT_OF_SERVICE", 503);
assertThat(statusMappings).containsEntry("CUSTOM", 500); assertThat(statusMappings).containsEntry("CUSTOM", 500);
...@@ -161,8 +157,7 @@ public class WebEndpointManagementContextConfigurationTests { ...@@ -161,8 +157,7 @@ public class WebEndpointManagementContextConfigurationTests {
} }
private void beanIsAutoConfigured(Class<?> beanType, Class<?>... config) { private void beanIsAutoConfigured(Class<?> beanType, Class<?>... config) {
contextRunner() contextRunner().withPropertyValues("endpoints.default.web.enabled:true")
.withPropertyValues("endpoints.default.web.enabled:true")
.withUserConfiguration(config) .withUserConfiguration(config)
.run((context) -> assertThat(context).hasSingleBean(beanType)); .run((context) -> assertThat(context).hasSingleBean(beanType));
} }
...@@ -178,6 +173,11 @@ public class WebEndpointManagementContextConfigurationTests { ...@@ -178,6 +173,11 @@ public class WebEndpointManagementContextConfigurationTests {
AutoConfigurations.of(WebEndpointManagementContextConfiguration.class)); AutoConfigurations.of(WebEndpointManagementContextConfiguration.class));
} }
private Map<String, Integer> getStatusMapping(Object extension) {
return ((HealthStatusHttpMapper) ReflectionTestUtils.getField(extension,
"statusHttpMapper")).getStatusMapping();
}
@Configuration @Configuration
static class HealthEndpointConfiguration { static class HealthEndpointConfiguration {
......
...@@ -63,28 +63,30 @@ public class JolokiaManagementContextConfigurationTests { ...@@ -63,28 +63,30 @@ public class JolokiaManagementContextConfigurationTests {
@Test @Test
public void customPath() { public void customPath() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true", this.contextRunner
"management.jolokia.path=/lokia").run( .withPropertyValues("management.jolokia.enabled=true",
isDefinedOnPath("/application/lokia/*")); "management.jolokia.path=/lokia")
.run(isDefinedOnPath("/application/lokia/*"));
} }
@Test @Test
public void customManagementPath() { public void customManagementPath() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true", this.contextRunner
"management.context-path=/admin").run( .withPropertyValues("management.jolokia.enabled=true",
isDefinedOnPath("/admin/jolokia/*")); "management.context-path=/admin")
.run(isDefinedOnPath("/admin/jolokia/*"));
} }
@Test @Test
public void customInitParameters() { public void customInitParameters() {
this.contextRunner.withPropertyValues("management.jolokia.enabled=true", this.contextRunner.withPropertyValues("management.jolokia.enabled=true",
"management.jolokia.config.debug=true").run((context) -> { "management.jolokia.config.debug=true").run((context) -> {
assertThat(context).hasSingleBean(ServletRegistrationBean.class); assertThat(context).hasSingleBean(ServletRegistrationBean.class);
ServletRegistrationBean<?> registrationBean = context ServletRegistrationBean<?> registrationBean = context
.getBean(ServletRegistrationBean.class); .getBean(ServletRegistrationBean.class);
assertThat(registrationBean.getInitParameters()) assertThat(registrationBean.getInitParameters())
.containsOnly(entry("debug", "true")); .containsOnly(entry("debug", "true"));
}); });
} }
private ContextConsumer<AssertableWebApplicationContext> isDefinedOnPath( private ContextConsumer<AssertableWebApplicationContext> isDefinedOnPath(
......
...@@ -385,8 +385,10 @@ public class MetricFilterAutoConfigurationTests { ...@@ -385,8 +385,10 @@ public class MetricFilterAutoConfigurationTests {
public void doesNotRecordRolledUpMetricsIfConfigured() throws Exception { public void doesNotRecordRolledUpMetricsIfConfigured() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Config.class, MetricFilterAutoConfiguration.class); context.register(Config.class, MetricFilterAutoConfiguration.class);
TestPropertyValues.of("management.metrics.filter.gauge-submissions=", TestPropertyValues
"management.metrics.filter.counter-submissions=").applyTo(context); .of("management.metrics.filter.gauge-submissions=",
"management.metrics.filter.counter-submissions=")
.applyTo(context);
context.refresh(); context.refresh();
Filter filter = context.getBean(Filter.class); Filter filter = context.getBean(Filter.class);
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test/path"); MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/test/path");
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -39,11 +39,10 @@ final class AuthorizationExceptionMatcher { ...@@ -39,11 +39,10 @@ final class AuthorizationExceptionMatcher {
public boolean matches(Object object) { public boolean matches(Object object) {
return ((object instanceof CloudFoundryAuthorizationException) return ((object instanceof CloudFoundryAuthorizationException)
&& ((CloudFoundryAuthorizationException) object) && ((CloudFoundryAuthorizationException) object)
.getReason() == reason); .getReason() == reason);
} }
}; };
} }
} }
...@@ -59,8 +59,7 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -59,8 +59,7 @@ public class CloudFoundryActuatorAutoConfigurationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(SecurityAutoConfiguration.class, this.context.register(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
JacksonAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
...@@ -80,7 +79,8 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -80,7 +79,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformActive() throws Exception { public void cloudFoundryPlatformActive() throws Exception {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(); CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping();
assertThat(handlerMapping.getEndpointPath()).isEqualTo("/cloudfoundryapplication"); assertThat(handlerMapping.getEndpointPath())
.isEqualTo("/cloudfoundryapplication");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
.getField(handlerMapping, "corsConfiguration"); .getField(handlerMapping, "corsConfiguration");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
...@@ -136,9 +136,9 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -136,9 +136,9 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") .of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.applyTo(this.context); .applyTo(this.context);
this.context.refresh(); this.context.refresh();
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = this.context.getBean( CloudFoundryWebEndpointServletHandlerMapping handlerMapping = this.context
"cloudFoundryWebEndpointServletHandlerMapping", .getBean("cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class); CloudFoundryWebEndpointServletHandlerMapping.class);
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor"); "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils Object interceptorSecurityService = ReflectionTestUtils
...@@ -152,7 +152,8 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -152,7 +152,8 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") .of("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.applyTo(this.context); .applyTo(this.context);
this.context.refresh(); this.context.refresh();
FilterChainProxy securityFilterChain = (FilterChainProxy) this.context.getBean("springSecurityFilterChain"); FilterChainProxy securityFilterChain = (FilterChainProxy) this.context
.getBean("springSecurityFilterChain");
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0); SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/cloudfoundryapplication/my-path"); request.setServletPath("/cloudfoundryapplication/my-path");
...@@ -165,8 +166,9 @@ public class CloudFoundryActuatorAutoConfigurationTests { ...@@ -165,8 +166,9 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test @Test
public void cloudFoundryPlatformInactive() throws Exception { public void cloudFoundryPlatformInactive() throws Exception {
this.context.refresh(); this.context.refresh();
assertThat(this.context.containsBean("cloudFoundryWebEndpointServletHandlerMapping")) assertThat(
.isFalse(); this.context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse();
} }
@Test @Test
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -23,8 +23,6 @@ import java.util.function.BiConsumer; ...@@ -23,8 +23,6 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.junit.Test; import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.boot.endpoint.CachingConfiguration; import org.springframework.boot.endpoint.CachingConfiguration;
import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper; import org.springframework.boot.endpoint.ConversionServiceOperationParameterMapper;
...@@ -52,39 +50,40 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc; ...@@ -52,39 +50,40 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
/** /**
* Integration tests for web endpoints exposed using Spring MVC * Integration tests for web endpoints exposed using Spring MVC on CloudFoundry.
* on CloudFoundry.
* *
* @author Madhura Bhave * @author Madhura Bhave
*/ */
public class CloudFoundryMvcWebEndpointIntegrationTests { public class CloudFoundryMvcWebEndpointIntegrationTests {
private static TokenValidator tokenValidator = Mockito.mock(TokenValidator.class); private static TokenValidator tokenValidator = mock(TokenValidator.class);
private static CloudFoundrySecurityService securityService = Mockito.mock(CloudFoundrySecurityService.class); private static CloudFoundrySecurityService securityService = mock(
CloudFoundrySecurityService.class);
@Test @Test
public void operationWithSecurityInterceptorForbidden() throws Exception { public void operationWithSecurityInterceptorForbidden() throws Exception {
BDDMockito.doNothing().when(tokenValidator).validate(any()); given(securityService.getAccessLevel(any(), eq("app-id")))
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED); .willReturn(AccessLevel.RESTRICTED);
load(TestEndpointConfiguration.class, (client) -> { load(TestEndpointConfiguration.class, (client) -> {
client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON) client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()) .header("Authorization", "bearer " + mockAccessToken()).exchange()
.exchange().expectStatus().isEqualTo(HttpStatus.FORBIDDEN); .expectStatus().isEqualTo(HttpStatus.FORBIDDEN);
}); });
} }
@Test @Test
public void operationWithSecurityInterceptorSuccess() throws Exception { public void operationWithSecurityInterceptorSuccess() throws Exception {
BDDMockito.doNothing().when(tokenValidator).validate(any()); given(securityService.getAccessLevel(any(), eq("app-id")))
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL); .willReturn(AccessLevel.FULL);
load(TestEndpointConfiguration.class, (client) -> { load(TestEndpointConfiguration.class, (client) -> {
client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON) client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()) .header("Authorization", "bearer " + mockAccessToken()).exchange()
.exchange().expectStatus().isEqualTo(HttpStatus.OK); .expectStatus().isEqualTo(HttpStatus.OK);
}); });
} }
...@@ -103,14 +102,14 @@ public class CloudFoundryMvcWebEndpointIntegrationTests { ...@@ -103,14 +102,14 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Test @Test
public void linksToOtherEndpointsWithFullAccess() { public void linksToOtherEndpointsWithFullAccess() {
BDDMockito.doNothing().when(tokenValidator).validate(any()); given(securityService.getAccessLevel(any(), eq("app-id")))
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL); .willReturn(AccessLevel.FULL);
load(TestEndpointConfiguration.class, load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON) (client) -> client.get().uri("/cfApplication")
.header("Authorization", "bearer " + mockAccessToken()) .accept(MediaType.APPLICATION_JSON)
.exchange().expectStatus().isOk().expectBody() .header("Authorization", "bearer " + mockAccessToken()).exchange()
.jsonPath("_links.length()").isEqualTo(5) .expectStatus().isOk().expectBody().jsonPath("_links.length()")
.jsonPath("_links.self.href").isNotEmpty() .isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false) .jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty() .jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false) .jsonPath("_links.info.templated").isEqualTo(false)
...@@ -124,33 +123,35 @@ public class CloudFoundryMvcWebEndpointIntegrationTests { ...@@ -124,33 +123,35 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Test @Test
public void linksToOtherEndpointsForbidden() { public void linksToOtherEndpointsForbidden() {
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(CloudFoundryAuthorizationException.Reason.INVALID_TOKEN, "invalid-token"); CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
BDDMockito.doThrow(exception).when(tokenValidator).validate(any()); CloudFoundryAuthorizationException.Reason.INVALID_TOKEN, "invalid-token");
willThrow(exception).given(tokenValidator).validate(any());
load(TestEndpointConfiguration.class, load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON) (client) -> client.get().uri("/cfApplication")
.header("Authorization", "bearer " + mockAccessToken()) .accept(MediaType.APPLICATION_JSON)
.exchange().expectStatus().isUnauthorized()); .header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isUnauthorized());
} }
@Test @Test
public void linksToOtherEndpointsWithRestrictedAccess() { public void linksToOtherEndpointsWithRestrictedAccess() {
BDDMockito.doNothing().when(tokenValidator).validate(any()); given(securityService.getAccessLevel(any(), eq("app-id")))
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED); .willReturn(AccessLevel.RESTRICTED);
load(TestEndpointConfiguration.class, load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON) (client) -> client.get().uri("/cfApplication")
.header("Authorization", "bearer " + mockAccessToken()) .accept(MediaType.APPLICATION_JSON)
.exchange().expectStatus().isOk().expectBody() .header("Authorization", "bearer " + mockAccessToken()).exchange()
.jsonPath("_links.length()").isEqualTo(2) .expectStatus().isOk().expectBody().jsonPath("_links.length()")
.jsonPath("_links.self.href").isNotEmpty() .isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false) .jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty() .jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false) .jsonPath("_links.info.templated").isEqualTo(false)
.jsonPath("_links.env").doesNotExist() .jsonPath("_links.env").doesNotExist().jsonPath("_links.test")
.jsonPath("_links.test").doesNotExist() .doesNotExist().jsonPath("_links.test-part").doesNotExist());
.jsonPath("_links.test-part").doesNotExist());
} }
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(Class<?>... config) { private AnnotationConfigServletWebServerApplicationContext createApplicationContext(
Class<?>... config) {
return new AnnotationConfigServletWebServerApplicationContext(config); return new AnnotationConfigServletWebServerApplicationContext(config);
} }
...@@ -159,14 +160,13 @@ public class CloudFoundryMvcWebEndpointIntegrationTests { ...@@ -159,14 +160,13 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
} }
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) { private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client); BiConsumer<ApplicationContext, WebTestClient> consumer = (context,
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(configuration, CloudFoundryMvcConfiguration.class); client) -> clientConsumer.accept(client);
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(
configuration, CloudFoundryMvcConfiguration.class);
try { try {
consumer.accept(context, consumer.accept(context, WebTestClient.bindToServer()
WebTestClient.bindToServer() .baseUrl("http://localhost:" + getPort(context)).build());
.baseUrl(
"http://localhost:" + getPort(context))
.build());
} }
finally { finally {
context.close(); context.close();
...@@ -185,17 +185,20 @@ public class CloudFoundryMvcWebEndpointIntegrationTests { ...@@ -185,17 +185,20 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Bean @Bean
public CloudFoundrySecurityInterceptor interceptor() { public CloudFoundrySecurityInterceptor interceptor() {
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id"); return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
"app-id");
} }
@Bean @Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping( public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
WebAnnotationEndpointDiscoverer webEndpointDiscoverer, CloudFoundrySecurityInterceptor interceptor) { WebAnnotationEndpointDiscoverer webEndpointDiscoverer,
CloudFoundrySecurityInterceptor interceptor) {
CorsConfiguration corsConfiguration = new CorsConfiguration(); CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(Arrays.asList("http://example.com")); corsConfiguration.setAllowedOrigins(Arrays.asList("http://example.com"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST")); corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
return new CloudFoundryWebEndpointServletHandlerMapping("/cfApplication", return new CloudFoundryWebEndpointServletHandlerMapping("/cfApplication",
webEndpointDiscoverer.discoverEndpoints(), corsConfiguration, interceptor); webEndpointDiscoverer.discoverEndpoints(), corsConfiguration,
interceptor);
} }
@Bean @Bean
...@@ -302,4 +305,3 @@ public class CloudFoundryMvcWebEndpointIntegrationTests { ...@@ -302,4 +305,3 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -19,7 +19,6 @@ package org.springframework.boot.actuate.cloudfoundry; ...@@ -19,7 +19,6 @@ package org.springframework.boot.actuate.cloudfoundry;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.BDDMockito;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
...@@ -30,6 +29,7 @@ import org.springframework.mock.web.MockHttpServletRequest; ...@@ -30,6 +29,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.Base64Utils; import org.springframework.util.Base64Utils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
...@@ -62,13 +62,15 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -62,13 +62,15 @@ public class CloudFoundrySecurityInterceptorTests {
this.request.setMethod("OPTIONS"); this.request.setMethod("OPTIONS");
this.request.addHeader(HttpHeaders.ORIGIN, "http://example.com"); this.request.addHeader(HttpHeaders.ORIGIN, "http://example.com");
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"); this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK); assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
} }
@Test @Test
public void preHandleWhenTokenIsMissingShouldReturnFalse() throws Exception { public void preHandleWhenTokenIsMissingShouldReturnFalse() throws Exception {
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()) assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()); .isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
} }
...@@ -76,7 +78,8 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -76,7 +78,8 @@ public class CloudFoundrySecurityInterceptorTests {
@Test @Test
public void preHandleWhenTokenIsNotBearerShouldReturnFalse() throws Exception { public void preHandleWhenTokenIsNotBearerShouldReturnFalse() throws Exception {
this.request.addHeader("Authorization", mockAccessToken()); this.request.addHeader("Authorization", mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()) assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()); .isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
} }
...@@ -86,7 +89,8 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -86,7 +89,8 @@ public class CloudFoundrySecurityInterceptorTests {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, null); this.securityService, null);
this.request.addHeader("Authorization", "bearer " + mockAccessToken()); this.request.addHeader("Authorization", "bearer " + mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()) assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus()); .isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
} }
...@@ -97,7 +101,8 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -97,7 +101,8 @@ public class CloudFoundrySecurityInterceptorTests {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
"my-app-id"); "my-app-id");
this.request.addHeader("Authorization", "bearer " + mockAccessToken()); this.request.addHeader("Authorization", "bearer " + mockAccessToken());
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
assertThat(response.getStatus()) assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus()); .isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
} }
...@@ -106,20 +111,21 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -106,20 +111,21 @@ public class CloudFoundrySecurityInterceptorTests {
public void preHandleWhenAccessIsNotAllowedShouldReturnFalse() throws Exception { public void preHandleWhenAccessIsNotAllowedShouldReturnFalse() throws Exception {
String accessToken = mockAccessToken(); String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "bearer " + accessToken); this.request.addHeader("Authorization", "bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id")) given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED); .willReturn(AccessLevel.RESTRICTED);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
assertThat(response.getStatus()) .preHandle(this.request, "/a");
.isEqualTo(Reason.ACCESS_DENIED.getStatus()); assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
} }
@Test @Test
public void preHandleSuccessfulWithFullAccess() throws Exception { public void preHandleSuccessfulWithFullAccess() throws Exception {
String accessToken = mockAccessToken(); String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken); this.request.addHeader("Authorization", "Bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id")) given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.FULL); .willReturn(AccessLevel.FULL);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "/a"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "/a");
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class); ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture()); verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue(); Token token = tokenArgumentCaptor.getValue();
...@@ -133,9 +139,10 @@ public class CloudFoundrySecurityInterceptorTests { ...@@ -133,9 +139,10 @@ public class CloudFoundrySecurityInterceptorTests {
public void preHandleSuccessfulWithRestrictedAccess() throws Exception { public void preHandleSuccessfulWithRestrictedAccess() throws Exception {
String accessToken = mockAccessToken(); String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken); this.request.addHeader("Authorization", "Bearer " + accessToken);
BDDMockito.given(this.securityService.getAccessLevel(accessToken, "my-app-id")) given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED); .willReturn(AccessLevel.RESTRICTED);
CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor.preHandle(this.request, "info"); CloudFoundrySecurityInterceptor.SecurityResponse response = this.interceptor
.preHandle(this.request, "info");
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class); ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture()); verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue(); Token token = tokenArgumentCaptor.getValue();
......
...@@ -137,4 +137,3 @@ public class TokenTests { ...@@ -137,4 +137,3 @@ public class TokenTests {
} }
} }
...@@ -266,4 +266,3 @@ public class TokenValidatorTests { ...@@ -266,4 +266,3 @@ public class TokenValidatorTests {
} }
} }
...@@ -46,8 +46,8 @@ public class HealthEndpointTests { ...@@ -46,8 +46,8 @@ public class HealthEndpointTests {
.withDetail("first", "1").build()); .withDetail("first", "1").build());
healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP) healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP)
.withDetail("second", "2").build()); .withDetail("second", "2").build());
HealthEndpoint endpoint = new HealthEndpoint(createHealthIndicator( HealthEndpoint endpoint = new HealthEndpoint(
healthIndicators)); createHealthIndicator(healthIndicators));
Health health = endpoint.health(); Health health = endpoint.health();
assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).containsOnlyKeys("up", "upAgain"); assertThat(health.getDetails()).containsOnlyKeys("up", "upAgain");
...@@ -59,8 +59,8 @@ public class HealthEndpointTests { ...@@ -59,8 +59,8 @@ public class HealthEndpointTests {
private HealthIndicator createHealthIndicator( private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator( return new HealthIndicatorFactory()
new OrderedHealthAggregator(), healthIndicators); .createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
} }
} }
...@@ -43,8 +43,8 @@ public class StatusEndpointTests { ...@@ -43,8 +43,8 @@ public class StatusEndpointTests {
.withDetail("first", "1").build()); .withDetail("first", "1").build());
healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP) healthIndicators.put("upAgain", () -> new Health.Builder().status(Status.UP)
.withDetail("second", "2").build()); .withDetail("second", "2").build());
StatusEndpoint endpoint = new StatusEndpoint(createHealthIndicator( StatusEndpoint endpoint = new StatusEndpoint(
healthIndicators)); createHealthIndicator(healthIndicators));
Health health = endpoint.health(); Health health = endpoint.health();
assertThat(health.getStatus()).isEqualTo(Status.UP); assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).isEmpty(); assertThat(health.getDetails()).isEmpty();
...@@ -52,8 +52,8 @@ public class StatusEndpointTests { ...@@ -52,8 +52,8 @@ public class StatusEndpointTests {
private HealthIndicator createHealthIndicator( private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator( return new HealthIndicatorFactory()
new OrderedHealthAggregator(), healthIndicators); .createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
} }
} }
...@@ -65,8 +65,7 @@ public class MvcEndpointCorsIntegrationTests { ...@@ -65,8 +65,7 @@ public class MvcEndpointCorsIntegrationTests {
EndpointInfrastructureAutoConfiguration.class, EndpointInfrastructureAutoConfiguration.class,
EndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletEndpointAutoConfiguration.class); ServletEndpointAutoConfiguration.class);
TestPropertyValues.of("endpoints.default.web.enabled:true") TestPropertyValues.of("endpoints.default.web.enabled:true").applyTo(this.context);
.applyTo(this.context);
} }
@Test @Test
...@@ -144,8 +143,10 @@ public class MvcEndpointCorsIntegrationTests { ...@@ -144,8 +143,10 @@ public class MvcEndpointCorsIntegrationTests {
@Test @Test
public void allowedMethodsCanBeConfigured() throws Exception { public void allowedMethodsCanBeConfigured() throws Exception {
TestPropertyValues.of("management.endpoints.cors.allowed-origins:foo.example.com", TestPropertyValues
"management.endpoints.cors.allowed-methods:GET,HEAD").applyTo(this.context); .of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allowed-methods:GET,HEAD")
.applyTo(this.context);
createMockMvc() createMockMvc()
.perform(options("/application/beans") .perform(options("/application/beans")
.header(HttpHeaders.ORIGIN, "foo.example.com") .header(HttpHeaders.ORIGIN, "foo.example.com")
...@@ -156,16 +157,20 @@ public class MvcEndpointCorsIntegrationTests { ...@@ -156,16 +157,20 @@ public class MvcEndpointCorsIntegrationTests {
@Test @Test
public void credentialsCanBeAllowed() throws Exception { public void credentialsCanBeAllowed() throws Exception {
TestPropertyValues.of("management.endpoints.cors.allowed-origins:foo.example.com", TestPropertyValues
"management.endpoints.cors.allow-credentials:true").applyTo(this.context); .of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allow-credentials:true")
.applyTo(this.context);
performAcceptedCorsRequest().andExpect( performAcceptedCorsRequest().andExpect(
header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")); header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"));
} }
@Test @Test
public void credentialsCanBeDisabled() throws Exception { public void credentialsCanBeDisabled() throws Exception {
TestPropertyValues.of("management.endpoints.cors.allowed-origins:foo.example.com", TestPropertyValues
"management.endpoints.cors.allow-credentials:false").applyTo(this.context); .of("management.endpoints.cors.allowed-origins:foo.example.com",
"management.endpoints.cors.allow-credentials:false")
.applyTo(this.context);
performAcceptedCorsRequest().andExpect( performAcceptedCorsRequest().andExpect(
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)); header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
} }
......
...@@ -69,8 +69,8 @@ public class MvcEndpointIntegrationTests { ...@@ -69,8 +69,8 @@ public class MvcEndpointIntegrationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class); this.context.register(SecureConfiguration.class);
MockMvc mockMvc = createSecureMockMvc(); MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/application/beans") mockMvc.perform(get("/application/beans").accept(MediaType.APPLICATION_JSON))
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized()); .andExpect(status().isUnauthorized());
} }
@Test @Test
...@@ -80,8 +80,8 @@ public class MvcEndpointIntegrationTests { ...@@ -80,8 +80,8 @@ public class MvcEndpointIntegrationTests {
TestPropertyValues.of("management.context-path:/management") TestPropertyValues.of("management.context-path:/management")
.applyTo(this.context); .applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc(); MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans") mockMvc.perform(get("/management/beans").accept(MediaType.APPLICATION_JSON))
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized()); .andExpect(status().isUnauthorized());
} }
@Test @Test
...@@ -92,8 +92,7 @@ public class MvcEndpointIntegrationTests { ...@@ -92,8 +92,7 @@ public class MvcEndpointIntegrationTests {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class); this.context.register(SecureConfiguration.class);
TestPropertyValues.of("management.context-path:/management", TestPropertyValues.of("management.context-path:/management",
"endpoints.default.web.enabled=true") "endpoints.default.web.enabled=true").applyTo(this.context);
.applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc(); MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans")).andExpect(status().isOk()); mockMvc.perform(get("/management/beans")).andExpect(status().isOk());
} }
...@@ -137,7 +136,7 @@ public class MvcEndpointIntegrationTests { ...@@ -137,7 +136,7 @@ public class MvcEndpointIntegrationTests {
} }
@Import(DefaultConfiguration.class) @Import(DefaultConfiguration.class)
@ImportAutoConfiguration({ SecurityAutoConfiguration.class}) @ImportAutoConfiguration({ SecurityAutoConfiguration.class })
static class SecureConfiguration { static class SecureConfiguration {
} }
......
...@@ -57,8 +57,8 @@ public class StatusEndpointWebIntegrationTests { ...@@ -57,8 +57,8 @@ public class StatusEndpointWebIntegrationTests {
context.getBean("alphaHealthIndicator", TestHealthIndicator.class) context.getBean("alphaHealthIndicator", TestHealthIndicator.class)
.setHealth(Health.down().build()); .setHealth(Health.down().build());
client.get().uri("/application/status").exchange().expectStatus() client.get().uri("/application/status").exchange().expectStatus()
.isEqualTo(HttpStatus.SERVICE_UNAVAILABLE) .isEqualTo(HttpStatus.SERVICE_UNAVAILABLE).expectBody()
.expectBody().json("{\"status\":\"DOWN\"}"); .json("{\"status\":\"DOWN\"}");
} }
@Configuration @Configuration
......
...@@ -78,9 +78,8 @@ import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode; ...@@ -78,9 +78,8 @@ import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
* The {@link PropertySource PropertySources} that belong to the application context's * The {@link PropertySource PropertySources} that belong to the application context's
* {@link org.springframework.core.env.Environment} are reset at the end of every test. * {@link org.springframework.core.env.Environment} are reset at the end of every test.
* This means that {@link TestPropertyValues} can be used in a test without affecting the * This means that {@link TestPropertyValues} can be used in a test without affecting the
* {@code Environment} of other tests in the same class. * {@code Environment} of other tests in the same class. The runner always sets the flag
* The runner always sets the flag `endpoints.default.web.enabled` to true so that web * `endpoints.default.web.enabled` to true so that web endpoints are enabled.
* endpoints are enabled.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
...@@ -266,7 +265,8 @@ public class WebEndpointsRunner extends Suite { ...@@ -266,7 +265,8 @@ public class WebEndpointsRunner extends Suite {
private ReactiveWebEndpointsRunner(Class<?> klass) throws InitializationError { private ReactiveWebEndpointsRunner(Class<?> klass) throws InitializationError {
super(klass, "Reactive", (classes) -> { super(klass, "Reactive", (classes) -> {
ReactiveWebServerApplicationContext context = new ReactiveWebServerApplicationContext(); ReactiveWebServerApplicationContext context = new ReactiveWebServerApplicationContext();
TestPropertyValues.of("endpoints.default.web.enabled:true").applyTo(context); TestPropertyValues.of("endpoints.default.web.enabled:true")
.applyTo(context);
classes.add(ReactiveInfrastructureConfiguration.class); classes.add(ReactiveInfrastructureConfiguration.class);
context.register(classes.toArray(new Class<?>[classes.size()])); context.register(classes.toArray(new Class<?>[classes.size()]));
context.refresh(); context.refresh();
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -62,8 +62,8 @@ public class HealthIndicatorFactoryTests { ...@@ -62,8 +62,8 @@ public class HealthIndicatorFactoryTests {
private HealthIndicator createHealthIndicator( private HealthIndicator createHealthIndicator(
Map<String, HealthIndicator> healthIndicators) { Map<String, HealthIndicator> healthIndicators) {
return new HealthIndicatorFactory().createHealthIndicator( return new HealthIndicatorFactory()
new OrderedHealthAggregator(), healthIndicators); .createHealthIndicator(new OrderedHealthAggregator(), healthIndicators);
} }
} }
...@@ -51,12 +51,14 @@ public class RedisHealthIndicatorTests { ...@@ -51,12 +51,14 @@ public class RedisHealthIndicatorTests {
@Test @Test
public void indicatorExists() { public void indicatorExists() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of( new ApplicationContextRunner()
RedisAutoConfiguration.class, EndpointAutoConfiguration.class, .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class)).run((context) -> { EndpointAutoConfiguration.class,
assertThat(context).hasSingleBean(RedisConnectionFactory.class); HealthIndicatorAutoConfiguration.class))
assertThat(context).hasSingleBean(RedisHealthIndicator.class); .run((context) -> {
}); assertThat(context).hasSingleBean(RedisConnectionFactory.class);
assertThat(context).hasSingleBean(RedisHealthIndicator.class);
});
} }
@Test @Test
...@@ -74,8 +76,8 @@ public class RedisHealthIndicatorTests { ...@@ -74,8 +76,8 @@ public class RedisHealthIndicatorTests {
@Test @Test
public void redisIsDown() throws Exception { public void redisIsDown() throws Exception {
RedisConnection redisConnection = mock(RedisConnection.class); RedisConnection redisConnection = mock(RedisConnection.class);
given(redisConnection.info()).willThrow( given(redisConnection.info())
new RedisConnectionFailureException("Connection failed")); .willThrow(new RedisConnectionFailureException("Connection failed"));
RedisHealthIndicator healthIndicator = createHealthIndicator(redisConnection); RedisHealthIndicator healthIndicator = createHealthIndicator(redisConnection);
Health health = healthIndicator.health(); Health health = healthIndicator.health();
assertThat(health.getStatus()).isEqualTo(Status.DOWN); assertThat(health.getStatus()).isEqualTo(Status.DOWN);
...@@ -83,9 +85,9 @@ public class RedisHealthIndicatorTests { ...@@ -83,9 +85,9 @@ public class RedisHealthIndicatorTests {
.contains("Connection failed"); .contains("Connection failed");
} }
private RedisHealthIndicator createHealthIndicator( private RedisHealthIndicator createHealthIndicator(RedisConnection redisConnection) {
RedisConnection redisConnection) { RedisConnectionFactory redisConnectionFactory = mock(
RedisConnectionFactory redisConnectionFactory = mock(RedisConnectionFactory.class); RedisConnectionFactory.class);
given(redisConnectionFactory.getConnection()).willReturn(redisConnection); given(redisConnectionFactory.getConnection()).willReturn(redisConnection);
return new RedisHealthIndicator(redisConnectionFactory); return new RedisHealthIndicator(redisConnectionFactory);
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -50,12 +50,12 @@ import org.springframework.util.ReflectionUtils; ...@@ -50,12 +50,12 @@ import org.springframework.util.ReflectionUtils;
/** /**
* Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be * Configuration for a Spring Security in-memory {@link AuthenticationManager}. Can be
* disabled by providing a bean of type {@link AuthenticationManager}, {@link AuthenticationProvider} * disabled by providing a bean of type {@link AuthenticationManager},
* or {@link UserDetailsService}. The value provided by this configuration will become the "global" * {@link AuthenticationProvider} or {@link UserDetailsService}. The value provided by
* authentication manager (from Spring Security), or the parent of the global instance. * this configuration will become the "global" authentication manager (from Spring
* Thus it acts as a fallback when no others are provided, is used by method security if * Security), or the parent of the global instance. Thus it acts as a fallback when no
* enabled, and as a parent authentication manager for "local" authentication managers in * others are provided, is used by method security if enabled, and as a parent
* individual filter chains. * authentication manager for "local" authentication managers in individual filter chains.
* *
* @author Dave Syer * @author Dave Syer
* @author Rob Winch * @author Rob Winch
...@@ -63,8 +63,8 @@ import org.springframework.util.ReflectionUtils; ...@@ -63,8 +63,8 @@ import org.springframework.util.ReflectionUtils;
*/ */
@Configuration @Configuration
@ConditionalOnBean(ObjectPostProcessor.class) @ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean({ AuthenticationManager.class, @ConditionalOnMissingBean({ AuthenticationManager.class, AuthenticationProvider.class,
AuthenticationProvider.class, UserDetailsService.class}) UserDetailsService.class })
@Order(0) @Order(0)
public class AuthenticationManagerConfiguration { public class AuthenticationManagerConfiguration {
...@@ -102,8 +102,8 @@ public class AuthenticationManagerConfiguration { ...@@ -102,8 +102,8 @@ public class AuthenticationManagerConfiguration {
* {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)} * {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)}
* exists that adds a {@link SecurityConfigurer} to the * exists that adds a {@link SecurityConfigurer} to the
* {@link AuthenticationManagerBuilder}.</li> * {@link AuthenticationManagerBuilder}.</li>
* <li>{@link AuthenticationManagerConfiguration} * <li>{@link AuthenticationManagerConfiguration} adds
* adds {@link SpringBootAuthenticationConfigurerAdapter} so it is after the * {@link SpringBootAuthenticationConfigurerAdapter} so it is after the
* {@link SecurityConfigurer} in the first step.</li> * {@link SecurityConfigurer} in the first step.</li>
* <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can * <li>We then can default an {@link AuthenticationProvider} if necessary. Note we can
* only invoke the * only invoke the
...@@ -169,10 +169,9 @@ public class AuthenticationManagerConfiguration { ...@@ -169,10 +169,9 @@ public class AuthenticationManagerConfiguration {
return; return;
} }
String password = UUID.randomUUID().toString(); String password = UUID.randomUUID().toString();
logger.info(String.format("%n%nUsing default security password: %s%n", logger.info(
password)); String.format("%n%nUsing default security password: %s%n", password));
withUser("user").password(password) withUser("user").password(password).roles();
.roles();
setField(auth, "defaultUserDetailsService", getUserDetailsService()); setField(auth, "defaultUserDetailsService", getUserDetailsService());
super.configure(auth); super.configure(auth);
} }
......
...@@ -63,9 +63,11 @@ public class SecurityAutoConfiguration { ...@@ -63,9 +63,11 @@ public class SecurityAutoConfiguration {
} }
@Bean @Bean
public SpringBootSecurity springBootSecurity(EndpointPathResolver endpointPathResolver, public SpringBootSecurity springBootSecurity(
EndpointPathResolver endpointPathResolver,
ObjectProvider<ErrorController> errorController) { ObjectProvider<ErrorController> errorController) {
return new SpringBootSecurity(endpointPathResolver, errorController.getIfAvailable()); return new SpringBootSecurity(endpointPathResolver,
errorController.getIfAvailable());
} }
@Bean @Bean
......
...@@ -73,8 +73,7 @@ public class SecurityFilterAutoConfiguration { ...@@ -73,8 +73,7 @@ public class SecurityFilterAutoConfiguration {
return null; return null;
} }
return securityProperties.getFilterDispatcherTypes().stream() return securityProperties.getFilterDispatcherTypes().stream()
.map((type) -> DispatcherType.valueOf(type.name())) .map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors
.collect(Collectors
.collectingAndThen(Collectors.toSet(), EnumSet::copyOf)); .collectingAndThen(Collectors.toSet(), EnumSet::copyOf));
} }
......
...@@ -66,8 +66,8 @@ public class SecurityProperties implements SecurityPrerequisite { ...@@ -66,8 +66,8 @@ public class SecurityProperties implements SecurityPrerequisite {
/** /**
* Security filter chain dispatcher types. * Security filter chain dispatcher types.
*/ */
private Set<DispatcherType> filterDispatcherTypes = new HashSet<>(Arrays.asList( private Set<DispatcherType> filterDispatcherTypes = new HashSet<>(Arrays
DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST)); .asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
public Basic getBasic() { public Basic getBasic() {
return this.basic; return this.basic;
......
...@@ -31,7 +31,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher; ...@@ -31,7 +31,6 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Provides request matchers that can be used to configure security for static resources * Provides request matchers that can be used to configure security for static resources
* and the error controller path in a custom {@link WebSecurityConfigurerAdapter}. * and the error controller path in a custom {@link WebSecurityConfigurerAdapter}.
...@@ -68,8 +67,8 @@ public final class SpringBootSecurity { ...@@ -68,8 +67,8 @@ public final class SpringBootSecurity {
Assert.notEmpty(ids, "At least one endpoint id must be specified."); Assert.notEmpty(ids, "At least one endpoint id must be specified.");
List<String> pathList = Arrays.asList(ids); List<String> pathList = Arrays.asList(ids);
if (pathList.contains(ALL_ENDPOINTS)) { if (pathList.contains(ALL_ENDPOINTS)) {
return new AntPathRequestMatcher(this.endpointPathResolver.resolvePath( return new AntPathRequestMatcher(
ALL_ENDPOINTS), null); this.endpointPathResolver.resolvePath(ALL_ENDPOINTS), null);
} }
return getEndpointsRequestMatcher(pathList); return getEndpointsRequestMatcher(pathList);
} }
...@@ -140,4 +139,3 @@ public final class SpringBootSecurity { ...@@ -140,4 +139,3 @@ public final class SpringBootSecurity {
} }
} }
...@@ -29,10 +29,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur ...@@ -29,10 +29,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
/** /**
* The default configuration for web security. It relies on Spring Security's * The default configuration for web security. It relies on Spring Security's
* content-negotiation strategy to determine what sort of authentication to use. * content-negotiation strategy to determine what sort of authentication to use. If the
* If the user specifies their own {@link WebSecurityConfigurerAdapter}, this will * user specifies their own {@link WebSecurityConfigurerAdapter}, this will back-off
* back-off completely and the users should specify all the bits that they want to * completely and the users should specify all the bits that they want to configure as
* configure as part of the custom security configuration. * part of the custom security configuration.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
...@@ -52,6 +52,7 @@ public class SpringBootWebSecurityConfiguration { ...@@ -52,6 +52,7 @@ public class SpringBootWebSecurityConfiguration {
super.configure(http); super.configure(http);
http.csrf().disable(); http.csrf().disable();
} }
} }
} }
...@@ -39,5 +39,5 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur ...@@ -39,5 +39,5 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityEnablerConfiguration { public class WebSecurityEnablerConfiguration {
}
}
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -86,7 +86,7 @@ public class OAuth2RestOperationsConfiguration { ...@@ -86,7 +86,7 @@ public class OAuth2RestOperationsConfiguration {
@Configuration @Configuration
@ConditionalOnBean(OAuth2ClientConfiguration.class) @ConditionalOnBean(OAuth2ClientConfiguration.class)
@Conditional({OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class}) @Conditional({ OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class })
@Import(OAuth2ProtectedResourceDetailsConfiguration.class) @Import(OAuth2ProtectedResourceDetailsConfiguration.class)
protected static class SessionScopedConfiguration { protected static class SessionScopedConfiguration {
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -55,8 +55,7 @@ class SessionRepositoryFilterConfiguration { ...@@ -55,8 +55,7 @@ class SessionRepositoryFilterConfiguration {
return null; return null;
} }
return servletProperties.getFilterDispatcherTypes().stream() return servletProperties.getFilterDispatcherTypes().stream()
.map((type) -> DispatcherType.valueOf(type.name())) .map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors
.collect(Collectors
.collectingAndThen(Collectors.toSet(), EnumSet::copyOf)); .collectingAndThen(Collectors.toSet(), EnumSet::copyOf));
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -95,8 +95,8 @@ public class FlywayAutoConfigurationTests { ...@@ -95,8 +95,8 @@ public class FlywayAutoConfigurationTests {
@Test @Test
public void createDataSource() throws Exception { public void createDataSource() throws Exception {
TestPropertyValues.of("spring.flyway.url:jdbc:hsqldb:mem:flywaytest", "spring.flyway.user:sa") TestPropertyValues.of("spring.flyway.url:jdbc:hsqldb:mem:flywaytest",
.applyTo(this.context); "spring.flyway.user:sa").applyTo(this.context);
registerAndRefresh(EmbeddedDataSourceConfiguration.class, registerAndRefresh(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class, FlywayAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
...@@ -162,7 +162,8 @@ public class FlywayAutoConfigurationTests { ...@@ -162,7 +162,8 @@ public class FlywayAutoConfigurationTests {
@Test @Test
public void changeLogDoesNotExist() throws Exception { public void changeLogDoesNotExist() throws Exception {
TestPropertyValues.of("spring.flyway.locations:file:no-such-dir").applyTo(this.context); TestPropertyValues.of("spring.flyway.locations:file:no-such-dir")
.applyTo(this.context);
this.thrown.expect(BeanCreationException.class); this.thrown.expect(BeanCreationException.class);
registerAndRefresh(EmbeddedDataSourceConfiguration.class, registerAndRefresh(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class, FlywayAutoConfiguration.class,
......
...@@ -318,7 +318,8 @@ public class DataSourceAutoConfigurationTests { ...@@ -318,7 +318,8 @@ public class DataSourceAutoConfigurationTests {
@Override @Override
protected Class<?> loadClass(String name, boolean resolve) protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException { throws ClassNotFoundException {
for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) { for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection
.values()) {
if (name.equals(candidate.getDriverClassName())) { if (name.equals(candidate.getDriverClassName())) {
throw new ClassNotFoundException(); throw new ClassNotFoundException();
} }
...@@ -328,5 +329,4 @@ public class DataSourceAutoConfigurationTests { ...@@ -328,5 +329,4 @@ public class DataSourceAutoConfigurationTests {
} }
} }
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -160,7 +160,8 @@ public class LiquibaseAutoConfigurationTests { ...@@ -160,7 +160,8 @@ public class LiquibaseAutoConfigurationTests {
@Test @Test
public void testOverrideDefaultSchema() throws Exception { public void testOverrideDefaultSchema() throws Exception {
TestPropertyValues.of("spring.liquibase.default-schema:public").applyTo(this.context); TestPropertyValues.of("spring.liquibase.default-schema:public")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class, LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
...@@ -182,9 +183,8 @@ public class LiquibaseAutoConfigurationTests { ...@@ -182,9 +183,8 @@ public class LiquibaseAutoConfigurationTests {
@Test @Test
public void testOverrideDataSource() throws Exception { public void testOverrideDataSource() throws Exception {
TestPropertyValues TestPropertyValues.of("spring.liquibase.url:jdbc:hsqldb:mem:liquibase",
.of("spring.liquibase.url:jdbc:hsqldb:mem:liquibase", "spring.liquibase.user:sa") "spring.liquibase.user:sa").applyTo(this.context);
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class, LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
...@@ -198,7 +198,8 @@ public class LiquibaseAutoConfigurationTests { ...@@ -198,7 +198,8 @@ public class LiquibaseAutoConfigurationTests {
@Test(expected = BeanCreationException.class) @Test(expected = BeanCreationException.class)
public void testChangeLogDoesNotExist() throws Exception { public void testChangeLogDoesNotExist() throws Exception {
TestPropertyValues.of("spring.liquibase.change-log:classpath:/no-such-changelog.yaml") TestPropertyValues
.of("spring.liquibase.change-log:classpath:/no-such-changelog.yaml")
.applyTo(this.context); .applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class, LiquibaseAutoConfiguration.class,
...@@ -220,7 +221,8 @@ public class LiquibaseAutoConfigurationTests { ...@@ -220,7 +221,8 @@ public class LiquibaseAutoConfigurationTests {
@Test @Test
public void testOverrideLabels() throws Exception { public void testOverrideLabels() throws Exception {
TestPropertyValues.of("spring.liquibase.labels:test, production").applyTo(this.context); TestPropertyValues.of("spring.liquibase.labels:test, production")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class, LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
...@@ -232,7 +234,8 @@ public class LiquibaseAutoConfigurationTests { ...@@ -232,7 +234,8 @@ public class LiquibaseAutoConfigurationTests {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testOverrideParameters() throws Exception { public void testOverrideParameters() throws Exception {
TestPropertyValues.of("spring.liquibase.parameters.foo:bar").applyTo(this.context); TestPropertyValues.of("spring.liquibase.parameters.foo:bar")
.applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class, LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class); PropertyPlaceholderAutoConfiguration.class);
......
...@@ -298,8 +298,8 @@ public class SecurityAutoConfigurationTests { ...@@ -298,8 +298,8 @@ public class SecurityAutoConfigurationTests {
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(SecurityAutoConfiguration.class); this.context.register(SecurityAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
String password = this.outputCapture.toString().split("Using default security password: ")[1] String password = this.outputCapture.toString()
.split("\n")[0].trim(); .split("Using default security password: ")[1].split("\n")[0].trim();
AuthenticationManager manager = this.context.getBean(AuthenticationManager.class); AuthenticationManager manager = this.context.getBean(AuthenticationManager.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"user", password); "user", password);
...@@ -307,16 +307,17 @@ public class SecurityAutoConfigurationTests { ...@@ -307,16 +307,17 @@ public class SecurityAutoConfigurationTests {
} }
@Test @Test
public void testCustomAuthenticationDoesNotCreateDefaultUser() public void testCustomAuthenticationDoesNotCreateDefaultUser() throws Exception {
throws Exception {
this.context = new AnnotationConfigWebApplicationContext(); this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext()); this.context.setServletContext(new MockServletContext());
this.context.register(AuthenticationManagerCustomizer.class, this.context.register(AuthenticationManagerCustomizer.class,
SecurityAutoConfiguration.class); SecurityAutoConfiguration.class);
this.context.refresh(); this.context.refresh();
AuthenticationManager manager = this.context.getBean(AuthenticationManager.class); AuthenticationManager manager = this.context.getBean(AuthenticationManager.class);
assertThat(this.outputCapture.toString()).doesNotContain("Using default security password: "); assertThat(this.outputCapture.toString())
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("foo", "bar"); .doesNotContain("Using default security password: ");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
"foo", "bar");
assertThat(manager.authenticate(token)).isNotNull(); assertThat(manager.authenticate(token)).isNotNull();
} }
......
...@@ -61,13 +61,12 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests { ...@@ -61,13 +61,12 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests {
@Test @Test
public void testSecurityFilterDoesNotCauseEarlyInitialization() throws Exception { public void testSecurityFilterDoesNotCauseEarlyInitialization() throws Exception {
try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) { try (AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext()) {
TestPropertyValues.of("server.port:0") TestPropertyValues.of("server.port:0").applyTo(context);
.applyTo(context);
context.register(Config.class); context.register(Config.class);
context.refresh(); context.refresh();
int port = context.getWebServer().getPort(); int port = context.getWebServer().getPort();
String password = this.outputCapture.toString().split("Using default security password: ")[1] String password = this.outputCapture.toString()
.split("\n")[0].trim(); .split("Using default security password: ")[1].split("\n")[0].trim();
new TestRestTemplate("user", password) new TestRestTemplate("user", password)
.getForEntity("http://localhost:" + port, Object.class); .getForEntity("http://localhost:" + port, Object.class);
// If early initialization occurred a ConverterNotFoundException is thrown // If early initialization occurred a ConverterNotFoundException is thrown
...@@ -80,8 +79,8 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests { ...@@ -80,8 +79,8 @@ public class SecurityFilterAutoConfigurationEarlyInitializationTests {
ConverterBean.class }) ConverterBean.class })
@ImportAutoConfiguration({ WebMvcAutoConfiguration.class, @ImportAutoConfiguration({ WebMvcAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, DispatcherServletAutoConfiguration.class, SecurityAutoConfiguration.class,
SecurityAutoConfiguration.class, SecurityFilterAutoConfiguration.class, SecurityFilterAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class }) PropertyPlaceholderAutoConfiguration.class })
static class Config { static class Config {
......
...@@ -46,15 +46,16 @@ public class SpringBootSecurityTests { ...@@ -46,15 +46,16 @@ public class SpringBootSecurityTests {
private MockHttpServletRequest request = new MockHttpServletRequest(); private MockHttpServletRequest request = new MockHttpServletRequest();
private static String[] STATIC_RESOURCES = new String[]{"/css/**", "/js/**", private static String[] STATIC_RESOURCES = new String[] { "/css/**", "/js/**",
"/images/**", "/webjars/**", "/**/favicon.ico"}; "/images/**", "/webjars/**", "/**/favicon.ico" };
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
this.bootSecurity = new SpringBootSecurity(this.endpointPathResolver, this.errorController); this.bootSecurity = new SpringBootSecurity(this.endpointPathResolver,
this.errorController);
} }
@Test @Test
...@@ -65,7 +66,8 @@ public class SpringBootSecurityTests { ...@@ -65,7 +66,8 @@ public class SpringBootSecurityTests {
} }
@Test @Test
public void endpointIdsShouldReturnRequestMatcherWithEndpointPaths() throws Exception { public void endpointIdsShouldReturnRequestMatcherWithEndpointPaths()
throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.endpointIds("id-1", "id-2"); RequestMatcher requestMatcher = this.bootSecurity.endpointIds("id-1", "id-2");
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class); assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
this.request.setServletPath("/test/id-1"); this.request.setServletPath("/test/id-1");
...@@ -77,8 +79,10 @@ public class SpringBootSecurityTests { ...@@ -77,8 +79,10 @@ public class SpringBootSecurityTests {
} }
@Test @Test
public void endpointIdsShouldReturnRequestMatcherWithAllEndpointPaths() throws Exception { public void endpointIdsShouldReturnRequestMatcherWithAllEndpointPaths()
RequestMatcher requestMatcher = this.bootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS); throws Exception {
RequestMatcher requestMatcher = this.bootSecurity
.endpointIds(SpringBootSecurity.ALL_ENDPOINTS);
this.request.setServletPath("/test/id-1"); this.request.setServletPath("/test/id-1");
assertThat(requestMatcher.matches(this.request)).isTrue(); assertThat(requestMatcher.matches(this.request)).isTrue();
this.request.setServletPath("/test/id-2"); this.request.setServletPath("/test/id-2");
...@@ -112,7 +116,8 @@ public class SpringBootSecurityTests { ...@@ -112,7 +116,8 @@ public class SpringBootSecurityTests {
} }
@Test @Test
public void staticResourcesShouldReturnRequestMatcherWithStaticResources() throws Exception { public void staticResourcesShouldReturnRequestMatcherWithStaticResources()
throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.staticResources(); RequestMatcher requestMatcher = this.bootSecurity.staticResources();
assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class); assertThat(requestMatcher).isInstanceOf(OrRequestMatcher.class);
for (String resource : STATIC_RESOURCES) { for (String resource : STATIC_RESOURCES) {
...@@ -122,7 +127,8 @@ public class SpringBootSecurityTests { ...@@ -122,7 +127,8 @@ public class SpringBootSecurityTests {
} }
@Test @Test
public void errorShouldReturnRequestMatcherWithErrorControllerPath() throws Exception { public void errorShouldReturnRequestMatcherWithErrorControllerPath()
throws Exception {
RequestMatcher requestMatcher = this.bootSecurity.error(); RequestMatcher requestMatcher = this.bootSecurity.error();
assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class); assertThat(requestMatcher).isInstanceOf(AntPathRequestMatcher.class);
this.request.setServletPath("/test/error"); this.request.setServletPath("/test/error");
...@@ -152,6 +158,7 @@ public class SpringBootSecurityTests { ...@@ -152,6 +158,7 @@ public class SpringBootSecurityTests {
public String getErrorPath() { public String getErrorPath() {
return "/test/error"; return "/test/error";
} }
} }
@Endpoint(id = "id-1") @Endpoint(id = "id-1")
...@@ -167,4 +174,5 @@ public class SpringBootSecurityTests { ...@@ -167,4 +174,5 @@ public class SpringBootSecurityTests {
static class FakeEndpoint { static class FakeEndpoint {
} }
} }
...@@ -22,6 +22,7 @@ import org.junit.rules.ExpectedException; ...@@ -22,6 +22,7 @@ import org.junit.rules.ExpectedException;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.web.servlet.MockServletWebServerFactory; import org.springframework.boot.autoconfigure.web.servlet.MockServletWebServerFactory;
import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.builder.SpringApplicationBuilder;
...@@ -77,8 +78,7 @@ public class OAuth2RestOperationsConfigurationTests { ...@@ -77,8 +78,7 @@ public class OAuth2RestOperationsConfigurationTests {
TestPropertyValues.of("security.oauth2.client.client-id=acme") TestPropertyValues.of("security.oauth2.client.client-id=acme")
.applyTo(this.environment); .applyTo(this.environment);
initializeContext(ConfigForRequestScopedConfiguration.class, false); initializeContext(ConfigForRequestScopedConfiguration.class, false);
assertThat(this.context.containsBean("oauth2ClientContext")) assertThat(this.context.containsBean("oauth2ClientContext")).isTrue();
.isTrue();
} }
@Test @Test
...@@ -93,8 +93,7 @@ public class OAuth2RestOperationsConfigurationTests { ...@@ -93,8 +93,7 @@ public class OAuth2RestOperationsConfigurationTests {
TestPropertyValues.of("security.oauth2.client.client-id=acme") TestPropertyValues.of("security.oauth2.client.client-id=acme")
.applyTo(this.environment); .applyTo(this.environment);
initializeContext(ConfigForSessionScopedConfiguration.class, false); initializeContext(ConfigForSessionScopedConfiguration.class, false);
assertThat(this.context.containsBean("oauth2ClientContext")) assertThat(this.context.containsBean("oauth2ClientContext")).isTrue();
.isTrue();
} }
@Test @Test
...@@ -104,10 +103,11 @@ public class OAuth2RestOperationsConfigurationTests { ...@@ -104,10 +103,11 @@ public class OAuth2RestOperationsConfigurationTests {
this.context.getBean(DefaultOAuth2ClientContext.class); this.context.getBean(DefaultOAuth2ClientContext.class);
} }
private void initializeContext(Class<?> configuration, boolean isClientCredentials) { private void initializeContext(Class<?> configuration, boolean clientCredentials) {
this.context = new SpringApplicationBuilder(configuration) this.context = new SpringApplicationBuilder(configuration)
.environment(this.environment) .environment(this.environment).web(clientCredentials
.web(!isClientCredentials).run(); ? WebApplicationType.NONE : WebApplicationType.SERVLET)
.run();
} }
@Configuration @Configuration
...@@ -123,7 +123,8 @@ public class OAuth2RestOperationsConfigurationTests { ...@@ -123,7 +123,8 @@ public class OAuth2RestOperationsConfigurationTests {
@Configuration @Configuration
@Import({ OAuth2ClientConfiguration.class, OAuth2RestOperationsConfiguration.class }) @Import({ OAuth2ClientConfiguration.class, OAuth2RestOperationsConfiguration.class })
protected static class ConfigForSessionScopedConfiguration extends WebApplicationConfiguration { protected static class ConfigForSessionScopedConfiguration
extends WebApplicationConfiguration {
@Bean @Bean
public SecurityProperties securityProperties() { public SecurityProperties securityProperties() {
...@@ -133,7 +134,8 @@ public class OAuth2RestOperationsConfigurationTests { ...@@ -133,7 +134,8 @@ public class OAuth2RestOperationsConfigurationTests {
} }
@Configuration @Configuration
protected static class ConfigForRequestScopedConfiguration extends WebApplicationConfiguration { protected static class ConfigForRequestScopedConfiguration
extends WebApplicationConfiguration {
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -29,7 +29,8 @@ public class HelloWebSecurityApplication { ...@@ -29,7 +29,8 @@ public class HelloWebSecurityApplication {
@Bean @Bean
public UserDetailsService userDetailsService() throws Exception { public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build()); manager.createUser(
User.withUsername("user").password("password").roles("USER").build());
return manager; return manager;
} }
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<!-- Your own application should inherit from spring-boot-starter-parent --> <!-- Your own application should inherit from spring-boot-starter-parent -->
......
...@@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.security.SpringBootSecurity; ...@@ -4,7 +4,6 @@ import org.springframework.boot.autoconfigure.security.SpringBootSecurity;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration @Configuration
...@@ -18,13 +17,14 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { ...@@ -18,13 +17,14 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() auth.inMemoryAuthentication().withUser("user").password("password")
.withUser("user").password("password").authorities("ROLE_USER").and() .authorities("ROLE_USER").and().withUser("admin").password("admin")
.withUser("admin").password("admin").authorities("ROLE_ACTUATOR", "ROLE_USER"); .authorities("ROLE_ACTUATOR", "ROLE_USER");
} }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests() http.authorizeRequests()
.requestMatchers(this.bootSecurity.endpointIds("status", "info")).permitAll() .requestMatchers(this.bootSecurity.endpointIds("status", "info")).permitAll()
.requestMatchers(this.bootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS)).hasRole("ACTUATOR") .requestMatchers(this.bootSecurity.endpointIds(SpringBootSecurity.ALL_ENDPOINTS)).hasRole("ACTUATOR")
...@@ -35,6 +35,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { ...@@ -35,6 +35,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.cors() .cors()
.and() .and()
.httpBasic(); .httpBasic();
// @formatter:on
} }
} }
...@@ -12,14 +12,10 @@ import org.springframework.boot.test.context.SpringBootTest; ...@@ -12,14 +12,10 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler; import org.springframework.boot.test.web.client.LocalHostUriTemplateHandler;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity; import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
...@@ -41,7 +37,7 @@ public class CorsSampleActuatorApplicationTests { ...@@ -41,7 +37,7 @@ public class CorsSampleActuatorApplicationTests {
private TestRestTemplate testRestTemplate; private TestRestTemplate testRestTemplate;
@Autowired @Autowired
ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
......
...@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {
"management.port=0", "management.context-path=/admin"}) "management.port=0", "management.context-path=/admin" })
@DirtiesContext @DirtiesContext
public class InsecureManagementPortAndPathSampleActuatorApplicationTests { public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
...@@ -51,7 +51,6 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests { ...@@ -51,7 +51,6 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
@Test @Test
public void testHome() throws Exception { public void testHome() throws Exception {
@SuppressWarnings("rawtypes")
ResponseEntity<String> entity = new TestRestTemplate("user", "password") ResponseEntity<String> entity = new TestRestTemplate("user", "password")
.getForEntity("http://localhost:" + this.port, String.class); .getForEntity("http://localhost:" + this.port, String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
...@@ -77,9 +76,10 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests { ...@@ -77,9 +76,10 @@ public class InsecureManagementPortAndPathSampleActuatorApplicationTests {
@Test @Test
public void testMissing() throws Exception { public void testMissing() throws Exception {
ResponseEntity<String> entity = new TestRestTemplate("admin", "admin").getForEntity( ResponseEntity<String> entity = new TestRestTemplate("admin", "admin")
"http://localhost:" + this.managementPort + "/admin/missing", .getForEntity(
String.class); "http://localhost:" + this.managementPort + "/admin/missing",
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
assertThat(entity.getBody()).contains("\"status\":404"); assertThat(entity.getBody()).contains("\"status\":404");
} }
......
...@@ -44,22 +44,22 @@ public class SampleActuatorCustomSecurityApplicationTests { ...@@ -44,22 +44,22 @@ public class SampleActuatorCustomSecurityApplicationTests {
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> body = entity.getBody(); Map<String, Object> body = entity.getBody();
assertThat((String)body.get("message")).contains("Expected exception in controller"); assertThat((String) body.get("message"))
.contains("Expected exception in controller");
} }
@Test @Test
public void testInsecureStaticResources() throws Exception { public void testInsecureStaticResources() throws Exception {
@SuppressWarnings("rawtypes") ResponseEntity<String> entity = this.restTemplate
ResponseEntity<String> entity = this.restTemplate.getForEntity("/css/bootstrap.min.css", String.class); .getForEntity("/css/bootstrap.min.css", String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("body"); assertThat(entity.getBody()).contains("body");
} }
@Test @Test
public void insecureActuator() throws Exception { public void insecureActuator() throws Exception {
@SuppressWarnings("rawtypes") ResponseEntity<String> entity = this.restTemplate
ResponseEntity<String> entity = this.restTemplate.getForEntity("/application/status", .getForEntity("/application/status", String.class);
String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("\"status\":\"UP\""); assertThat(entity.getBody()).contains("\"status\":\"UP\"");
} }
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -29,7 +29,8 @@ public class SampleActuatorLog4J2Application { ...@@ -29,7 +29,8 @@ public class SampleActuatorLog4J2Application {
@Bean @Bean
public UserDetailsService userDetailsService() throws Exception { public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build()); manager.createUser(
User.withUsername("user").password("password").roles("USER").build());
return manager; return manager;
} }
......
...@@ -65,17 +65,16 @@ public class SampleActuatorLog4J2ApplicationTests { ...@@ -65,17 +65,16 @@ public class SampleActuatorLog4J2ApplicationTests {
@Test @Test
public void validateLoggersEndpoint() throws Exception { public void validateLoggersEndpoint() throws Exception {
this.mvc.perform(get("/application/loggers/org.apache.coyote.http11.Http11NioProtocol") this.mvc.perform(
.header("Authorization", "Basic " + getBasicAuth())) get("/application/loggers/org.apache.coyote.http11.Http11NioProtocol")
.header("Authorization", "Basic " + getBasicAuth()))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().string(equalTo("{\"configuredLevel\":\"WARN\"," .andExpect(content().string(equalTo("{\"configuredLevel\":\"WARN\","
+ "\"effectiveLevel\":\"WARN\"}"))); + "\"effectiveLevel\":\"WARN\"}")));
} }
private String getBasicAuth() { private String getBasicAuth() {
return new String(Base64.getEncoder() return new String(Base64.getEncoder().encode(("user:password").getBytes()));
.encode(("user:password").getBytes()));
} }
} }
...@@ -36,7 +36,8 @@ public class SampleActuatorUiApplication { ...@@ -36,7 +36,8 @@ public class SampleActuatorUiApplication {
@Bean @Bean
public UserDetailsService userDetailsService() throws Exception { public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build()); manager.createUser(
User.withUsername("user").password("password").roles("USER").build());
return manager; return manager;
} }
......
...@@ -54,9 +54,9 @@ public class SampleActuatorUiApplicationTests { ...@@ -54,9 +54,9 @@ public class SampleActuatorUiApplicationTests {
public void testHome() throws Exception { public void testHome() throws Exception {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
ResponseEntity<String> entity = this.restTemplate.withBasicAuth("user", getPassword()) ResponseEntity<String> entity = this.restTemplate
.exchange("/", HttpMethod.GET, .withBasicAuth("user", getPassword()).exchange("/", HttpMethod.GET,
new HttpEntity<Void>(headers), String.class); new HttpEntity<Void>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("<title>Hello"); assertThat(entity.getBody()).contains("<title>Hello");
} }
...@@ -72,8 +72,8 @@ public class SampleActuatorUiApplicationTests { ...@@ -72,8 +72,8 @@ public class SampleActuatorUiApplicationTests {
@Test @Test
public void testMetrics() throws Exception { public void testMetrics() throws Exception {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = this.restTemplate.getForEntity("/application/metrics", ResponseEntity<Map> entity = this.restTemplate
Map.class); .getForEntity("/application/metrics", Map.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
} }
...@@ -81,9 +81,9 @@ public class SampleActuatorUiApplicationTests { ...@@ -81,9 +81,9 @@ public class SampleActuatorUiApplicationTests {
public void testError() throws Exception { public void testError() throws Exception {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.TEXT_HTML)); headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
ResponseEntity<String> entity = this.restTemplate.withBasicAuth("user", getPassword()) ResponseEntity<String> entity = this.restTemplate
.exchange("/error", .withBasicAuth("user", getPassword()).exchange("/error", HttpMethod.GET,
HttpMethod.GET, new HttpEntity<Void>(headers), String.class); new HttpEntity<Void>(headers), String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
assertThat(entity.getBody()).contains("<html>").contains("<body>") assertThat(entity.getBody()).contains("<html>").contains("<body>")
.contains("Please contact the operator with the above information"); .contains("Please contact the operator with the above information");
......
...@@ -22,7 +22,6 @@ import org.springframework.boot.actuate.health.HealthIndicator; ...@@ -22,7 +22,6 @@ import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.provisioning.InMemoryUserDetailsManager;
...@@ -38,17 +37,20 @@ public class SampleActuatorApplication { ...@@ -38,17 +37,20 @@ public class SampleActuatorApplication {
@Bean @Bean
public UserDetailsService userDetailsService() throws Exception { public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("user").password("password").roles("USER").build()); manager.createUser(
User.withUsername("user").password("password").roles("USER").build());
return manager; return manager;
} }
@Bean @Bean
public HealthIndicator helloHealthIndicator() { public HealthIndicator helloHealthIndicator() {
return new HealthIndicator() { return new HealthIndicator() {
@Override @Override
public Health health() { public Health health() {
return Health.up().withDetail("hello", "world").build(); return Health.up().withDetail("hello", "world").build();
} }
}; };
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment