Spring/Spring Cloud

Spring Cloud Config Server - Vault 적용

묠니르묘묘 2023. 9. 23. 18:19

🚀 Spring Cloud Config 란?

Spring Cloud Config Server

  • 분산 시스템에서 애플리케이션 구성 데이터를 하나의 중앙화 된 저장소에서 관리 가능
  • 각 서비스를 다시 build(빌드)하지 않고 최신 구성 정보 적용 가능
  • 스프링 및 스프링이 아닌 서비스와 긴밀한 통합
  • 애플리케이션 환경에 맞는 구성 정보 사용 가능(dev, local. prod ...)
  • 속성 값 암호화 및 해독(대칭 or 비대칭)
  • MSA 인스턴스를 많이 실행하더라도 항상 동일한 구성 보장 가능
  • 자체 프로퍼티(property) 관리 저장소가 있지만, 오픈 소스 프로젝트와도 통합 가능
    • Git(깃)
    • Eureka(유레카)
    • Vault(볼트)
    • ....

 

그림처럼 Config Server는 외부 저장소에서 최신 구성 정보를 가져오고, 그것을 애플리케이션에게 줄 수 있습니다.

애플리케이션은 각각 필요한 구성 정보를 가져올 수 있으며, 그림에 있는 구성정보 외에도 키-값으로 이루어진 데이터를 가져옵니다.

 

🚀  외부 저장소는 어떤 것을 사용해야 할까?

Config Server는 로컬 저장소(파일 저장소)를 사용해도 된다.

하지만 클라우드 기반 애플리케이션에서는 실용성이 크게 없다.

공유 파일 시스템을 설정하고 관리해야하기 때문에 손쉽게 구성 정보를 갱신할 수 있어야 한다.

따라서 Git과 Vault를 사용하는 것이다.

 

💾 Github 저장소

  • 깃허브에 구성 정보를 저장하고 손쉽게 변경 및 제어를 할 수 있음
  • 원격 저장소이기 때문에 개발자는 어디서든지 구성 정보 제어 가능
  • private repository로 관리를 해야하는 것이 중요!

단점

  • Github 저장소에 의존적이어서, SPOF(단일장애지점)이 될 가능성 있음
  • Github에 접속하기 위한 ID, PW 또는 토큰값을 서버에 미리 설정해야 함 (보안)

 

이렇게 결국 Github ID, PW, 토큰값이나 각종 중요한 ID,PW를 미리 설정하거나 Github의 private repository에 저장해야한다는 문제점이 있다. 암호화를 하여 읽을때 해독하는 방법도 제공하지만 나는 이런 중요한 정보들(ID,PW)를 또 다른 외부 저장소인 Vault에 저장하기로 했다.

 

💾 HashiCorp Vault(하시코프 볼트)

  • secrets(시크릿)에 민감한 정보를 안전하게 접근 및 관리 할 수 있는 오픈소스 도구
  • PW, 인증서, API 키 등 접근을 제한하거나 제한하려는 어떤 정보로도 시크릿 정의 가능
  • Spring Cloud Config Server의 설정 저장소로 Git과 Vault 지원
  • 관리자, 다른 Vault 사용자도 내 토큰이 없으면 정보를 읽을 수 없음

Spring Cloud Config Server와 Vault, Github 구조

따라서 볼트에 가장 중요한 정보를 저장하고, 그 후에 Git에 저장하기로 한다.

하지만 나는 가장 중요한 정보에 Github의 ID,PW도 포함시키고 싶다.

따라서 내가 생각하는 구조는 아래와 같다.

 

Spring Cloud Config Server 외부 저장소 구조 설계

Github 뿐만 아니라 DB나 중요한 정보는 전부 Vault에 저장하고 꺼내 쓰는 것으로 한다.

따라서 Config Server는 Vault에 먼저 접속해서 설정정보를 가져와야하므로 Bootstrap 라이브러리를 활용해야 한다.

 

🚀 Bootstrap(부트스트랩)

properties와 yml을 동일하게 여기시면 됩니다.
e.g. application.properties == application.yml
  • 서버 실행 시, application.yml보다 bootstrap.yml이 먼저 로드되게 함
  • Bootstrap Context는 Application Context의 상위 컨텍스트
  • 2021년도 기준으로 Spring Cloud에서는 bootstrap을 자동으로 읽어오는 기능이 없음
    • 따라서 spring-cloud-starter-bootstrap 의존성 추가해야 함
  • bootstrap.yml은 Config Server(구성서버)를 준비하기 위한 것
  • application.yml은 애플리케이션과 관련된 속성을 위한 것

🚀 Spring Cloud Config Server 외부 저장소 설계

Spring Cloud Config Serve 보안 설계

 

🚀 Vault와 Github 연동하고 사용해보기

이 구조를 사용하려면 우선 아래 라이브러리 추가가 필요하다.

implementation 'org.springframework.cloud:spring-cloud-config-server' //구성 서버
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' //부트스트랩
implementation 'org.springframework.cloud:spring-cloud-starter-vault-config' //볼트

우선 볼트 라이브러리를 추가한 것에 의아할 수도 있다.

