Vault Cluster 구축기(feat. Terraform)

Asher·2025년 6월 28일
post-thumbnail

0. 도입

올해 신규 보안 프로젝트의 일환으로 Vault Cluster를 구축해 보았습니다.
기술 관련 오픈채팅방을 종종 살펴보면서 Vault를 사용하는 실무자가 의외로 많다고 생각했었는데 이번 프로젝트를 통해 Vault에 대한 실질적인 지식을 쌓을 수 있는 좋은 기회가 되었습니다.

Why? 왜 Vault를 사용했는가?
많은 실무자들이 AWS를 활용하면서 동시에 AWS CLI도 같이 사용합니다. 저 역시 실무에서 AWS CLI를 사용하는데, 이때 /root/.aws 디렉터리에 AWS Secret Key가 평문으로 저장되어 있다는 점이 보안상 큰 취약점이라고 판단했습니다. 그래서 Vault를 활용하면 Secret Key를 동적으로 발급받을 수 있으며 이 키는 일정 시간이 지나면 만료가 되어 보안 수준을 한 층 높일 수 있다고 생각했습니다.

1. Vault란?

  • Vault는 UI, CLI 또는 HTTP API를 사용하여 애플리케이션이나 인프라에서 사용되는 민감 정보(Secrets) ex) API 키, 비밀번호, 인증서, 데이터베이스 자격 증명 등을 안전하게 저장하고 제어할 수 있게 도와주는 비밀 관리 시스템(Secret Management System) 입니다.

  • Vault의 기능?

    기능설명
    Secret 저장민감한 정보를 중앙에서 안전하게 저장하고 액세스를 제어할 수 있음
    동적 자격증명(Dynamic Secrets)요청 시마다 짧은 TTL(Time-To-Live)을 가진 임시 자격증명을 생성
    예: DB 계정, AWS IAM credentials 등
    암호화 서비스(Encryption as a Service)Vault를 통해 데이터를 직접 암복호화 할 수 있음 (앱에 키를 저장할 필요 없음)
    정책 기반 접근 제어사용자/서비스의 권한을 세밀하게 제어 가능 (ACL 정책)
    감사 로그(Audit Logs)누가 어떤 Secret에 접근했는지 기록을 남겨 보안 감사에 유용
    멀티 백엔드 저장소 지원AWS S3, 파일 시스템, Consul, PostgreSQL 등 다양한 스토리지 백엔드를 사용 가능
  • Vault의 장점?
    • 민감한 정보들이 소스코드, 환경변수, 파일 등에 직접 노출되지 않음
    • 자격증명이 자동으로 만료되고 폐기되므로, 유출 시 피해를 최소화할 수 있음
    • 자격 증명별 권한과 경로를 매우 세밀하게 정의 가능
    • 감사로그(Audit Logs)를 지원하여 비밀에 접근하는지를 기록 가능

2. Vault Cluster 구성

  • Vault Cluster의 필요성

    • HA 구성 가능 → 하나의 서비스가 중단 되더라도 장애 X (무중단 운영 가능)
    • Auto Failover → 운영자가 개입 하지 않고도 follwer Node가 Leader Node로 자동 승격
    • 데이터 내구성 → 저장된 Secrets 및 정보가 사라져도 복제된 다른 Node에서 정보 받아옴
  • Vault Cluster 구성 요소?

    • 최소 3EA Node로 구성 (1개의 Active Node, 2개의 Stanby Node)
    • Active Node: 클러스터에서 실제로 요청을 처리하는 주 노드입니다. 이 노드는 Vault의 모든 API 요청을 처리하며, 읽기 및 쓰기 작업을 수행할 가능
    • Standby Node: 주로 Active Node의 상태를 복제하고 있습니다. Standby Node는 요청을 처리하지 않으며, Active Node에 장애가 발생할 경우 자동으로 Active Node 역할을 맡는다.
  • Raft Storage 구성도

    암호화된 데이터를 보관하는 여러가지의 Storage 중 HA를 지원하는 Raft Storage를 선택했습니다.


    Raft Storage는 Raft Consensus 알고리즘 사용하여 Leader 선출하는데 자세한 내용은 Google에... 질문하시면 더 자세한 정보를 얻을 수 있습니다!

3. Vault Cluster 구축

