개발을 하다 보면 API 키, 데이터베이스 비밀번호, 인증서 등 민감한 정보를 안전하게 관리해야 할 필요성을 느낄 때가 있습니다.

오래전에 스프링 마이크로서비스 코딩 공작소 도서를 스터디하면서 알게 된 HashiCorp Vault를 실습 해보겠습니다.

HashiCorp Vault란?

HashiCorp Vault는 비밀 정보(secrets)를 안전하게 저장하고 접근을 제어하는 오픈소스 도구입니다.

API 키, 비밀번호, 인증서, 토큰 등의 민감한 정보를 중앙에서 관리할 수 있으며, 동적으로 비밀 정보를 생성하거나 암호화 서비스를 제공하는 등 다양한 기능을 제공합니다.

Vault의 주요 특징

  • 비밀 정보 중앙 관리: 모든 민감한 정보를 한 곳에서 안전하게 관리
  • 동적 비밀 정보 생성: 필요할 때마다 임시 자격증명을 생성하여 보안 강화
  • 데이터 암호화: 저장 데이터와 전송 데이터 모두 암호화
  • 접근 제어: 세밀한 권한 관리 및 감사 로그
  • 다양한 인증 방법: Token, LDAP, AWS, Kubernetes 등 다양한 인증 백엔드 지원

최근 마이크로서비스 아키텍처와 클라우드 네이티브 환경이 확산되면서, 분산된 시스템에서 비밀 정보를 안전하게 관리하는 것이 더욱 중요해졌습니다. Vault는 이러한 요구사항을 충족시키는 강력한 솔루션입니다.

그렇지만 본인의 서비스에 맞게 아키텍처를 선택하고, 기술 또한 개발 기간과 필요 여부로 적절히 선택하는게 좋습니다. 오히려 유지보수의 어려움과 복잡성만 높일 수도 있으니까요.

이번 글에서는 Vault를 Docker Compose로 설치한 후 초기화하고 시크릿을 생성하는 과정을 알아보겠습니다.

도커로 진행하기 때문에 딱히 운영체제(Window, Mac)는 고민할 필요가 없습니다.

Docker로 Vault 설치하기

docker-compose를 이용하여 Vault 서버를 생성합니다.

1. Docker Compose 파일 작성

docker-compose.yml 파일을 생성합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '3.8'

services:
  vault:
    image: hashicorp/vault:1.20
    container_name: vault
    ports:
      - '8200:8200'
    cap_add:
      - IPC_LOCK
    volumes:
      - ./config:/vault/config:ro # 설정 파일
      - ./file:/vault/file # 데이터 저장소
      - ./logs:/vault/logs # 로그 파일
    environment:
      VAULT_ADDR: http://0.0.0.0:8200
      VAULT_LOG_LEVEL: info
    command: ['vault', 'server', '-config=/vault/config']
    restart: unless-stopped
    healthcheck:
      test: ['CMD', 'vault', 'status']
      interval: 10s
      timeout: 3s
      retries: 3

2. Vault 설정 파일 작성

docker-compose.yml 파일과 동일한 디렉토리에 config 폴더를 생성합니다.

config/vault.hcl 파일을 생성합니다. 아래는 해당 파일 내용입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# UI 웹 인터페이스 활성화
ui = true

# 메모리 잠금 비활성화 (Docker 환경에서 권장)
disable_mlock = true

# 스토리지 백엔드: 파일 시스템 사용
storage "file" {
  path = "/vault/file"
}

# 네트워크 리스너: HTTP 연결 설정
listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = 1
}

# API 주소
api_addr = "http://0.0.0.0:8200"

# 토큰/시크릿 유효 기간
max_lease_ttl = "10h"
default_lease_ttl = "10h"

경고

위 설정은 개발 환경용입니다. 운영 환경에서는 TLS를 활성화하고 적절한 보안 설정을 적용해야 합니다.

3. Vault 컨테이너 실행

1
docker-compose up -d

컨테이너가 정상적으로 실행되면 브라우저에서 http://localhost:8200로 접속하여 Vault UI를 확인할 수 있습니다.

Vault UI 초기 화면

Vault 초기화 및 설정

1. Vault 초기화 (Operator Init)

Vault를 처음 실행하면 초기화 과정이 필요합니다. 초기화 시 아래와 같이 Unseal Key와 Initial Root Token을 발급 받습니다.

  • Unseal Keys: Vault를 unsealing하는 데 사용되는 키
  • Initial Root Token: Vault에 접근할 수 있는 최초 루트 토큰

