Skip to content

Commit 2726540

Browse files
committed
Merge branch '2.1.x'
Closes spring-projectsgh-17980
2 parents e3c87cb + 674f2f5 commit 2726540

File tree

28 files changed

+1230
-307
lines changed

28 files changed

+1230
-307
lines changed
Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,48 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.boot.autoconfigure.security.servlet;
16+
17+
package org.springframework.boot.actuate.autoconfigure.security.servlet;
1718

1819
import org.glassfish.jersey.server.ResourceConfig;
1920

21+
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
2022
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2123
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2225
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
2326
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
27+
import org.springframework.boot.autoconfigure.security.servlet.AntPathRequestMatcherProvider;
28+
import org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProvider;
29+
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath;
2430
import org.springframework.boot.autoconfigure.web.servlet.JerseyApplicationPath;
2531
import org.springframework.context.annotation.Bean;
2632
import org.springframework.context.annotation.Configuration;
2733
import org.springframework.security.web.util.matcher.RequestMatcher;
2834
import org.springframework.web.servlet.DispatcherServlet;
29-
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
3035

3136
/**
32-
* Auto-configuration for {@link RequestMatcherProvider}.
37+
* {@link ManagementContextConfiguration} that configures the appropriate
38+
* {@link RequestMatcherProvider}.
3339
*
3440
* @author Madhura Bhave
35-
* @since 2.0.5
41+
* @since 2.1.8
3642
*/
37-
@Configuration(proxyBeanMethods = false)
43+
@ManagementContextConfiguration
3844
@ConditionalOnClass({ RequestMatcher.class })
3945
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
40-
public class SecurityRequestMatcherProviderAutoConfiguration {
46+
public class SecurityRequestMatchersManagementContextConfiguration {
4147

4248
@Configuration(proxyBeanMethods = false)
4349
@ConditionalOnClass(DispatcherServlet.class)
44-
@ConditionalOnBean(HandlerMappingIntrospector.class)
50+
@ConditionalOnBean(DispatcherServletPath.class)
4551
public static class MvcRequestMatcherConfiguration {
4652

4753
@Bean
54+
@ConditionalOnMissingBean
4855
@ConditionalOnClass(DispatcherServlet.class)
49-
public RequestMatcherProvider requestMatcherProvider(HandlerMappingIntrospector introspector) {
50-
return new MvcRequestMatcherProvider(introspector);
56+
public RequestMatcherProvider requestMatcherProvider(DispatcherServletPath servletPath) {
57+
return new AntPathRequestMatcherProvider(servletPath::getRelativePath);
5158
}
5259

5360
}
@@ -60,7 +67,7 @@ public static class JerseyRequestMatcherConfiguration {
6067

6168
@Bean
6269
public RequestMatcherProvider requestMatcherProvider(JerseyApplicationPath applicationPath) {
63-
return new JerseyRequestMatcherProvider(applicationPath);
70+
return new AntPathRequestMatcherProvider(applicationPath::getRelativePath);
6471
}
6572

6673
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManag
9595
org.springframework.boot.actuate.autoconfigure.endpoint.web.reactive.WebFluxEndpointManagementContextConfiguration,\
9696
org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration,\
9797
org.springframework.boot.actuate.autoconfigure.endpoint.web.jersey.JerseyWebEndpointManagementContextConfiguration,\
98+
org.springframework.boot.actuate.autoconfigure.security.servlet.SecurityRequestMatchersManagementContextConfiguration,\
9899
org.springframework.boot.actuate.autoconfigure.web.jersey.JerseySameManagementContextConfiguration,\
99100
org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyChildManagementContextConfiguration,\
100101
org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementChildContextConfiguration,\

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/AbstractEndpointRequestIntegrationTests.java

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,24 @@
1515
*/
1616
package org.springframework.boot.actuate.autoconfigure.security.servlet;
1717

18-
import java.util.ArrayList;
1918
import java.util.Base64;
20-
import java.util.List;
19+
import java.util.function.Supplier;
2120

21+
import org.jolokia.http.AgentServlet;
2222
import org.junit.jupiter.api.Test;
2323

24-
import org.springframework.boot.actuate.endpoint.EndpointId;
25-
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
26-
import org.springframework.boot.actuate.endpoint.Operation;
24+
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
25+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
26+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
2727
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
2828
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
29-
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
30-
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
29+
import org.springframework.boot.actuate.endpoint.web.EndpointServlet;
30+
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpoint;
31+
import org.springframework.boot.autoconfigure.AutoConfigurations;
32+
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
3133
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
34+
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
35+
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
3236
import org.springframework.boot.logging.LogLevel;
3337
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
3438
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
@@ -39,18 +43,13 @@
3943
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
4044
import org.springframework.test.web.reactive.server.WebTestClient;
4145

42-
import static org.mockito.BDDMockito.given;
43-
import static org.mockito.Mockito.mock;
44-
4546
/**
4647
* Abstract base class for {@link EndpointRequest} tests.
4748
*
4849
* @author Madhura Bhave
4950
*/
5051
abstract class AbstractEndpointRequestIntegrationTests {
5152

52-
protected abstract WebApplicationContextRunner getContextRunner();
53-
5453
@Test
5554
void toEndpointShouldMatch() {
5655
getContextRunner().run((context) -> {
@@ -79,6 +78,17 @@ void toLinksShouldMatch() {
7978
});
8079
}
8180

81+
protected final WebApplicationContextRunner getContextRunner() {
82+
return createContextRunner().withPropertyValues("management.endpoints.web.exposure.include=*")
83+
.withUserConfiguration(BaseConfiguration.class, SecurityConfiguration.class).withConfiguration(
84+
AutoConfigurations.of(JacksonAutoConfiguration.class, SecurityAutoConfiguration.class,
85+
UserDetailsServiceAutoConfiguration.class, EndpointAutoConfiguration.class,
86+
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class));
87+
88+
}
89+
90+
protected abstract WebApplicationContextRunner createContextRunner();
91+
8292
protected WebTestClient getWebTestClient(AssertableWebApplicationContext context) {
8393
int port = context.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
8494
.getWebServer().getPort();
@@ -108,19 +118,8 @@ TestEndpoint3 endpoint3() {
108118
}
109119

110120
@Bean
111-
PathMappedEndpoints pathMappedEndpoints() {
112-
List<ExposableEndpoint<?>> endpoints = new ArrayList<>();
113-
endpoints.add(mockEndpoint("e1"));
114-
endpoints.add(mockEndpoint("e2"));
115-
endpoints.add(mockEndpoint("e3"));
116-
return new PathMappedEndpoints("/actuator", () -> endpoints);
117-
}
118-
119-
private TestPathMappedEndpoint mockEndpoint(String id) {
120-
TestPathMappedEndpoint endpoint = mock(TestPathMappedEndpoint.class);
121-
given(endpoint.getEndpointId()).willReturn(EndpointId.of(id));
122-
given(endpoint.getRootPath()).willReturn(id);
123-
return endpoint;
121+
TestServletEndpoint servletEndpoint() {
122+
return new TestServletEndpoint();
124123
}
125124

126125
}
@@ -155,7 +154,13 @@ Object getAll() {
155154

156155
}
157156

158-
public interface TestPathMappedEndpoint extends ExposableEndpoint<Operation>, PathMappedEndpoint {
157+
@ServletEndpoint(id = "se1")
158+
static class TestServletEndpoint implements Supplier<EndpointServlet> {
159+
160+
@Override
161+
public EndpointServlet get() {
162+
return new EndpointServlet(AgentServlet.class);
163+
}
159164

160165
}
161166

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/JerseyEndpointRequestIntegrationTests.java

Lines changed: 38 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,17 @@
1515
*/
1616
package org.springframework.boot.actuate.autoconfigure.security.servlet;
1717

18-
import java.util.Arrays;
19-
import java.util.Collection;
20-
import java.util.Collections;
21-
import java.util.HashSet;
22-
import java.util.List;
23-
2418
import org.glassfish.jersey.server.ResourceConfig;
25-
import org.glassfish.jersey.server.model.Resource;
2619
import org.junit.jupiter.api.Test;
2720

2821
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
29-
import org.springframework.boot.actuate.endpoint.EndpointId;
30-
import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
31-
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
32-
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
33-
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
34-
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
35-
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
36-
import org.springframework.boot.actuate.endpoint.web.jersey.JerseyEndpointResourceFactory;
3722
import org.springframework.boot.autoconfigure.AutoConfigurations;
38-
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
3923
import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration;
40-
import org.springframework.boot.autoconfigure.jersey.ResourceConfigCustomizer;
41-
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
42-
import org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration;
43-
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
4424
import org.springframework.boot.context.properties.EnableConfigurationProperties;
4525
import org.springframework.boot.test.context.FilteredClassLoader;
4626
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
4727
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
4828
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
49-
import org.springframework.context.ApplicationContext;
5029
import org.springframework.context.annotation.Bean;
5130
import org.springframework.context.annotation.Configuration;
5231
import org.springframework.test.web.reactive.server.WebTestClient;
@@ -58,18 +37,6 @@
5837
*/
5938
class JerseyEndpointRequestIntegrationTests extends AbstractEndpointRequestIntegrationTests {
6039

61-
@Override
62-
protected WebApplicationContextRunner getContextRunner() {
63-
return new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
64-
.withClassLoader(new FilteredClassLoader("org.springframework.web.servlet.DispatcherServlet"))
65-
.withUserConfiguration(JerseyEndpointConfiguration.class, SecurityConfiguration.class,
66-
BaseConfiguration.class)
67-
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
68-
UserDetailsServiceAutoConfiguration.class,
69-
SecurityRequestMatcherProviderAutoConfiguration.class, JacksonAutoConfiguration.class,
70-
JerseyAutoConfiguration.class));
71-
}
72-
7340
@Test
7441
void toLinksWhenApplicationPathSetShouldMatch() {
7542
getContextRunner().withPropertyValues("spring.jersey.application-path=/admin").run((context) -> {
@@ -99,15 +66,46 @@ void toAnyEndpointWhenApplicationPathSetShouldMatch() {
9966
});
10067
}
10168

102-
@Configuration(proxyBeanMethods = false)
103-
@EnableConfigurationProperties(WebEndpointProperties.class)
104-
static class JerseyEndpointConfiguration {
69+
@Test
70+
void toAnyEndpointShouldMatchServletEndpoint() {
71+
getContextRunner().withPropertyValues("spring.security.user.password=password",
72+
"management.endpoints.web.exposure.include=se1").run((context) -> {
73+
WebTestClient webTestClient = getWebTestClient(context);
74+
webTestClient.get().uri("/actuator/se1").exchange().expectStatus().isUnauthorized();
75+
webTestClient.get().uri("/actuator/se1").header("Authorization", getBasicAuth()).exchange()
76+
.expectStatus().isOk();
77+
webTestClient.get().uri("/actuator/se1/list").exchange().expectStatus().isUnauthorized();
78+
webTestClient.get().uri("/actuator/se1/list").header("Authorization", getBasicAuth()).exchange()
79+
.expectStatus().isOk();
80+
});
81+
}
10582

106-
private final ApplicationContext applicationContext;
83+
@Test
84+
void toAnyEndpointWhenApplicationPathSetShouldMatchServletEndpoint() {
85+
getContextRunner().withPropertyValues("spring.jersey.application-path=/admin",
86+
"spring.security.user.password=password", "management.endpoints.web.exposure.include=se1")
87+
.run((context) -> {
88+
WebTestClient webTestClient = getWebTestClient(context);
89+
webTestClient.get().uri("/admin/actuator/se1").exchange().expectStatus().isUnauthorized();
90+
webTestClient.get().uri("/admin/actuator/se1").header("Authorization", getBasicAuth()).exchange()
91+
.expectStatus().isOk();
92+
webTestClient.get().uri("/admin/actuator/se1/list").exchange().expectStatus().isUnauthorized();
93+
webTestClient.get().uri("/admin/actuator/se1/list").header("Authorization", getBasicAuth())
94+
.exchange().expectStatus().isOk();
95+
});
96+
}
10797

108-
JerseyEndpointConfiguration(ApplicationContext applicationContext) {
109-
this.applicationContext = applicationContext;
110-
}
98+
@Override
99+
protected WebApplicationContextRunner createContextRunner() {
100+
return new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
101+
.withClassLoader(new FilteredClassLoader("org.springframework.web.servlet.DispatcherServlet"))
102+
.withUserConfiguration(JerseyEndpointConfiguration.class)
103+
.withConfiguration(AutoConfigurations.of(JerseyAutoConfiguration.class));
104+
}
105+
106+
@Configuration
107+
@EnableConfigurationProperties(WebEndpointProperties.class)
108+
static class JerseyEndpointConfiguration {
111109

112110
@Bean
113111
TomcatServletWebServerFactory tomcat() {
@@ -119,24 +117,6 @@ ResourceConfig resourceConfig() {
119117
return new ResourceConfig();
120118
}
121119

122-
@Bean
123-
ResourceConfigCustomizer webEndpointRegistrar() {
124-
return this::customize;
125-
}
126-
127-
private void customize(ResourceConfig config) {
128-
List<String> mediaTypes = Arrays.asList(javax.ws.rs.core.MediaType.APPLICATION_JSON,
129-
ActuatorMediaType.V2_JSON);
130-
EndpointMediaTypes endpointMediaTypes = new EndpointMediaTypes(mediaTypes, mediaTypes);
131-
WebEndpointDiscoverer discoverer = new WebEndpointDiscoverer(this.applicationContext,
132-
new ConversionServiceParameterValueMapper(), endpointMediaTypes,
133-
Arrays.asList(EndpointId::toString), Collections.emptyList(), Collections.emptyList());
134-
Collection<Resource> resources = new JerseyEndpointResourceFactory().createEndpointResources(
135-
new EndpointMapping("/actuator"), discoverer.getEndpoints(), endpointMediaTypes,
136-
new EndpointLinksResolver(discoverer.getEndpoints()), true);
137-
config.registerResources(new HashSet<>(resources));
138-
}
139-
140120
}
141121

142122
}

0 commit comments

Comments
 (0)