3.1 Vault 설치

  • GPG, wget 설치
    sudo apt update && sudo apt install gpg wget
  • Keyring 다운로드
    wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
  • Keyring 확인
    gpg --no-default-keyring --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg --fingerprint
  • Vault 설치
    sudo apt update && sudo apt install vault
  • Vault Version 확인
    vault -version
  • Vault 시작
    systemctl enable vault.service
    systemctl start vault.service

같은 방식으로 3EA 서버에 Vault 세팅 진행하면 됩니다

3.2 Vault Cluster 구성

  • 데이터 폴더 생성 - Vault 1, Vault 2, Vault 3 서버
    mkdir -p /data/vault
  • 인증서 폴더 생성 - Vault 1, Vault 2, Vault 3 서버
    mkdir -p /data/vault/tls
  • Vault User에게 소유권 부여 - Vault1, Vault2, Vault3
    chown -R vault:vault /data/vault
  • 인증서 구성 파일 옮기기
    cd /data/vault/tls
    • cert.pem
    • chain.pem
    • fullchain.pem
    • privkey.pem
  • Vault 환경 구성 진행

    vi /etc/vault.d/vault.hcl
    • vault.hcl 파일 수정 - Vault1, Vault2, Vault3
    # Copyright (c) HashiCorp, Inc.
    # SPDX-License-Identifier: BUSL-1.1
    
    # Full configuration options can be found at https://developer.hashicorp.com/vault/docs/configuration
    
    ui = true  # UI 모드 Enable
    
    #mlock = true
    #disable_mlock = true
    
    #storage "file" {
    #  path = "/opt/vault/data"
    #}
    
    #storage "consul" {
    #  address = "127.0.0.1:8500"
    #  path    = "vault"
    #}
    
    # HTTP listener
    #listener "tcp" {
    #  address = "127.0.0.1:8200"
    #  tls_disable = 1
    #}
    
    cluster_addr = "https://sample1.domain.com:8201"
    api_addr = "https://sample1.domain.com:8200"
    # 메모리 부족 오류 방지
    disable_mlock = true
    
    # HTTPS listener
    
    # HTTPS 구성
    listener "tcp" {
      address = "0.0.0.0:8200"
      cluster_address = "0.0.0.0:8201"
      tls_cert_file      = "/data/vault/tls/fullchain.pem"
      tls_key_file       = "/data/vault/tls/privkey.pem"
      tls_client_ca_file = "/data/vault/tls/chain.pem"
      tls_disable = 0
    }
    
    # Storage 구성 각 **node_id는 달라야함!!**
    storage "raft" {
      path = "/data/vault"
      node_id = "raft_node_1" 
    
      retry_join {
        leader_api_addr = "https://sample1.domain.com:8200"
        leader_tls_servername   = "sample1.domain.com"
        leader_ca_cert_file     = "/data/vault/tls/chain.pem"
        leader_client_cert_file = "/data/vault/tls/fullchain.pem"
        leader_client_key_file  = "/data/vault/tls/privkey.pem"
      }
      retry_join {
        leader_api_addr = "https://sample2.domain.com"
        leader_tls_servername   = "sample2.domain.com"
        leader_ca_cert_file     = "/data/vault/tls/chain.pem"
        leader_client_cert_file = "/data/vault/tls/fullchain.pem"
        leader_client_key_file  = "/data/vault/tls/privkey.pem"
      }
      retry_join {
        leader_api_addr = "https://sample3.domain.com:8200"
        leader_tls_servername   = "sample3.domain.com"
        leader_ca_cert_file     = "/data/vault/tls/chain.pem"
        leader_client_cert_file = "/data/vault/tls/fullchain.pem"
        leader_client_key_file  = "/data/vault/tls/privkey.pem"
      }
    }
    # Enterprise license_path
    # This will be required for enterprise as of v1.8
    #license_path = "/etc/vault.d/vault.hclic"
    
    # Example AWS KMS auto unseal
    #seal "awskms" {
    #  region = "us-east-1"
    #  kms_key_id = "REPLACE-ME"
    #}
    
    # Example HSM auto unseal
    #seal "pkcs11" {
    #  lib            = "/usr/vault/lib/libCryptoki2_64.so"
    #  slot           = "0"
    #  pin            = "AAAA-BBBB-CCCC-DDDD"
    #  key_label      = "vault-hsm-key"
    #  hmac_key_label = "vault-hsm-hmac-key"
    #}

