Skip to content

Commit 1cd1054

Browse files
committed
Merge branch '1.5.x'
2 parents 263d444 + 1be5812 commit 1cd1054

File tree

36 files changed

+626
-236
lines changed

36 files changed

+626
-236
lines changed

spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/EndpointDocumentation.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
@ContextConfiguration(classes = SpringBootHypermediaApplication.class, loader = SpringBootContextLoader.class)
6666
@WebAppConfiguration
6767
@TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true",
68-
"endpoints.health.sensitive=true", "endpoints.actuator.enabled=false" })
68+
"endpoints.health.sensitive=true", "endpoints.actuator.enabled=false",
69+
"management.security.enabled=false" })
6970
@DirtiesContext
7071
@AutoConfigureRestDocs(EndpointDocumentation.RESTDOCS_OUTPUT_DIR)
7172
@AutoConfigureMockMvc(print = MockMvcPrint.NONE)

spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/HealthEndpointDocumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
@ContextConfiguration(classes = SpringBootHypermediaApplication.class, loader = SpringBootContextLoader.class)
4040
@WebAppConfiguration
4141
@TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true",
42-
"endpoints.health.sensitive=false" })
42+
"endpoints.health.sensitive=false", "management.security.enabled=false" })
4343
@DirtiesContext
4444
@AutoConfigureMockMvc
4545
@AutoConfigureRestDocs("target/generated-snippets")

spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/HypermediaEndpointDocumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
@ContextConfiguration(classes = SpringBootHypermediaApplication.class, loader = SpringBootContextLoader.class)
4141
@WebAppConfiguration
4242
@TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true",
43-
"endpoints.hypermedia.enabled=true" })
43+
"endpoints.hypermedia.enabled=true", "management.security.enabled=false" })
4444
@DirtiesContext
4545
@AutoConfigureMockMvc
4646
@AutoConfigureRestDocs("target/generated-snippets")

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint;
3838
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
3939
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
40+
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpointSecurityInterceptor;
4041
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
4142
import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
4243
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
@@ -99,6 +100,10 @@ public EndpointHandlerMapping endpointHandlerMapping() {
99100
EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,
100101
corsConfiguration);
101102
mapping.setPrefix(this.managementServerProperties.getContextPath());
103+
MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(
104+
this.managementServerProperties.getSecurity().isEnabled(),
105+
this.managementServerProperties.getSecurity().getRoles());
106+
mapping.setSecurityInterceptor(securityInterceptor);
102107
for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) {
103108
customizer.customize(mapping);
104109
}

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementServerProperties.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public static class Security {
168168
/**
169169
* Comma-separated list of roles that can access the management endpoint.
170170
*/
171-
private List<String> roles = Arrays.asList("ADMIN");
171+
private List<String> roles = Arrays.asList("ACTUATOR");
172172

173173
/**
174174
* Session creating policy for security use (always, never, if_required,

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfiguration.java

Lines changed: 30 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import javax.servlet.http.HttpServletRequest;
2727

2828
import org.springframework.beans.factory.ObjectProvider;
29-
import org.springframework.beans.factory.annotation.Autowired;
3029
import org.springframework.boot.actuate.endpoint.Endpoint;
3130
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
3231
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
@@ -42,11 +41,11 @@
4241
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
4342
import org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration;
4443
import org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration;
44+
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
4545
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
4646
import org.springframework.boot.autoconfigure.security.SecurityPrerequisite;
4747
import org.springframework.boot.autoconfigure.security.SecurityProperties;
4848
import org.springframework.boot.autoconfigure.security.SpringBootWebSecurityConfiguration;
49-
import org.springframework.boot.autoconfigure.web.ErrorController;
5049
import org.springframework.boot.autoconfigure.web.ServerProperties;
5150
import org.springframework.boot.context.properties.EnableConfigurationProperties;
5251
import org.springframework.context.ApplicationContext;
@@ -56,9 +55,7 @@
5655
import org.springframework.context.annotation.Configuration;
5756
import org.springframework.core.annotation.Order;
5857
import org.springframework.core.type.AnnotatedTypeMetadata;
59-
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
6058
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
61-
import org.springframework.security.config.annotation.web.builders.WebSecurity;
6259
import org.springframework.security.config.annotation.web.builders.WebSecurity.IgnoredRequestConfigurer;
6360
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6461
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
@@ -72,7 +69,6 @@
7269
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
7370
import org.springframework.security.web.util.matcher.OrRequestMatcher;
7471
import org.springframework.security.web.util.matcher.RequestMatcher;
75-
import org.springframework.util.ObjectUtils;
7672
import org.springframework.util.StringUtils;
7773

7874
/**
@@ -102,9 +98,34 @@ public class ManagementWebSecurityAutoConfiguration {
10298
AnyRequestMatcher.INSTANCE);
10399

104100
@Bean
105-
@ConditionalOnMissingBean({ IgnoredPathsWebSecurityConfigurerAdapter.class })
106-
public IgnoredPathsWebSecurityConfigurerAdapter ignoredPathsWebSecurityConfigurerAdapter() {
107-
return new IgnoredPathsWebSecurityConfigurerAdapter();
101+
public IgnoredRequestCustomizer managementIgnoredRequestCustomizer(
102+
ManagementServerProperties management,
103+
ObjectProvider<ManagementContextResolver> contextResolverProvider) {
104+
return new ManagementIgnoredRequestCustomizer(management,
105+
contextResolverProvider.getIfAvailable());
106+
}
107+
108+
private class ManagementIgnoredRequestCustomizer implements IgnoredRequestCustomizer {
109+
110+
private final ManagementServerProperties management;
111+
112+
private final ManagementContextResolver contextResolver;
113+
114+
ManagementIgnoredRequestCustomizer(ManagementServerProperties management,
115+
ManagementContextResolver contextResolver) {
116+
this.management = management;
117+
this.contextResolver = contextResolver;
118+
}
119+
120+
@Override
121+
public void customize(IgnoredRequestConfigurer configurer) {
122+
if (!this.management.getSecurity().isEnabled()) {
123+
RequestMatcher requestMatcher = LazyEndpointPathRequestMatcher
124+
.getRequestMatcher(this.contextResolver);
125+
configurer.requestMatchers(requestMatcher);
126+
}
127+
128+
}
108129
}
109130

110131
@Configuration
@@ -132,80 +153,6 @@ public void init() {
132153

133154
}
134155

135-
// Get the ignored paths in early
136-
@Order(SecurityProperties.IGNORED_ORDER + 1)
137-
private static class IgnoredPathsWebSecurityConfigurerAdapter
138-
implements WebSecurityConfigurer<WebSecurity> {
139-
140-
@Autowired(required = false)
141-
private ErrorController errorController;
142-
143-
@Autowired
144-
private SecurityProperties security;
145-
146-
@Autowired
147-
private ManagementServerProperties management;
148-
149-
@Autowired(required = false)
150-
private ManagementContextResolver contextResolver;
151-
152-
@Autowired(required = false)
153-
private ServerProperties server;
154-
155-
@Override
156-
public void configure(WebSecurity builder) throws Exception {
157-
}
158-
159-
@Override
160-
public void init(WebSecurity builder) throws Exception {
161-
if (this.server == null) {
162-
return;
163-
}
164-
IgnoredRequestConfigurer ignoring = builder.ignoring();
165-
// The ignores are not cumulative, so to prevent overwriting the defaults
166-
// we add them back.
167-
Set<String> ignored = new LinkedHashSet<String>(
168-
SpringBootWebSecurityConfiguration.getIgnored(this.security));
169-
if (ignored.contains("none")) {
170-
ignored.remove("none");
171-
}
172-
if (this.errorController != null) {
173-
ignored.add(normalizePath(this.errorController.getErrorPath()));
174-
}
175-
RequestMatcher requestMatcher = getRequestMatcher();
176-
String[] paths = this.server.getPathsArray(ignored);
177-
if (!ObjectUtils.isEmpty(paths)) {
178-
List<RequestMatcher> matchers = new ArrayList<RequestMatcher>();
179-
for (String pattern : paths) {
180-
matchers.add(new AntPathRequestMatcher(pattern, null));
181-
}
182-
if (requestMatcher != null) {
183-
matchers.add(requestMatcher);
184-
}
185-
requestMatcher = new OrRequestMatcher(matchers);
186-
}
187-
if (requestMatcher != null) {
188-
ignoring.requestMatchers(requestMatcher);
189-
}
190-
}
191-
192-
private RequestMatcher getRequestMatcher() {
193-
if (this.management.getSecurity().isEnabled()) {
194-
return null;
195-
}
196-
return LazyEndpointPathRequestMatcher.getRequestMatcher(this.contextResolver);
197-
}
198-
199-
private String normalizePath(String errorPath) {
200-
String result = StringUtils.cleanPath(errorPath);
201-
if (!result.startsWith("/")) {
202-
result = "/" + result;
203-
}
204-
return result;
205-
}
206-
207-
}
208-
209156
@Configuration
210157
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
211158
@Conditional(WebSecurityEnablerCondition.class)
@@ -310,9 +257,7 @@ private void configurePermittedRequests(
310257
// Permit access to the non-sensitive endpoints
311258
requests.requestMatchers(new LazyEndpointPathRequestMatcher(
312259
this.contextResolver, EndpointPaths.NON_SENSITIVE)).permitAll();
313-
// Restrict the rest to the configured roles
314-
List<String> roles = this.management.getSecurity().getRoles();
315-
requests.anyRequest().hasAnyRole(roles.toArray(new String[roles.size()]));
260+
requests.anyRequest().authenticated();
316261
}
317262

318263
}

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryActuatorAutoConfiguration.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2929
import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform;
3030
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
31+
import org.springframework.boot.autoconfigure.security.IgnoredRequestCustomizer;
3132
import org.springframework.boot.cloud.CloudPlatform;
3233
import org.springframework.boot.web.client.RestTemplateBuilder;
3334
import org.springframework.context.annotation.Bean;
3435
import org.springframework.context.annotation.Configuration;
3536
import org.springframework.core.env.Environment;
3637
import org.springframework.http.HttpMethod;
38+
import org.springframework.security.config.annotation.web.builders.WebSecurity;
39+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3740
import org.springframework.web.cors.CorsConfiguration;
3841
import org.springframework.web.servlet.HandlerInterceptor;
3942

@@ -95,4 +98,20 @@ private CorsConfiguration getCorsConfiguration() {
9598
return corsConfiguration;
9699
}
97100

101+
@Bean
102+
public IgnoredRequestCustomizer cloudFoundryIgnoredRequestCustomizer() {
103+
return new CloudFoundryIgnoredRequestCustomizer();
104+
}
105+
106+
private class CloudFoundryIgnoredRequestCustomizer
107+
implements IgnoredRequestCustomizer {
108+
109+
@Override
110+
public void customize(WebSecurity.IgnoredRequestConfigurer configurer) {
111+
configurer.requestMatchers(
112+
new AntPathRequestMatcher("/cloudfoundryapplication/**"));
113+
}
114+
115+
}
116+
98117
}

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryEndpointHandlerMapping.java

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,18 @@
1616

1717
package org.springframework.boot.actuate.cloudfoundry;
1818

19-
import java.util.ArrayList;
20-
import java.util.Arrays;
2119
import java.util.Iterator;
22-
import java.util.List;
2320
import java.util.Set;
2421

25-
import javax.servlet.http.HttpServletRequest;
26-
import javax.servlet.http.HttpServletResponse;
27-
2822
import org.springframework.boot.actuate.endpoint.Endpoint;
2923
import org.springframework.boot.actuate.endpoint.mvc.AbstractEndpointHandlerMapping;
3024
import org.springframework.boot.actuate.endpoint.mvc.HalJsonMvcEndpoint;
3125
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
3226
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
3327
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
3428
import org.springframework.web.cors.CorsConfiguration;
35-
import org.springframework.web.servlet.HandlerExecutionChain;
3629
import org.springframework.web.servlet.HandlerInterceptor;
3730
import org.springframework.web.servlet.HandlerMapping;
38-
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
3931

4032
/**
4133
* {@link HandlerMapping} to map {@link Endpoint}s to Cloud Foundry specific URLs.
@@ -45,15 +37,10 @@
4537
class CloudFoundryEndpointHandlerMapping
4638
extends AbstractEndpointHandlerMapping<NamedMvcEndpoint> {
4739

48-
private final HandlerInterceptor securityInterceptor;
49-
50-
private final CorsConfiguration corsConfiguration;
51-
5240
CloudFoundryEndpointHandlerMapping(Set<? extends NamedMvcEndpoint> endpoints,
5341
CorsConfiguration corsConfiguration, HandlerInterceptor securityInterceptor) {
5442
super(endpoints, corsConfiguration);
55-
this.securityInterceptor = securityInterceptor;
56-
this.corsConfiguration = corsConfiguration;
43+
setSecurityInterceptor(securityInterceptor);
5744
}
5845

5946
@Override
@@ -91,42 +78,4 @@ protected String getPath(MvcEndpoint endpoint) {
9178
return super.getPath(endpoint);
9279
}
9380

94-
@Override
95-
protected HandlerExecutionChain getHandlerExecutionChain(Object handler,
96-
HttpServletRequest request) {
97-
HandlerExecutionChain chain = super.getHandlerExecutionChain(handler, request);
98-
HandlerInterceptor[] interceptors = addSecurityInterceptor(
99-
chain.getInterceptors());
100-
return new HandlerExecutionChain(chain.getHandler(), interceptors);
101-
}
102-
103-
private HandlerInterceptor[] addSecurityInterceptor(HandlerInterceptor[] existing) {
104-
List<HandlerInterceptor> interceptors = new ArrayList<HandlerInterceptor>();
105-
interceptors.add(new CorsInterceptor(this.corsConfiguration));
106-
interceptors.add(this.securityInterceptor);
107-
if (existing != null) {
108-
interceptors.addAll(Arrays.asList(existing));
109-
}
110-
return interceptors.toArray(new HandlerInterceptor[interceptors.size()]);
111-
}
112-
113-
/**
114-
* {@link HandlerInterceptor} that processes the response for CORS.
115-
*/
116-
class CorsInterceptor extends HandlerInterceptorAdapter {
117-
118-
private final CorsConfiguration config;
119-
120-
CorsInterceptor(CorsConfiguration config) {
121-
this.config = config;
122-
}
123-
124-
@Override
125-
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
126-
Object handler) throws Exception {
127-
return getCorsProcessor().processRequest(this.config, request, response);
128-
}
129-
130-
}
131-
13281
}

0 commit comments

Comments
 (0)