[JAVA-25516] Upgraded spring-boot-actuator module to spring boot 3 (#14874)

* [JAVA-25516] Upgraded spring-boot-actuator module to spring boot 3

* [JAVA-25516] Fixed issue related to actuator security
This commit is contained in:
panos-kakos 2023-10-05 11:54:51 +03:00 committed by GitHub
parent bc83cc6616
commit 12809e524b
6 changed files with 63 additions and 52 deletions

View File

@ -9,9 +9,10 @@
<description>This is simple boot application for Spring boot actuator test</description> <description>This is simple boot application for Spring boot actuator test</description>
<parent> <parent>
<groupId>com.baeldung.spring-boot-modules</groupId> <groupId>com.baeldung</groupId>
<artifactId>spring-boot-modules</artifactId> <artifactId>parent-boot-3</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-3</relativePath>
</parent> </parent>
<dependencies> <dependencies>
@ -39,16 +40,6 @@
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -1,36 +1,56 @@
package com.baeldung.endpoints.enabling; package com.baeldung.endpoints.enabling;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
@Configuration
@EnableWebSecurity @EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Configuration
public class SecurityConfiguration {
@Override @Bean
protected void configure(AuthenticationManagerBuilder auth) throws Exception { MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); return new MvcRequestMatcher.Builder(introspector);
auth.inMemoryAuthentication()
.withUser("user")
.password(encoder.encode("password"))
.roles("USER")
.and()
.withUser("admin")
.password(encoder.encode("admin"))
.roles("USER", "ADMIN");
} }
@Override @Bean
protected void configure(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
http.requestMatcher(EndpointRequest.toAnyEndpoint()) http.httpBasic(Customizer.withDefaults());
.authorizeRequests((requests) -> requests.anyRequest() http.securityMatcher(EndpointRequest.toAnyEndpoint());
.hasRole("ADMIN")); http.authorizeHttpRequests(authz -> {
http.httpBasic(); authz.requestMatchers(mvc.pattern("/actuator/**"))
.hasRole("ADMIN")
.anyRequest()
.authenticated();
});
return http.build();
}
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("password")
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
} }
} }

View File

@ -1,9 +1,9 @@
package com.baeldung.endpoints.info; package com.baeldung.endpoints.info;
import javax.persistence.Entity; import jakarta.persistence.Entity;
import javax.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import javax.persistence.Id; import jakarta.persistence.Id;
import javax.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Table(name = "users") @Table(name = "users")

View File

@ -15,7 +15,7 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.context.request.RequestContextListener;
import javax.servlet.ServletContext; import jakarta.servlet.ServletContext;
@EnableScheduling @EnableScheduling
@ComponentScan("com.baeldung.metrics") @ComponentScan("com.baeldung.metrics")

View File

@ -7,14 +7,14 @@ import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils; import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.Filter; import jakarta.servlet.Filter;
import javax.servlet.FilterChain; import jakarta.servlet.FilterChain;
import javax.servlet.FilterConfig; import jakarta.servlet.FilterConfig;
import javax.servlet.ServletException; import jakarta.servlet.ServletException;
import javax.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
import javax.servlet.ServletResponse; import jakarta.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
@Component @Component
public class MetricFilter implements Filter { public class MetricFilter implements Filter {

View File

@ -13,20 +13,20 @@ import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest @SpringBootTest
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class EndpointEnablingIntegrationTest { class EndpointEnablingIntegrationTest {
@Autowired @Autowired
private MockMvc mockMvc; private MockMvc mockMvc;
@Test @Test
@WithMockUser(username = "user", password = "password", roles = "USER") @WithMockUser(username = "user", password = "password", roles = "USER")
public void givenWrongAuthentication_whenCallingActuator_thenReturns401() throws Exception { void givenWrongAuthentication_whenCallingActuator_thenReturns401() throws Exception {
mockMvc.perform(get("/actuator")) mockMvc.perform(get("/actuator"))
.andExpect(status().isForbidden()); .andExpect(status().isForbidden());
} }
@Test @Test
@WithMockUser(username = "admin", password = "admin", roles = "ADMIN") @WithMockUser(username = "admin", password = "admin", roles = "ADMIN")
public void givenProperAuthentication_whenCallingActuator_thenReturnsExpectedEndpoints() throws Exception { void givenProperAuthentication_whenCallingActuator_thenReturnsExpectedEndpoints() throws Exception {
mockMvc.perform(get("/actuator")) mockMvc.perform(get("/actuator"))
.andExpect(jsonPath("$._links").exists()) .andExpect(jsonPath("$._links").exists())
.andExpect(jsonPath("$._links.beans").exists()) .andExpect(jsonPath("$._links.beans").exists())