왜냐하면 Config Server에서 기본적으로 설정 저장소로 지원하기 때문이다.

 

여기서부터는 나의 여러 실험 환경에 의한 개인적인 의견이 포함된다.

처음엔 Config Server와 Bootstrap 의존성만 추가하고 테스트 해보았지만 Vault에서 가져온 값으로 Github에 접속할 수 없었다. 

spring:
  profiles:
    active: git, vault
  cloud:
    config:
      server:
        git:
          uri: file:///path/to/git/repo
          order: 2
        vault:
          host: 127.0.0.1
          port: 8200
          order: 1

이런 식으로 우선순위를 정해보기도 하고, bootstrap.yml에 따로 적어보기도 하는 등 구글과 스택오버플로우 등 여러 방법을 적용해봤지만 절대로 불가능했다.

따라서 Vault에서 가져온 값으로 Github 접속하는 것이 아니라, Vault와 Github를 접속할 수 있는 값을 미리 적는 경우라면 상관이 없었다.

하지만 나는 Vault에서 가져온 값으로 Github에 접속하고 싶었기에 Vault 라이브러리를 추가해보았다.

그리고 성공했다.

 

bootstrap.yml

우선 bootstrap.yml에 vault에 접속하기 위한 설정정보를 적는다.

이 값을 통해서 vault에 접속하고 값을 미리 가져온다.

application.yml

그리고 vault에서 github ID, PW를 가져와서 application.yml에 넣어 접속을 시도하고 가져온다.

config-server 설정정보에서 vault를 적지않아도 되지만 나는 config-server에서도 vault 구성정보를 확인하고 싶었기에 추가했다.

spring cloud config server 확인

이렇게 "localhost:8888/config-service/dev" 를 통해 vault에 있는 값을 최우선적으로 가져오는 것을 알 수 있다.

마지막으로 github에서 application.yml을 가져왔다.

application.yml에서 config-server의 백엔드 구성정보에 vault를 작성하지 않으면 github의 application.yml만 확인할 수 있고, 가져올 수 있다.

 

 

🖥 Vault를 도커로 실행하기

컴퓨터에 볼트를 설치하기 싫으니 도커 컨테이너로 실행하기로 한다.

 

docker run -d -p 8200:8200 --name vault -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' vault:1.13.3
  • VAULT_DEV_ROOT_TOKEN_ID
    • 루트 토큰(root token) ID 설정하는 것
    • 루트 토큰은 볼트 구성을 시작하는 초기 액세스 토큰
  • VAULT_DEV_LISTEN_ADDRESS
    • 개발 서버의 IP주소와 포트 설정
    • 기본값은 0.0.0.0:8200

위 도커 명령어로 vault 1.13.3 버전 이미지를 가져오고 컨테이너로 실행시킨다.

이후 편의성을 위해 볼트 UI를 이용하여 설정하기로 한다.

CLI(명령어)를 선호한다면 그건 다른 쪽에서 알아보자.

application.yml과 bootstrap.yml에서 vault의 토큰값을 넣는 부분이 있는데 여기서 설정한 루트 토큰값을 넣으면 된다. 위 명령어대로라면 "myroot"를 넣으면 된다.

 

Vault UI (볼트 UI) 접속 페이지

"http://0.0.0.0:8200/ui/vault/auth" 주소를 통해 볼트를 접속한다.

토큰값은 도커를 실행했을 때 설정했던 루트 토큰값인 "myroot"를 통해 접속한다.

 

Vault UI 접속 후, 시크릿(secret) 목록들

접속하면 초기 secret들이 있는데 새로 만들기로 한다.

[Enable new engine] 버튼을 누른다.

 

Enable new engine 버튼 클릭 후 설정

새로운 엔진 중에서 범용 KV 를 선택하고

 

enable new engine 시크릿 엔진 데이터 입력

KV 시크릿 엔진 데이터를 입력한다.

우리는 시크릿 이름을 "config-service-secret"으로 설정한다.

 

시크릿

새로운 시크릿 엔진이 만들어졌다면 이제 시크릿을 생성해보자.

[Create secret] 버튼을 누른다.

 

Vault Secret 생성

그럼 이제 시크릿을 생성할 수 있다.

시크릿 이름을 적을 때 "/"를 기준으로 세분화할 수 있다.

"config-service/dev"를 적고, 여기에 저장할 데이터를 입력한다.

우리는 gitId와 gitPw를 적어놓는다.

이후 [Save] 버튼을 누르면 끝난다.

 

새로운 secret 생성

이제 정상적으로 Vault 데이터를 가져오는지 확인해보자.

 

Spring Cloud Config Server 테스트

"localhost:8888/config-service/dev" 주소를 입력해서 가져오는지 확인한다.

아까 저장했던 gitId와 gitPw가 가져와지는 것을 알 수 있고, 이 데이터로 Github에 접속해서 application.yml 구성정보를 가져오는 것도 확인할 수 있다.

 

참고로 Github에서 public repository라면 ID와 PW를 적을 필요 없이 주소(uri)만 적으면 가져올 수 있다. 여기서는 Github의 private repository에 접근하기 위해 ID와 PW를 입력해야하는 것이다.