spring-projects / spring-projects/spring-boot

Improve documentation and/or support for securing requests made on a different management port

Open
#50,355 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: feedback-provided status: waiting-for-triage
Dominant language
Java
Stars
81.5k
Forks
42.7k
Avg merge
2d 4h
Merged PRs (30d)
65

Description

TLDR:
IMHO Spring Boot should provide a supported and documented way to set up the actuator endpoints on a separate management port with completely isolated Spring Security filter chains, or at least with a dedicated chain that does not cause requests made on that port to leak into other chains (unless I want it to).

Long explanation:

I have a Spring Boot application, secured with Spring Security and a custom security filter chain. I was requested to add support for management on a different port, with endpoints exposed through HTTP open to anyone. I followed the docs but it was quite hard for me to deeply understand what happens under the hood and how I should adapt my security configuration. Especially because matchers used to secure the application usually work on paths, and not on specific ports. And apparently there's no out-of-the-box support to match on ports in the actuator API as well.

So, this is what I ended up with, after quite some investigation and debugging.

Starting from https://docs.spring.io/spring-boot/reference/actuator/endpoints.html#actuator.endpoints.security I understood I had to create a separate security filter chain. It's key that this chain is applied first (through proper @Order, which is not evident from the example), so that:

  • if the securityMatcher matches (and this happens when the request is made on the management port), this chain is applied
  • otherwise the next available filter chain will be applied, instead, since it means the request was made on the standard port
  • (please note: this gets complicated when you have a WebSecurityCustomizer which adds ignored resources with ignoring().requestMatchers(...), because this will cause an additional chain to be created and put in front of any other chain - but this is a different story)

In my mind, I wanted that any request made on the management port would go into the first chain, being authorized or not based on what that chain establishes, while any request made on the standard port would go into the other chain. So two completely separate paths for processing the request, from reception to response, passing through filtering. However, with the solution proposed in that example, things are not fully working in this way. If I make a request to the management port with a path which does not correspond to a management endpoint, the security matcher returned by EndpointRequest.toAnyEndpoint() will return false, and hence my other security chain is queried, even if the request was made on the management port. In the end, most probably my main application resources would still be protected and not reachable, due to how Spring Boot works under the hood: it creates a separate application context, child of the main one, where another DispatcherServlet is configured, which can serve only management endpoints and nothing else (again, something that the documentation does not fully explain and which has important consequences that, instead, should be made perfectly clear to users, as the currently open issues demonstrate and my direct experience also proved, as I suddenly started to receive two ContextRefreshEvents on a listener that didn't expect it). So, even if security filter chains are not isolated by each other, the final request handling is. Still, the fact that requests made on the management port still leak into my main application security chain does not sound correct to me, at least not on an "out-of-the-box" experience, as I feel the two different ports should be doors to completely different resources and security processing. In my case, it was also causing troubles because my main security chain had quite some configuration that was expecting things to work in a way which simply does not apply to requests made on the management port, like assumptions on pre-authenticated HTTP headers which are instead missing, or redirections on AccessDeniedExceptions to resources that are not available on the context bound to requests made on the management port.
In the end, what I did was to apply on the above chain a security matcher extending ApplicationContextRequestMatcher that works similarly to the matcher returned by EndpointRequest.toAnyEndpoint() (i.e.: it filters out requests where the request context is not bound to the management application context, in its ignoreApplicationContext(WebApplicationContext)), but has matches(HttpServletRequest, Supplier) always returning true.

Another option could be to provide a way to define a completely independent filter chain, instead of one that goes into the same FilterChainProxy as the main one...
Maybe other people have different requirements, which require full or hybrid application processing of requests made on both ports (as some other open issues here seem to suggest), but this sounds more like the exception to me, rather than the first simple option to start with.

What do you think?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the actuator endpoint security documentation and inspect EndpointRequest.toAnyEndpoint(), ApplicationContextRequestMatcher, FilterChainProxy, and the separate management application context described in the report. Reproduce requests on the management and standard ports, then establish whether done means clearer documentation, isolated filter-chain behavior, or both.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.