현재 Spring Security 6.2.3 을 사용 중인 프로젝트에 JWT 인증 방식을 사용하고 있다.
이번에 spring actuator에 대해서 적용을 하던 중, 보안 상 인증을 태우는게 좋다라는 글을 봤다. actuator의 base path만 알게 된다면 metric, health 정보를 비롯해 shutdown 등 기능도 누구나 접근이 가능해진다. 물론 내가 보고자 하는 것만 enabled true를 해놓으면 된다고는 하지만, 시스템 관리자만 알고 있으면 되는 정보가 누구에게나 공개된다는건 문제가 되는 부분이었다.
그러면 단순히 현재 JWT를 사용하니 token을 동일하게 사용하면 되는걸까?? 나는 spring actuator의 metric 정보를 prometheus를 통해서 수집하고 grafana로 대시보드를 구성하려고 했다. 근데, prometheus에서 spring actuator에 접근할 때 로그인 인증과정이 별도로 존재하지 않고 token 값을 고정으로 두어야 했다. (다른 방법이 있는지는 찾지 못함.....ㅠ) access token은 만료일이 존재하고... 해당 token에 문제가 있으면 그 때마다 prometheus 서버에 접속해서 설정파일을 수정하는 것은 귀찮은 일이고... 방법을 찾다보니 Spring Security의 filter를 여러개 사용이 가능하고 @Order 어노테이션으로 chain 통과 순서도 정할 수 있다는 글을 보게 되었다.
(이걸 아직도 모른다는것에 참.... security 공부를 더 해야겠다...)
구글링을 해보니 antMatcher()를 이용해서 특정 URL 패턴을 해당 filter에서 처리하도록 할 수 있다. 그래서 antMatcher를 config에 넣어보는데 찾지를 못한다...
이 때까지 antMatcher가 Spring boot2의 spring security까지만 지원되는거라고 생각하지 못했다...
spring boot 3.0에서는 securityMatcher로 변경이 되었다라는 것을 찾게되었다.. spring boot 2에서 spring security를 잠시 맛만 보고 실무에서는 적용을 해보지 못해서 이런 변경점에 대해서 놓쳤다.
수정 결과는 다음과 같다.
@Bean
@Order(0)
public SecurityFilterChain basicConfigure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.httpBasic(Customizer.withDefaults())
.cors(configurer -> configurer.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.securityMatcher("/actuator/**")
.authorizeHttpRequests(req ->
req.requestMatchers("/actuator/**")
.authenticated()
.anyRequest()
.denyAll()
)
.sessionManagement(session -> session.sessionCreationPolicy(STATELESS));
return httpSecurity.build();
}
해당 filter는 Basic Auth로 잡았다. application.yaml 파일에 security user 설정을 잡고 해당 계정 정보는 jasypt를 이용해서 암호화를 해놓고 쓸 생각이다. 그리고 해당 filter를 order 0으로 잡아서 먼저 확인하고 match가 안되는건 jwt filter에서 검증하도록 순서를 잡았다.
spring 및 관련 기본 라이브러리에 대해 기초부터 세세하게 다시 살펴보고 정리 중인데, 이번 이슈를 해결하면서 더더욱 기초가 중요하다라는 것을 느끼게 되었다. 원래 그렇게 해왔으니까 라는 경험에 의해서 개발을 주로 해왔던 나를 반성하면서 이번 기회에 열심히 정리를 해보자!!
■ 참고 자료