Search code examples
spring-bootgroovyspring-securityspring-boot-admin

Spring Boot Client Not Able to Register


I've been trying to setup Spring Boot Admin Server with a client using basic security configuration for a couple days now. Unfortunately I'm unable to get the client to authenticate with the server. I've tried a variety of examples and am at the point where I'm wondering if this is just a bug with the current release of the Spring Boot Admin.

Server application.properties

spring.security.user.name=admin
spring.security.user.password=admin

Server build.gradle

plugins {
    id 'groovy'
}

group 'edu.wsu.it.esg-apps'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:latest.release'
    compile 'de.codecentric:spring-boot-admin-starter-server:2.1.6'
    compile 'org.springframework.boot:spring-boot-starter-web:2.1.7.RELEASE'
    compile 'org.springframework.boot:spring-boot-starter-security:2.1.7.RELEASE'
    compile 'de.codecentric:spring-boot-admin-server-ui-login:2.1.6'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

SecuritySecureConfig.groovy

package admin.security

import de.codecentric.boot.admin.server.config.AdminServerProperties
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler

@Configuration
class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
    private final String adminContextPath

    SecuritySecureConfig(AdminServerProperties adminServerProperties) {
        this.adminContextPath = adminServerProperties.getContextPath()
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // @formatter:off
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler()
        successHandler.setTargetUrlParameter("redirectTo")
        successHandler.setDefaultTargetUrl(adminContextPath + "/")

        http.authorizeRequests()
                .antMatchers(adminContextPath + "/assets/**").permitAll()
                .antMatchers(adminContextPath + "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
                .logout().logoutUrl(adminContextPath + "/logout").and()
                .httpBasic().and()
                .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .ignoringAntMatchers(
                        adminContextPath + "/instances",
                        adminContextPath + "/actuator/**"
                );
        // @formatter:on
    }
}

SpringBootAdminApplication.groovy

package admin

import de.codecentric.boot.admin.server.config.EnableAdminServer
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.Configuration


@Configuration
@EnableAutoConfiguration
@EnableAdminServer
class SpringBootAdminApplication {
    static void main(String[] args){
        SpringApplication.run(SpringBootAdminApplication.class,args)
    }
}

Client application.properties

server.port=8081
logging.level.root=DEBUG

spring.boot.admin.client.url=http://localhost:8080
spring.boot.admin.client.username=admin
spring.boot.admin.client.password=admin
spring.boot.admin.client.api-path=instances


management.endpoints.web.exposure.include=*
management.endpoints.jmx.exposure.include=*
management.endpoint.health.show-details=always
spring.security.user.name=client
spring.security.user.password=client
spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}

Client build.gradle

plugins {
    id 'groovy'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
}

group 'edu.wsu.it.esgapps'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    compile "org.codehaus.groovy:groovy-all:latest.release"
    compile "de.codecentric:spring-boot-admin-starter-client:2.1.6"
    compile "org.springframework.boot:spring-boot-starter-security:2.1.7.RELEASE"
    compile "org.springframework.boot:spring-boot-starter-web:2.1.7.RELEASE"
    compile 'org.springframework.boot:spring-boot-starter-actuator:2.1.7.RELEASE'
    compile 'org.springframework.boot:spring-boot-starter-thymeleaf:2.1.7.RELEASE'
//    compile 'org.springframework.cloud:spring-cloud-config-client:latest.release'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

client application.groovy

package edu.wsu.it.esgapps

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
class Application {
    static void main(String[] args){
        SpringApplication.run(Application.class,args)
    }
}

At this point I'm at a loss. 90% of the configuration and classes are copy paste from reported working examples. I receive the following messages in the logs after firing up the client.

2019-11-24 21:06:36.021 DEBUG 20980 --- [gistrationTask1] o.s.web.client.RestTemplate              : HTTP POST http://localhost:8080/instances
2019-11-24 21:06:36.021 DEBUG 20980 --- [gistrationTask1] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2019-11-24 21:06:36.021 DEBUG 20980 --- [gistrationTask1] o.s.web.client.RestTemplate              : Writing [Application(name=spring-boot-application, managementUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/actuator, healthUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/actuator/health, serviceUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/)] as "application/json"
2019-11-24 21:06:36.024 DEBUG 20980 --- [gistrationTask1] s.n.www.protocol.http.HttpURLConnection  : sun.net.www.MessageHeader@1715607e8 pairs: {POST /instances HTTP/1.1: null}{Accept: application/json}{Content-Type: application/json}{Authorization: Basic YWRtaW46YWRtaW4=}{User-Agent: Java/11.0.1}{Host: localhost:8080}{Connection: keep-alive}{Content-Length: 329}
2019-11-24 21:06:36.030 DEBUG 20980 --- [gistrationTask1] s.n.www.protocol.http.HttpURLConnection  : sun.net.www.MessageHeader@17d95de411 pairs: {null: HTTP/1.1 401}{Set-Cookie: JSESSIONID=3D29D6099D55422892981E516391F158; 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: Mon, 25 Nov 2019 05:06:36 GMT}
2019-11-24 21:06:36.030 DEBUG 20980 --- [gistrationTask1] o.s.web.client.RestTemplate              : Response 401 UNAUTHORIZED
2019-11-24 21:06:36.033 DEBUG 20980 --- [gistrationTask1] d.c.b.a.c.r.ApplicationRegistrator       : Failed to register application as Application(name=spring-boot-application, managementUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/actuator, healthUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/actuator/health, serviceUrl=http://ITS-ESG-T2-3025.ad.wsu.edu:8081/) at spring-boot-admin ([http://localhost:8080/instances]): 401 null

If anyone could help provide me with some insight I'd greatly appreciate it.


Solution

  • This was caused by dependency conflicts that gradle wasn't able to successfully resolve. The fact that I was using spring boot 2.1.7 and boot admin was built on 2.1.5 there were libraries that were either deprecated in 2.1.7 or moved to a different package. Rolling back to 2.1.5 across the board resolved this.