아래와 같이 입력하면 도커로 실행된 컨테이너에 접속하여 vault의 unseal키와 Root 토큰을 발급 받을 수 있습니다.

1
docker exec vault vault operator init -key-shares=5 -key-threshold=3 | tee vault-keys.txt

초기화가 완료되면 5개의 Unseal Key와 1개의 Root Token이 생성됩니다.

1
2
3
4
5
6
7
Unseal Key 1: ********************************************
Unseal Key 2: ********************************************
Unseal Key 3: ********************************************
Unseal Key 4: ********************************************
Unseal Key 5: ********************************************

Initial Root Token: hvs.**********************************

알림

해당 값은 매우 중요하므로 안전한 곳에 보관해야 합니다.
분실 시 Vault에 접근할 수 없게 됩니다.

2. Vault Unseal 하기

Vault는 보안을 위해 시작할 때마다 Sealed(봉인) 상태로 시작됩니다. Vault를 사용하려면 Unseal 과정을 거쳐야 합니다.

위 설정에서는 5개의 키 중 최소 3개의 키를 입력해야 Unseal이 완료됩니다. 이는 샤미르의 비밀 공유(Shamir’s Secret Sharing, SSS) 알고리즘을 기반으로 하며, 하나의 비밀을 여러 조각으로 나누어 분배하는 암호화 방식입니다.

여러 사람이 키를 나눠 가지고 있어도 임계값(threshold) 이상이 모여야만 Vault를 열 수 있도록 보안성을 강화한 것입니다.

Vault Unseal 과정

위에서 발급 받은 Unseal Key 중 아무거나 3개를 순차적으로 입력하면 됩니다.

3. Vault 로그인

Unseal 후 Root Token으로 로그인합니다.

Vault Login

웹 UI에서 Method를 “Token"으로 선택하고 Initial Root Token을 입력합니다.

Vault Login

그럼 위와 같이 메인화면에 접근할 수 있습니다.

웹 UI에서 시크릿 관리하기

Vault에 로그인하면 웹 UI를 통해 비밀 정보를 저장하고 관리할 수 있습니다.

1. Secret Engine 확인

로그인 후 좌측 메뉴에서 “Secrets"를 선택하면 사용 가능한 Secret Engine 목록을 볼 수 있습니다.

기본적으로 secret/ 경로에 KV(Key-Value) v2 엔진이 활성화되어 있습니다.

Vault Secrets 메뉴

2. 시크릿 생성하기

  1. secret/ 경로를 클릭합니다.
  2. 우측 상단의 “Create secret” 버튼을 클릭합니다.
  3. Path에 시크릿의 경로를 입력합니다. (예: database/config)
  4. Key-Value 쌍으로 비밀 정보를 입력합니다.
    • Key: username, Value: admin
    • Key: password, Value: mySecretPassword123
    • Key: host, Value: localhost
    • Key: port, Value: 5432
  5. “Save” 버튼을 클릭합니다.

Vault Secret 생성

image

image

3. 시크릿 조회 및 관리

생성한 시크릿을 클릭하면 저장된 정보를 확인할 수 있습니다. 각 값 옆의 눈 아이콘을 클릭하면 실제 값이 표시됩니다.

시크릿을 수정하거나 삭제할 수도 있으며, KV v2는 버전 관리를 지원하므로 이전 버전의 데이터도 확인할 수 있습니다.

image

4. Postman으로 시크릿 조회하기

스프링 클라우드를 이용해도 시크릿에 접근할 수 있지만, 간단하게 Postman으로 조회하는 방법을 알아보겠습니다.

아래와 같이 시크릿을 만든 경우 API Endpoint 경로를 웹 사이트에서 확인할 수 있으며, Postman으로 조회도 할 수 잇습니다.

경고

Root Token을 직접 사용하는 것은 보안상 좋지 않습니다.

운영 환경에서는 반드시 AppRole, AWS IAM, Kubernetes Service Account 등의 인증 방법을 사용하고, Policy를 통해 최소 권한 원칙을 적용해야 합니다.

image

image

이번 글에서는 Docker를 이용하여 HashiCorp Vault를 설치하고 기본적인 키를 만들어보고 실제로 값을 읽어오는 것을 해봤습니다.

아무래도 규모가 큰 여러 백엔드 서비스에서 비밀 정보들을 Vault로 관리하면 어쩌면 좋을수.. 있을 것 같네요.