Spring

Spring Boot Admin 구축 및 보안 설정

beekei 2023. 1. 2. 19:12
반응형

Spring Boot Admin은 Spring Boot 애플리케이션을 관리하고 모니터링하기 위한 커뮤니티 프로젝트이다.
현재 업무에는 ELK를 구축해 실시간 로깅, 서버 매트릭 정보 모니터링 등등을 사용하고 있지만,
서버 이전 시 한정적인 환경에서 Spring Boot Admin을 사용할 가능성도 있어 정리하며 구축하려 한다.

아래 예제는 Spring Boot 2.6.7 버전 기준이다.

1. Spring Boot Admin Server 구축

build.gradle
Spring Boot 프로젝트 생성 후 사용할 라이브러리를 추가한다.

dependencies {
    ....
    // 접속 시 보안 처리
    implementation 'org.springframework.boot:spring-boot-starter-security'
    // 접속 시 로그인 웹 화면
    implementation 'org.springframework.boot:spring-boot-starter-web'
    // Spring Boot Admin Server 라이브러리
    implementation 'de.codecentric:spring-boot-admin-starter-server:2.4.1'
}

application.yml
yml에 환경을 설정한다.
보안 처리할 username과 password는 환경변수 처리를 해주었다.

server:
  port: 8090

spring:
  application:
    name: spring-boot-admin-test
  security:
    user:
      name: ${ADMIN_SERVER_USERNAME}
      password: ${ADMIN_SERVER_PASSWORD}

WebSecurityConfig.java

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final AdminServerProperties adminServer;

    public WebSecurityConfig(AdminServerProperties adminServer) {
        this.adminServer = adminServer;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 로그인 성공 시 메인페이지로 이동
        final SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        loginSuccessHandler.setTargetUrlParameter("redirectTo");
        loginSuccessHandler.setDefaultTargetUrl(this.adminServer.path("/"));

        http.authorizeRequests()
            // login 페이지 접근 가능
            .antMatchers(this.adminServer.path("/login")).permitAll()
            // 나머지 접근은 권한 필요
            .anyRequest().authenticated()
            // 로그인 URL 설정 및 SuccessHandler 설정
            .and().formLogin().loginPage(this.adminServer.path("/login")).successHandler(loginSuccessHandler)
            // 로그아웃 URL 설정
            .and().logout().logoutUrl(this.adminServer.path("/logout")).and()
            // HTTP-Basic 지원 사용(Client 등록을 위한)
            .httpBasic()
            .and().csrf()
            // 쿠키를 사용하여 CSRF 보호
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            // CSRF 비활성화 URL
            .ignoringAntMatchers(
                this.adminServer.path("/instances"),
                this.adminServer.path("/actuator/**")
            );

    }
}

위 설정을 마치고 환경변수 설정 후 서버를 시작한다.

서버가 정상적으로 시작되었다면 위에서 설정한 포트번호로 접속해보면 로그인 화면이 나타난다.

위에서 환경변수로 설정한 username과 password도 접속이 가능하다.
Spring Boot Admin에 대한 더 많은 설정은 해당 글 가장 하단 참고 사이트에서 확인이 가능하다.

2. Spring Boot Admin Client 설정

build.gradle
Spring boot admin client 라이브러리를 추가한다.

dependencies {
    ....
    implementation 'de.codecentric:spring-boot-admin-starter-client:2.4.1'
}

application.yml
client 및 autuator의 환경을 설정한다.

server:
  port: 8080
  boot:
    admin:
      client:
        auto-registration: true // 클라이언트 자동 등록
        url: http://localhost:8090 // admin server url
        username: ${ADMIN_SERVER_USERNAME} // 계정 아이디
        password: ${ADMIN_SERVER_PASSWORD} // 계정 비밀번호
        instance:
          name: client1 // 인스턴스명
          service-url: http://localhost:8080 // 인스턴트 URL
  
management:
  endpoints:
    web:
      base-path: /app // actuator 접근 URL 설정
      exposure: // 사용할 actuator 엔드포인트 설정
        include: refresh, health, metrics, logfile, env 
  endpoint:
    health:
      show-details: always  // health 엔드포인트 정보 노출
      
logging:
  config: classpath:logback-spring.xml // logback 설정
  file:
    name: ./logs/application.log // log 파일 설정


더 많은 Actuator endpoint에 대한 정보는 해당 글 가장 하단 참고 사이트에서 확인이 가능하다.
logback에 대한 설정까지 작성하면 글이 너무 길어져 생략하겠다.

actuator는 개발자에게 편의를 주지만, 보안처리를 하지 않고 사용할 경우 서비스에 중요 정보들이 유출될 수 있다.
아래 항목을 설정하는 것을 매우 권장한다.
[권장 설정]
1. base-path를 설정해 Default 경로를 사용하지 않고, 경로를 변경하여 운영한다.
2. 사용할 엔드포인트만 enable 처리한다.
3. 애플리케이션 포트와 다른 포트로 설정해 운영한다. (management.server.port = [포트번호])
(다른 포트 사용 시 local에서 접근할 때 timeout이 발생해서 예제에서는 해당 설정을 하지 않았습니다.)
4. actuator 접근 시 보안 처리(Security)


WebSecurityConfig.java
아래 예제는 actuator에 localhost IP만 접근되도록 설정했다. 다른 방식의 보안처리를 하여도 무방할 것 같다.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    ....
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            ....
            // 설정한 IP 주소에서만 app 경로로 접근 가능
            .antMatchers("/app/**").hasIpAddress("localhost")
            .anyRequest().authenticated()
            .and()
            ...
            .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler())
            .authenticationEntryPoint(authenticationEntryPoint());

        http.addFilterBefore(new TokenAuthenticationFilter(tokenProvider()), UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(new TokenExceptionFilter(), TokenAuthenticationFilter.class);
    }
    
}

Security 설정 후 actuator endpoint를 접속해보면 접근이 불가한 것을 확인할 수 있다!

3. Spring Boot Admin Server 접속

위 설정이 모두 끝났으면 Server와 Client 모두 서버를 작동한 후 Spring Boot Admin에 접속해보면 client가 등록된 것을 확인할 수 있다.

해당 인스턴스를 클릭 해보면 위에서 설정한 actuator endpoint에 관한 정보들을 확인할 수 있다.

metrics
env
logfile

참고 사이트

Spring Boot Admin : https://codecentric.github.io/spring-boot-admin/2.4.1/
Actuator endpoint : https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#actuator.endpoints
Actuator 보안처리 권장 : https://techblog.woowahan.com/9232/

반응형