Describe the bug
Scratched my head at this one for awhile. We have some reactive applications and upon upgrading to Spring Boot 3.0.3, we noticed that the ObservationRegistry had zero handlers registered to it. This is because of some kind of early creation of the ObservationRegistry bean that is caused by the @EnableReactiveMethodSecurity.
I'm not sure what causes this problem in spring security, but in Spring Boot this would happen if something causes the ObservationRegistry bean to be created BEFORE the ObservationRegistryPostProcessor found here: https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java#L61-L70
This post processor is responsible for registering all the observation handlers. When you have an ObservationRegistry without handlers, it effectively becomes a NOOP registry causing all kinds of problems (including 500s in the spring cloud gateway).
To Reproduce
- Go to start.spring.io
- Create a project with: webflux, actuator, spring-security, and prometheus
- Add a configuration class with @EnableReactiveMethodSecurity
- For debugging purposes, add a controller which uses the ObservationRegistry, you can then set a breakpoint on the endpoint so you can inspect the ObservationRegistry bean. You will see it has zero handlers registered.
- Remove the @EnableReactiveMethodSecurity notice that the handlers are added correctly.
Expected behavior
The @EnableReactiveMethodSecurity should not interfere with the ObservationRegistry
Sample
TestConfiguration.java
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
@Configuration
@EnableReactiveMethodSecurity
public class TestConfiguration {
}
TestController.java
package com.example.demo;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class TestController {
public ObservationRegistry observationRegistry;
public TestController(ObservationRegistry observationRegistry) {
this.observationRegistry = observationRegistry;
}
@GetMapping("/hey")
Mono<String> myEndpoint() {
return Mono.just("hey"); // SET YOUR BREAKPOINT HERE
}
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<scope>runtime</scope>
</dependency>
Comment From: braunsonm
It seems this is the same problem as: https://github.com/spring-projects/spring-security/issues/12815
Comment From: marcusdacoregio
This seems to be a duplicate of https://github.com/spring-projects/spring-security/issues/12780.
Can you use Spring Security 6.0.3-SNAPSHOT and check if it fixes the problem?
I'll close this as a duplicate but feel free to continue the discussion if your scenario is different.