MSA 서비스의 각 application.yml 설정 값을 Spring Cloud Config 서버에서 요청 받아 오는 방식으로 구성하는 도중 보안 관련 문제점이 있었고, 이를 해결한 방법을 소개하고자 한다.
문제 상황
Config 서버의 URL을 직접 주소창에 입력하여 요청하면, 복호화 된 설정 값이 그대로 노출 된다는 문제점이 있다.
config 서버에 다음과 같은 요청을 보내면 모든 설정 값을 볼 수 있다.
http://publicIP:8888/member/prod
Config 서버에서 요청 받는 설정 값은 DB Password, AWS secret key와 같은 민감 정보가 들어있기 때문에 url 요청에 의한 조회를 방지해야 한다.
AWS VPC
AWS VPC는 aws 사용자의 전용 가상 네트워크이다. 즉, 사용자는 IP 주소 범위, 서브넷 생성, 라우팅 테이블 및 네트워크 게이트웨이 구성 등 가상 네트워크 환경을 구성해 VPC를 생성할 수 있는 것이다.
private subnet / public subnet
VPC에 여러 개의 subnet 주소 구역을 설정할 수 있다.
subnet 구역에 인스턴스를 각각 배정할 수 있고, VPC는 기본적으로 격리된 네트워크 환경이기 때문에 인터넷 게이트웨이를 라우팅 테이블에 설정하여 외부와 통신할 수 있는 public한 서브넷을 구성할 수 있다.
즉, MSA 서비스가 실행되는 인스턴스는 public 서브넷(인터넷 게이트웨이가 등록된 라우팅 테이블과 연결된 서브넷)에, Config 인스턴스는 private 서브넷에 할당하여 외부 접근을 제한하면 되는 것이다.
이와 같이 구성하게 되면 API Gateway를 비롯한 각 서비스는 인터넷에 연결되어 요청을 받을 수 있고, 내부적으로는 Config 서버와 통신하여 설정 값을 주기적으로 받아올 수 있는 것이다.
💡 기본적으로 VPC에 구성된 서브넷은 private 서브넷으로, VPC 내에서만 통신을 주고받을 수 있다.
AWS에서 제공하는 기본 VPC는 인터넷 게이트웨이를 라우팅 테이블에 등록해 놓은 것이다.
💡 VPC에서 사용하는 사설 IP 대역
10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
Git 통신
하지만 Config 서버를 private으로 감추게되면 Git과 통신할 수 없게 된다.
결국 Git 레포지토리에 있는 설정 값을 불러와야 하기 때문에 인터넷과 연결 시켜주어야 하는 것이다.
보안 그룹 설정
그렇다면 어떻게 해야 할까?
다시 돌아와서 Config 서버를 private 인스턴스로 구성하지 않고 public 인스턴스로 구성한다.
그리고 Git과 통신하는 인바운드 SSH 포트만 열어 놓은 보안 그룹을 연결시켜주기만 하면 된다.
💡 Config 인스턴스는 꼭 서비스 인스턴스와 같은 VPC 내에 구성해야한다.
서비스에서 주기적으로 watch를 통해 Config 파일과 통신하기 때문에 SSH를 제외하고 접근을 막아 놓은 Config 서버와 연결하기 위해서 같은 VPC내에서 내부적으로 통신해야 한다.
그러면 Git 연결을 위한 외부 통신에는 열려있지만, 다른 모든 요청에 대해서는 접근이 제한된다.
서로 다른 인스턴스가 통신하기 위해서는 public IP로 통신하거나, 같은 VPC내의 private IP 즉, 로컬IP로 통신할 수 있다.
우리는 서비스 인스턴스, Config 인스턴스 둘 다 public으로 열려있어 public IP로 통신할 수 있지만, Config 인스턴스에서 ssh를 제외한 접근을 모두 제한했기 때문에 private IP로 통신해야 한다.
먼저, 서비스 인스턴스와 Config 인스턴스의 로컬 IP를 확인한다.
hostname -i
💡 docker로 컨테이너를 띄우는 경우에도 당연히 docker 컨테이너의 IP 주소가 아닌 인스턴스의 로컬 IP로 연결해야 한다. (인스턴스로 먼저 접근한 후에 그 위에서 돌아가는 도커 컨테이너에 연결되는 것)
서비스 인스턴스와 Config 인스턴스가 로컬 통신을 하기 위해서는 한 가지 더 해주어야 할 작업이 있다.
Config 인스턴스의 보안그룹에 서비스 인스턴스 로컬 IP 주소를 열어주어야 한다. (Config 서버의 포트번호 8888)
서비스 인스턴스에서 Config 서버의 IP 주소로 서비스를 띄워보자.
docker run -d --network nuguri-network -e "spring.config.import=optional:configserver:http://172.31.1.25:8888" -e "eureka.client.serviceUrl.defaultZone=http://discovery-service:8761/eureka/" -e "spring.redis.host=redis" --name member-service {...}/member-service:1.0
spring.config.import 환경변수 설정값으로 Config 서버의 로컬 IP주소(172.31.1.25)를 적어준다.
Config 서버와 잘 연결된 것을 볼 수 있다.
'Spring' 카테고리의 다른 글
Spring Security Remember-Me (0) | 2024.06.22 |
---|---|
QueryDsl - 중복 필터 where문 적용 (0) | 2024.02.10 |
Embedded Redis로 테스트 환경 구축하기 (0) | 2023.10.30 |
Spring Cloud Config Watch (1) | 2023.10.11 |
Spring Gateway 에러 핸들링 (0) | 2023.09.19 |