실제 상용 서버에 구성하기 때문에 보안향상을 위해 TLS을 사용하여 구성 진행하였습니다. 또한 각 Vault 서버별로 node ID를 다르게 구성 하셔야 합니다.

  • Vault 데몬 재시작 - Vault1, Vault2, Vault3
    vi /etc/profile
    export VAULT_ADDR="https://sample1.domain.com:8200" or sample2. sample3(각 서버에 맞게)
    source /etc/profile
  • Vault 초기화 - Vault1(Leader Node)
    vault operator init

초기화를 진행하게 되면, Unseal Key가 나오는데 5개 중 3개를 입력해야지 Seal이 해제 됩니다.

  • Leader Node에서 Cluster 적용 확인
    vault operator raft list-peers

4. Terraform과 연동

Vault Cluster 활용법으로 Terraform과 연동 진행해 보았습니다.
앞서 언급한것처럼 기존에는 평문으로 AWS Token을 저장하여 Terraform을 사용하였는데, 보안 향상을 위해 Terraform Provider에서 Token을 주입해 AWS 리소스들을 다룰 수 있습니다.

Terraform에서는 임시 AWS Secret을 동적으로 provider에 주입하여 사용!
(단, Secret인증은 30분간 유효)
1. vault_token으로 Vault에 연결 (provider "vault")
2. Vault에서 AWS 자격증명 가져오기 (data "vault_aws_access_credentials")
3. AWS provider에 동적으로 그 자격증명 주입
4. 이제 Terraform이 AWS 자원 생성/조회 가능

4.1 Terraform 연동을 위한 구성 GSLB + TLS

  • GSLB 구성 이유?
    • Terraform은 Vault 클러스터의 모든 노드 주소를 인식하지 못하므로, 장애가 발생한 노드로 요청이 전달되면 Vault로부터 응답을 받지 못할 수 있다.
    • 이러한 문제를 방지하기 위해, GSLB의 헬스 체크 기능을 통해 장애 노드를 자동으로 감지하고 정상 노드로 트래픽을 우회시킨다
  • GSLB 구성이 안 되어 있을 경우

    Vault 2번으로 Terraform은 주소를 알고 있지만 장애가 발생하여 HA 구성을 통해 Vault 1번으로 Active Node로 전환 되었을 때 Terraform과 Vault Cluster는 통신이 불가합니다.

  • GSLB 구성이 되어 있을 경우

    GSLB를 통해 어디로 통신이 되든 Stanby Node는 Active Node로 요청을 Redirect 하기 때문에, 만약 Vault 2번이 장애가 나도 GSLB는 장애가 난 Node에게는 요청을 보내지 않기 때문에 서로 통신이 가능합니다.

    단) GSLB는 sample.domain.com으로 요청을 받아야 합니다.
    각 Node들은 고유의 도메인을 가지고 있으며(sample1, sample2, sample3) sample.domain.com 으로 요청을 받아 요청을 Balancing 해주게 됩니다.

4.2 Terraform 서버 수정

  • Vault Token 저장
    vi /etc/profile
    export TF_VAR_vault_token="{Vault Token}source /etc/profile
  • provider.tf 교체 및 재작성
    • vi provider.tf
variable "vault_token" {
  type = string
  sensitive = true # 토큰 값을 보호하기 위해 sensitive로 설정
}

provider "vault" {
  address = "https://sample.domain.com:8200" # Vault 서버의 주소
  token   = sensitive(var.vault_token)          # Vault Token
}

data "vault_aws_access_credentials" "example" {
  backend = "aws-test" # 원하는 secret 설정
  role    = "terraform"  # Vault에서 설정한 역할 이름
}

provider "aws" {
  access_key = data.vault_aws_access_credentials.example.access_key
  secret_key = data.vault_aws_access_credentials.example.secret_key
  region     = "ap-northeast-2"
}
  • Terraform - Vault 연동 테스트
    terraform init
    terraform plan

보안을 위해 몇가지 빠진 부분이 있지만, Vault Cluster 구축 및 Terraform과 연동을 위한 분들께 도움이 되었으면 좋겠습니다..!

참고문헌

Install Vault | Vault | HashiCorp Developer
Vault with integrated storage deployment guide | Vault | HashiCorp Developer
Vault with integrated storage deployment guide | Vault | HashiCorp Developer
Vault with integrated storage reference architecture | Vault | HashiCorp Developer

profile
System Engineer의 발전기록

0개의 댓글