Description
Describe the bug
I am trying to secure my actuator endpoints. For this purpose, I have a Multiple-Config where I specify the paths via an MVC RequestMatcher, which endpoints are to be used for which config.
The goal is that all actuator endpoints are secured and the remaining endpoints of my application are open.
My security config:
@EnableWebSecurity
public class SecurityConfiguration
{
@Configuration
@Order(1)
public static class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.requestMatchers(matcher -> matcher.mvcMatchers("/actuator/**")).authorizeRequests().anyRequest().authenticated(); // -> /actuator/jolokia endpoint is open
// http.requestMatchers(matcher -> matcher.antMatchers("/actuator/**")).authorizeRequests().anyRequest().authenticated(); -> /actuator/jolokia endpoint is secured
}
}
@Configuration
public static class DefaultSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.requestMatchers(matcher -> matcher.mvcMatchers("/**")).authorizeRequests().anyRequest().permitAll();
}
}
}
If I now specify my actuator endpoints via a MvcMatcher, all actuator endpoints are secured except for the endpoint "/actuator/jolokia".
Example:
"/actuator/prometheus" is secured:
But if I now use AntMatcher as a matcher, the endpoint "/actuator/jolokia" is also secured.
Why does the MvcMatcher not work for the specific endpoint "/actuator/jolokia"? Is this a bug or is there a precise reason why the endpoint "/actuator/jolokia" only works with an AntMatcher?
To Reproduce
Use the Config http.requestMatchers(matcher -> matcher.mvcMatchers("/actuator/**")).authorizeRequests().anyRequest().authenticated();
in your Security Config and call the endpoint "actuator/jolokia" with the expectation that it is secured.
Expected behavior
That the mvcMatcher has secured the Actuator endpoint Jolokia.
Activity
fegbers commentedon Oct 5, 2023
Any news?
jzheaux commentedon Oct 17, 2023
Sorry for the delay, @npriebe. The answer is likely because
/actuator/jolokia
is not a Spring MVC endpoint, though I'll need a little more information.What is the underlying servlet configuration for this application? I'm specifically curious about what servlets are registered and to what URL patterns.
If you aren't sure how to obtain this, you could also post a minimal sample application on GitHub that uses your version of Boot, Spring Security, Actuator, and Jolokia, and I'd be happy to help.
npriebe commentedon Oct 17, 2023
Hi @jzheaux , I have set up an example project with which you can reproduce the problem: https://github.com/npriebe/spring-security-jolokia-example
When you check out the project and then run it locally, the jolokia endpoint is open, although it should be closed according to
SecurityConfiguration
.In the documentation, the Jolokia endpoint is listed under web endpoints, so I actually expect it to behave the same way as the Prometheus endpoint. Which is secured with mvc, for example. https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html/production-ready-features.html#production-ready-endpoints
jzheaux commentedon Oct 17, 2023
Thanks for the sample. Actuator endpoints are a mixture of Spring MVC and other endpoints. Given that, Spring Boot provides a request matcher that you can use like so:
to alleviate the need for you to figure out which are which.
toAnyEndpoint
creates a composite request matcher based on your Actuator Boot configuration. This is also nice because the resulting matcher is more targeted than a blanket/actuator/**
.As a side note, the need for your application to recognize this distinction is reduced in Spring Security 6.2. In that version, you can simply specify
/actuator/**
and have it work as you described.npriebe commentedon Oct 18, 2023
Thank you for the explanation. My Spring application is currently still running with Spring Security Version 5.6.1, which is why the option to secure the endpoints via the
EndpointRequest.toAnyEndpoint()
method is not yet possible. After an update, this should be possible.