Spring boot actuator auditevents with custom ReactiveAuthenticationManager - spring-boot

I have setup my own ReactiveAuthenticationManager
public class CustomReactiveAuthenticationManager implements ReactiveAuthenticationManager
and then in SecurityWebFilterChain:
.authenticationManager(this.authenticationManager)
However after this setup im not getting anything in the actuator auditevents endpoint:
{"events":[]}
What do I need to change to have audit events even if I use a custom ReactiveAuthenticationManager?

This isn't a problem with your custom AuthenticationManager. It is a limitation of Spring Security. At the time of writing, events are not published when using reactive Spring Security. An enhancement that will remove the limitation is being tracked in this Spring Security issue.

Related

Configuring spring-oauth2-client for non boot spring framework

In spring boot, application.yml takes in the Spring oauth2 client config. How do I configure it for the non-boot application. By configuration I mean giving client ID, secret, scopes and redirect URI.
You could find an example here:
https://www.baeldung.com/spring-security-5-oauth2-login#non-boot
You need to:
Build your ClientRegistration.
A ClientRegistrationRepository.
Register your repository on WebSecurityConfigurerAdapter.
If you don't use SpringBoot : there is no application.yml and even if you can add the support of yml files. It won't handle your oauth2 client config.
Anyway you can use Spring security to implement your custom Authorization Service, a User service and implement a Token Store of your choice (JBDCTokenStore or JWTTokenStore for example). But It's a very wide question depending on your business logic.
You can find some well documented samples on :
https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2
Of course you can handle both XML and javaConfig even mixed Spring confugurations.
Create a #Configuration class with a #ComponentScan on the packages containing components or bean definitions.
#Configuration
#ComponentScan({ "com.firm.product.config.xml","com.firm.product.config.java" })
public class SpringConfig {
}
You can also set properties with #PropertySource() ans #Value annotations. It's very well documented.

Spring Boot metrics http.client.requests do not work for WebClient reactive applications

I have a spring boot 2.2.2 microservices, which integrations with other services using WebClient (rective). According to Spring documentation, the actuator should return "http.client.requests" metrics by default as Timer is enabled by default. But it does not work for me. I am able to get http.server.requests" metrics.
My WebClient is a bean configured and build with WebClient.builder(), as documented here: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-metrics-http-clients
Use Spring Boot's preconfigured WebClient.Builder instead of WebClient.builder() to have an instance of WebClient.
You can find more detail here.
As in the following you can have a bean of WebClient.
#Configuration
public class ClientConfiguration {
#Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
return webClientBuilder
.baseUrl("https://example.org")
.build();
}
}
WebClient.Builder is an Auto-configuration, means the injected point above will receive a newly cloned instance of the builder.
Here is the source for WebClientAutoConfiguration
I've noticed my application has to make a WebClient call before the metrics/http.client.requests endpoint exists. Prior to my application making a WebClient call that endpoint isn't discoverable and returns NOT FOUND.
Hope that helps others in a similar situation!

Spring Boot Actuator requires #EnableWebMvc but that turns off other features

I got confused trying to integrate Actuator to a project using Spring Boot 1.5.11's static resource serving feature:
Spring Boot Actuator does not work without #EnableWebMvc, HTTP 406 is returned because the right Http media converter is not installed.
But if I add #EnableWebMvc, it turns off serving resources from the static folder and other Spring Boot features.
Is there a way to initialize Actuator without losing Boot features?
Found a bug in Spring Boot 2.0, it seems it was there in Boot 1.5 as well. Workaround: setting favorPathExtension to false turns off buggy code in ServletPathExtensionContentNegotiationStrategy and Actuator endpoints start working.
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}

JerseyConfig and #Profile to hide a REST endpoint

I'm trying to hide a REST endpoint based on runtime configuration in Spring and Jersey. The most straightforward way is to throw the NotFoundException from the controller itself but maybe there's more kosher. The controller is registered in the constructor of the config class which extends org.glassfish.jersey.server.ResourceConfig.
I thought of using the #Profile annotation on the controller but I can still access the endpoint. When I hit that endpoint, I get the following error:
o.g.j.s.s.SpringComponentProvider - None or multiple beans found in Spring context
but then Jersey manages to access that controller, which I confirmed by attaching a debugger to the Spring process. So Jersey does not honor the #Profile setting.
On a separate note, I also have Swagger plugged into Jersey and when accessing the definition endpoint (.../swagger.json) I can see the endpoint provided by the #Profile-disabled controller.
Is there anything better I can do here is is throwing the NotFoundException the best option?
Note: Sorry, I thought I saw that you were using Spring Boot. The following answer is only relevant for Spring Boot.
#Profile is only good for Spring bean registration, but you are still registering the service with Jersey as a resource. What you can do is use a ResourceConfigCustomizer and add the #Profile to the customizer. This way it will only register the resource with Jersey ResourceConfig if the correct profile is active.
#Component
#Profile("..")
public class MyResourceConfigCustomizer implements ResourceConfigCustomizer {
#Override
public void customize(ResourceConfig config) {
config.register(MyResource.class);
}
}

Spring Security 4 & CDI

I want to use SpringSecurity4 in a CDI/EJB environment.
Is this possible? Can SpringSecurity can be used without using Spring?
What I want to do, is to use SpringSecurity with my EJB and CDI components.
Spring Security is basically a filter machine, filtering all the incoming requests. However, plenty of it's functionality is Spring-core dependent. It is possible to utilize Spring in a CDI application, but Spring's core is heavyweight and it's functionality is funny compared to CDI. That would be a downgrade and there would be no point in using CDI.
What you can do is to have a look at some Security projects for JEE world.
Apache DeltaSpike and it's Security module.
Keycloak - The absolute solution. Keycloak goes far, far beyond Spring security's functionality. It is an evolution of old PicketLink libraries developed by JBoss, but those are discontinued and merged into Keycloak instead. An example how simple usage of Keycloak is can be found here.
It is also not that hard to write own security interceptor using #WebFilter and #Inject :), there are several projects on GitHub:
https://github.com/rmpestano/security-interceptor
https://github.com/clairton/security
https://github.com/Rudin-Informatik/cdi-security
https://github.com/rafaelodon/my-security-context
I have no experience with these projects. However, I am always amazed how easily can Spring Security be replaced :)
I am using Spring Security with CDI but I can say it is not very healthy since Spring Security is based on spring and spring is messing with the CDI beans.
Here is what happened to me. I customized the AuthenticationProvider of spring security in order to authenticate users through my authentication server. When implementing this mechanism I used my predefined CDI beans by injecting them using (#Inject) annotation. At this point spring somehow intercepts the injection and creates its own bean, which means you cannot use any of the values you set to the CDI bean previously.
In order to solve this, I did some trick like this:
#Inject
private LoginController loginController;
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//Here, the injected bean is empty, I am requesting my old bean from CDI and assign it back.
LoginController bm = (LoginController) CDI.current().select(LoginController.class).get();
loginController = bm;
I don't know if this is the answer you are looking for but i hope this helps...

Resources