Spring Boot Actuator란?
시스템을 운영하다 보면 시스템이 사용하고 있는 Thread, Memory, Session 등의 요소에 대해서 모니터링은 필수적인 요소다.
운영되는 시스템은 아무리 잘 만들어졌다고 할지라도 버그가 있을 수 있다. 우리는 이런 상황을 대비하기 위해서 모니터링을 해야 한다.
Spring Boot에서는 Spring Boot Actuator라는 자체모니터링 툴을 제공한다.
Spring Boot 공식 Reference에 나와있는 Actuator에 대한 간략한 설명이다.
Spring Boot includes a number of additional features to help you monitor and manage your application when you push it to production. You can choose to manage and monitor your application by using HTTP endpoints or with JMX. Auditing, health, and metrics gathering can also be automatically applied to your application.
Actuator는 애플리케이션을 모니터링하고 관리하는 기능을 Spring Boot에서 자체적으로 제공해준다고 한다.
그리고 Http와 JMX를 통해 확인할 수 있다고 한다.
의존성(Dependency)
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Gradle
implementation 'org.springframework.boot:spring-boot-starter-actuator'
엔드포인트 리스트(EndPoints List)
actuator에서 제공하는 모니터링 엔드포인트는 상당히 많다.
그중에서 유용해 보이는 몇 가지만 알아보자. 전체 리스트의 내용은 Link에서 확인하면 된다.
- beans : application의 전체 Spring beans를 출력
- caches : 사용가능한 cache를 노출
- conditions : configuartion 또는 auto-configuration 되는 class들의 성공 여부와 이유를 설명
- env : Spring Boot의 현재 환경설정 정보(application.yml의 정보 등)를 출력
- health : application의 현재 상태를 보여준다.
- httptrace : http를 trace 한 정보를 노출(기본적으로 최신 100건의 request-response를 보여준다.)
- mappings : Request와 mapping 되어 있는 handler 정보를 가져온다.
- sessions : Spring Session이 가지고 있는 정보를 가져온다.
- threaddump : threaddump를 가져온다.
- logfile : log를 가져온다.
- metrics : metrics 정보를 노출합니다.
Actuator 보안 이슈
애플리케이션 모니터링 및 관리 측면에서 개발자에게 편의를 주는 기능이나, 잘못 사용할 경우 비밀번호, API KEY, Token 등 Credential들이나 내부 서비스 도메인, IP 주소와 같은 중요 정보들이 유출될 수 있다. 그뿐만 아니라 서비스를 강제로 중단시켜 가용성을 침해할 수도 있다.
정리하자면 불필요한 endpoint를 활성화시켜 문제가 발생한다고 할 수 있다.
여러 가지 상황이 있을 수 있으나 대표적으로 아래 3가지 상황을 예시로 들어본다.
환경변수로 중요 정보를 저장해 둔 경우
서비스를 개발할 때 보통 Git을 이용하여 협업을 하고, Github이나 Gitlab, bitbucket과 같은 Code Repository에 push 하고, master 브랜치에 merge 하는 등의 작업을 하게 된다.
이때 중요 정보를 소스코드에 하드코딩할 경우, 유출될 우려가 있기 때문에 소스코드에 API KEY나 DB Password와 같은 중요 정보를 하드코딩하지 않도록 권고한다.
하지만 개발자 입장에서는 반드시 그 정보를 사용해야만 한다.
그래서 개발자들이 주로 사용하는 방법이 소스코드엔서는 환경 변수를 사용하도록 코드를 작성하고, 필요한 중요 정보를 환경변수에 대입하여 사용하는 방법이다.
이때, Spring Actuator의 env endpoint가 필요하여 enable 시키고 expose까지 시켜두었다면, 서비스에서 사용 중인 환경 변수를 볼 수 있게 되기 때문에, 의도치 않게 설정해 둔 중요 정보가 유출될 수 있다.
중요 정보가 메모리에 올라가 있는 경우
서비스 운영 중 사용한 중요 정보가 아직 메모리에 남아있는 경우에도 문제가 될 수 있다.
Spring Actuator는 heapdump라는 endpoint를 제공함으로써 현재 서비스가 점유 중인 heap메모리를 덤프 하여 그 데이터를 제공해 주는 기능이 있어, 덤프 된 메모리 값을 통해 중요 정보가 유출될 위험이 있다.
shutdown endpoint를 enable/expose 한 경우
많지 않은 경우이지만, Shutdown endpoint를 활성화하여 사용할 경우 문제가 될 수 있다.
기본적으로 Shutdown endpoint는 비활성화되어 있는데, 이를 임의로 활성화시킨 뒤 사용하고자 할 때 발생하는 문제로, Shutdown endpoint를 사용할 경우 임의로 웹 애플리케이션을 말 그대로 중지시켜 버릴 수 있기 때문에, 서비스 가용성에 문제가 발생할 수 있다.
Spring Actuator 안전하게 사용하는 방법
Acutuator endpoint는 all disable 상태에서 필요한 것만 include 하여 화이트리스트 형태로 운영한다.
Actuator는 shutdown endpoint를 제외한 나머지 endpoint는 enable 되어있는 것이 기본 설정이다. 하지만 이 기본 설정 그대로 유지할 경우, 불필요한 endpoint가 활성화되어 추후 잠재적 위험이 될 수 있어, 기본 설정을 따르지 않겠다는 설정을 해주어야 한다.
이때 사용하는 것이 management.endpoints.enabled-by-default
속성이다.
해당 속성을 false로 만들어 줌으로써, 모든 endpoint에 대하여 disable 상태를 유지할 수 있다.
운영 중 필요한 endpoint가 있다면 management.endpoint.[endpoint name].enable
속성을 true로 설정하면 된다.
Actuator endpoint expose(노출)가 필요한 경우, 꼭 필요한 것만 include 하여 화이트리스트 형태로 운영한다. 또한 asterisk(*)를 이용하여 include 하지 않는다.
Actuator endpoint들은 enable 시킨다고 바로 사용할 수 있는 구조는 아니다. enable 된 endpoint를 expose(노출) 시켜야 이용할 수 있다는 특징이 있다. 기본적으로 설정된 값이 있는, JMX와 HTTP(WEB) 방식이 기본적으로 expose 되어있는 endpoint가 다르다.
HTTP(WEB)의 경우 기본적으로 expose 되어있는 endpoint가 매우 적기 때문에, 필요한 endpoint를 expose 하기 위해서는 management.endpoints.web.exposure.include
속성에 필요한 endpoint 리스트를 작성해야 한다.
이때 와일드카드도 입력이 가능하기 때문에 Asterisk(*)를 넣는 경우가 있는데, 이렇게 설정할 경우 필요치 않은 endpoint가 노출되기 때문에 추후 잠재적 위험이 될 수 있어, 반드시 와일드카드 형태가 아닌 필요한 endpoint를 각각 추가해 주어야 한다.
shutdown endpoint는 enable 하지 않는다.
shutdown endpoint는 기본적으로 disable 되며, expose도 되지 않기 때문에, 절대로 enable 하지 않도록 각별히 신경을 써주어야 한다.
JMX형태로 Actuator 사용이 필요하지 않을 경우, 반드시 disable 한다.
JMX는 Default로 expose 되어있는 endpoint가 많기 때문에, 사용하지 않음에도 반드시 enable 시켜두면 잠재적 위험이 될 수 있습니다.
이에 JMX형태로 Actuator 사용을 하지 않는 경우 management.endpoints.jmx.exposure.exclude =
형태로 속성을 추가함으로써, 모든 endpoint가 JMX로 사용 불가하게 설정해 주어야 한다.
Actuator는 서비스 운영에 사용되는 포트와 다른 포트를 사용한다.
Actuator가 다양한 기능을 가진 만큼, 공격자들은 웹 사이트를 공격할 때 Actuator 관련 페이지가 존재하는지를 스캐닝하는 경우가 굉장히 빈번하다.
이때 서비스를 운영하는 포트와 다른 포트로 Actuator를 사용할 경우, 공격자들의 스캔으로부터 1차적으로 보호받을 수 있다는 장점이 있다.
이에 management.server.port
속성을 통해 서비스를 운영하는 포트와 다른 포트로 설정하여 사용할 것을 추천한다.
Actuator Default 경로는 사용하지 않고, 경로를 변경하여 운영한다.
포트 관련 항목에서 언급했듯이, Actuator가 다양한 기능을 가진 만큼, 공격자들은 웹사이트를 공격할 때 Actuator 관련 페이지가 존재하는지를 스캐닝 하는 경우가 많은데, 이때 주로 알려준 URI 형태의 스캐닝을 많이 수행하게 된다.
그렇기에 Actuator 서비스에서 주로 사용하는 알려진 기본 경로(/actuator/[endpoint]) 대신 다른 경로를 사용함으로써 외부 공격자의 스캐닝으로부터 보호받을 수 있기 때문에 경로 변경을 추천한다.
management.endpoints.web.base-path
속성을 통해 설정이 가능하며, 유추하기 어려운 문자열의 경로로 설정함으로써 보안성을 향상할 수 있다.
Actuator에 접근할 때에는, 인증되었으며 권한이 있는 사용자만이 접근가능하도록 제어한다.
Actuator는 권한이 충분하며 인증된 관리자만이 다룰 수 있어야 하기에, 세션 또는 인증토큰을 통해 인증 여부와 접근 권한 유무를 파악한 뒤, 적절한 인가 검증 과정을 거쳐 접근할 수 있도록 제어해 줄 것을 추천한다. 다만 이 경우 Actuator를 사용할 때 반드시 인증을 위한 과정을 거쳐야 하기 때문에 health check와 같은 용도로는 부적합할 수 있어, 환경과 상황에 맞게 검토가 필요하다.
참고 자료 :
https://techblog.woowahan.com/9232/
'백엔드 > Spring' 카테고리의 다른 글
레이어간 의존 관계 문제 (0) | 2024.07.29 |
---|---|
[Spring] 동적 프록시(Dynamic Proxy) (1) | 2023.05.26 |
[Spring Cloud] Spring Cloud OpenFeign (0) | 2023.05.22 |
[Spring] 스프링(Spring) (0) | 2023.04.28 |
[Spring] POJO(Plain Old Java Object) (0) | 2023.04.27 |