Spring boot admin client not able to register with spring boot admin

1k Views Asked by At

I have a spring boot admin server application running which is secured by using spring security basic auth. When I am trying to register a spring boot admin client it's not able to register itself with spring boot admin. Here are the detail about both the application.

Spring Boot Admin Server

pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
<properties>
    <spring-boot-admin.version>2.7.4</spring-boot-admin.version>
</properties>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    </dependencies>

application.yml

spring:
  security:
    user:
      name: admin
      password: admin@123
  application:
    name: spring-boot-admin

server:
  port: 8081

Main class

@SpringBootApplication
@EnableAdminServer
public class AdminServer {
    public static void main(String[] args) {
        SpringApplication.run(AdminServer.class, args);
    }
}

With the above configuration Spring boot admin UI is secured with basic auth.

Spring Boot Admin Client

pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
<properties>
    <spring-boot-admin.version>2.7.4</spring-boot-admin.version>
</properties>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
        </dependency>
    </dependencies>

application.yml

spring:
  boot:
    admin:
      client:
        url: http://localhost:8081
        username: admin
        password: admin@123
management:
  endpoints:
    web:
      exposure:
        include: loggers, health, info
  endpoint:
    loggers:
      enabled: true
    health:
      show-details: always

After turning on the debug log on spring boot admin client, I see the following error

2023-06-09 16:57:55.116 DEBUG 23402 --- [gistrationTask1] o.s.web.client.RestTemplate              : HTTP POST http://localhost:8081/instances
2023-06-09 16:57:55.117 DEBUG 23402 --- [gistrationTask1] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2023-06-09 16:57:55.117 DEBUG 23402 --- [gistrationTask1] o.s.web.client.RestTemplate              : Writing [Application(name=admin-client, managementUrl=http://localhost:8080/actuator, healthUrl=http://localhost:8080/actuator/health, serviceUrl=http://localhost:8080/)] as "application/json"
2023-06-09 16:57:55.118 DEBUG 23402 --- [gistrationTask1] s.n.www.protocol.http.HttpURLConnection  : sun.net.www.MessageHeader@6f223fc18 pairs: {POST /instances HTTP/1.1: null}{Authorization: Basic YWRtaW46YWRtaW5AMTIz}{Accept: application/json}{Content-Type: application/json}{User-Agent: Java/17.0.6}{Host: localhost:8081}{Connection: keep-alive}{Content-Length: 220}
2023-06-09 16:57:55.121 DEBUG 23402 --- [gistrationTask1] s.n.www.protocol.http.HttpURLConnection  : sun.net.www.MessageHeader@4f08eaf016 pairs: {null: HTTP/1.1 401}{Vary: Origin}{Vary: Access-Control-Request-Method}{Vary: Access-Control-Request-Headers}{Set-Cookie: JSESSIONID=F1EE36B57198F3F2D2DDBB3DDE33A403; Path=/; HttpOnly}{X-Content-Type-Options: nosniff}{X-XSS-Protection: 1; mode=block}{Cache-Control: no-cache, no-store, max-age=0, must-revalidate}{Pragma: no-cache}{Expires: 0}{X-Frame-Options: DENY}{WWW-Authenticate: Basic realm="Realm"}{Content-Length: 0}{Date: Fri, 09 Jun 2023 11:27:55 GMT}{Keep-Alive: timeout=60}{Connection: keep-alive}
2023-06-09 16:57:55.121 DEBUG 23402 --- [gistrationTask1] o.s.web.client.RestTemplate              : Response 401 UNAUTHORIZED

I am not able to figure out what am I missing. Without auth the spring boot admin client is able to register with spring boot admin.

1

There are 1 best solutions below

1
Mudit Shukla On BEST ANSWER

This is resolved now. Followed spring boot admin reference http://docs.spring-boot-admin.com/2.7.4/#_securing_spring_boot_admin_server. After adding SecurityConfig it's working as expected.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final AdminServerProperties adminServer;

    private final SecurityProperties security;

    @Value("${spring.security.user.name}")
    private String username;

    @Value("${spring.security.user.password}")
    private String password;
    public SecurityConfig(AdminServerProperties adminServer, SecurityProperties security) {
        this.adminServer = adminServer;
        this.security = security;
    }

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        successHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests(
                        (authorizeRequests) -> authorizeRequests.antMatchers(this.adminServer.path("/assets/**")).permitAll()
                                .antMatchers(this.adminServer.path("/actuator/info")).permitAll()
                                .antMatchers(this.adminServer.path("/actuator/health")).permitAll()
                                .antMatchers(this.adminServer.path("/login")).permitAll().anyRequest().authenticated()
                ).formLogin(
                        (formLogin) -> formLogin.loginPage(this.adminServer.path("/login")).successHandler(successHandler).and()
                ).logout((logout) -> logout.logoutUrl(this.adminServer.path("/logout")))
                 .httpBasic(Customizer.withDefaults())
                .csrf((csrf) -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .ignoringRequestMatchers(
                                new AntPathRequestMatcher(this.adminServer.path("/instances"),
                                        POST.toString()),
                                new AntPathRequestMatcher(this.adminServer.path("/instances/*"),
                                        DELETE.toString()),
                                new AntPathRequestMatcher(this.adminServer.path("/actuator/**"))
                        )); // <4>


        return http.build();

    }

    @Bean
    public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
        UserDetails user = User.withUsername(username).password(passwordEncoder.encode(password)).roles("USER").build();
        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}