Consul 보안 운영 — TLS·ACL·Gossip 암호화

2026-05-03확률과 통계 마스터 노트

HashiCorp Consul 마스터 노트 시리즈 7편 완결편. TLS 3 검증 파라미터(verify_incoming/outgoing/server_hostname)와 server hostname의 보안 의의, ACL 워크플로우(allow → bootstrap → policy → token → deny), Gossip 암호화 키 생성·로테이션 4단계까지 — 시험 Objective 7·8·9 마무리.

이 글은 HashiCorp Consul 마스터 노트 시리즈의 마지막 편이자 일곱 번째 편입니다. 시험 Objective 7·8·9 — TLS · ACL · Gossip 암호화 세 보안 계층.

여기서 정말 중요한 시험 함정 — Consul은 기본적으로 보안이 활성 안 됨. 설치 직후 모든 통신은 평문. 운영에선 반드시 3계층 모두 활성.

Consul 보안 4계층

계층 도구 보호 대상
Gossip 암호화 대칭 키 (encrypt) 에이전트 간 멤버십·이벤트
TLS / RPC 암호화 TLS 인증서 API·RPC 통신
mTLS 인증서 + Connect 서비스 간 (6편)
ACL 토큰 + 정책 데이터·API 접근 제어

Part 1 — TLS (Objective 7)

핵심 파라미터

tls {
  default {
    ca_file                = "/etc/consul.d/ca.pem"
    cert_file              = "/etc/consul.d/server.pem"
    key_file               = "/etc/consul.d/server-key.pem"
    verify_incoming        = true
    verify_outgoing        = true
    verify_server_hostname = true
  }
}

여기서 정말 중요한 시험 함정 — 세 검증 파라미터의 기본값은 모두 false. 명시 활성 필요.

verify_incoming

verify_incoming = true
  • 모든 수신(인바운드) RPC·HTTPS API에 클라이언트 인증서 요구
  • 적용 — 서버에 들어오는 모든 연결
  • 효과 — 유효한 CA 서명 인증서 없는 클라이언트 차단

verify_outgoing

verify_outgoing = true
  • 모든 발신(아웃바운드) 연결에 TLS 강제
  • 적용 — 클라이언트·서버 모두의 아웃바운드
  • 효과 — 평문 통신 완전 차단

verify_server_hostname

verify_server_hostname = true
  • 서버 인증서에 특정 SAN 형식 요구
  • SAN 형식 — server.<datacenter>.<domain> (예: server.dc1.consul)

여기서 정말 중요한 시험 함정 — verify_server_hostname 없으면 권한 상승 공격:

공격 시나리오:
1. 손상된 클라이언트 노드
2. 공격자가 클라이언트 구성에서 server = true로 변경
3. 적당한 (클라이언트) 인증서로 재시작
4. Raft 클러스터 참여 → 모든 상태 데이터 복제
5. KV·ACL·서비스 카탈로그 탈취

방어:
- verify_server_hostname = true
- 클라이언트 인증서엔 server.<DC>.consul SAN 없음
- Raft 참여 불가

인증서 유형

유형 용도 SAN 요구
CA 다른 인증서 서명 -
서버 서버 노드 server.<DC>.consul 필수
클라이언트 클라이언트 노드 client.<DC>.consul
CLI consul CLI -

인증서 생성

# Consul 내장 CA 사용 (자동으로 올바른 SAN 포함)
consul tls ca create
consul tls cert create -server -dc dc1 -domain consul
consul tls cert create -client -dc dc1 -domain consul
consul tls cert create -cli

단일 CA 원칙

여기서 시험 함정이 하나 있어요. 모든 인증서는 동일한 CA에 서명되어야. 다른 CA 혼용 = 통신 실패.

auto_encrypt — 자동 인증서 배포

# 서버 (클라이언트에 인증서 자동 배포 허용)
auto_encrypt {
  allow_tls = true
}

# 클라이언트 (서버에서 인증서 자동 수령)
auto_encrypt {
  tls = true
}

클라이언트가 클러스터 가입할 때 서버에서 TLS 인증서 자동 수령. 인증서 수동 배포 부담 줄임.

Part 2 — ACL (Objective 8)

ACL 컴포넌트

ACL 시스템
├── Policies   → "무엇을 할 수 있는가"
├── Tokens     → "누가 요청하는가"
├── Roles      → 여러 정책 그룹
└── Service Identities → 서비스 메시용 정책 템플릿

기본 설정

acl {
  enabled                  = true
  default_policy           = "deny"
  down_policy              = "extend-cache"
  enable_token_persistence = true
  tokens {
    agent = "<AGENT_TOKEN_UUID>"
  }
}

여기서 시험 함정이 하나 있어요. ACL 기본 비활성. 명시 활성 필요.

default_policy

의미
"allow" 명시 거부 안 된 모든 접근 허용
"deny" 명시 허용만 (Zero Trust)

down_policy

의미
"allow" ACL 서버 다운 시 모든 허용
"deny" ACL 서버 다운 시 모든 거부
"extend-cache" 캐시 토큰 사용 (권장)

extend-cache 권장 — 리더 장애 시에도 캐시로 운영 지속.

단계적 활성화 워크플로우

여기서 정말 중요한 시험 함정 — 처음부터 default_policy = "deny"로 설정 X. 모든 통신 차단됨.

ACL 활성화 6단계:
1. default_policy = "allow"로 구성 → 재시작
2. consul acl bootstrap → 마스터 토큰 생성
3. 정책(Policy) 생성
4. 각 노드·서비스 토큰 생성·배포
5. 모든 에이전트 agent 토큰 설정 → 재시작
6. default_policy = "deny"로 변경 → 재시작

Bootstrap

consul acl bootstrap
# AccessorID:    a4baeae6-cdf9-...
# SecretID:      <UUID>
# Description:   Bootstrap Token (Global Management)

여기서 정말 중요한 시험 함정 — bootstrap은 한 번만 실행 가능. 두 번째 시도 → Permission denied (이미 실행됐다는 의미). 이 마스터 토큰은 절대 분실 X.

Policy 생성

# /tmp/web-policy.hcl
service "web" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}
node_prefix "" {
  policy = "read"
}
consul acl policy create \
  -name "web-service" \
  -description "Allow web service registration" \
  -rules @/tmp/web-policy.hcl

Token 생성

consul acl token create \
  -description "Web service token" \
  -policy-name "web-service"
# 발급된 토큰을 환경 변수로
export CONSUL_HTTP_TOKEN=<UUID>

# 또는 CLI 인자
consul kv put -token=<UUID> myapp/key value

Role

여러 정책을 그룹화.

consul acl role create \
  -name "developer" \
  -policy-name "kv-read" \
  -policy-name "service-discovery"

Service Identities

서비스 메시 자동화. 서비스 이름 기반 정책 자동 생성.

# 토큰 생성 시
service_identity "web" {
  datacenters = ["dc1"]
}

자동으로 web 서비스에 필요한 정책 부여.

정책 규칙

# KV
key_prefix "myapp/" {
  policy = "write"
}
key_prefix "" {
  policy = "read"
}

# 서비스
service_prefix "" {
  policy = "read"
}
service "web" {
  policy = "write"
}

# 노드
node_prefix "" {
  policy = "read"
}

# Operator (Raft 등 운영)
operator = "read"

# ACL (정책·토큰 관리)
acl = "write"

policy 값 — read / write / deny / list (KV 전용).

Part 3 — Gossip 암호화 (Objective 9)

키 생성

consul keygen
# wxX/4ZJfY3jE...   (32바이트 Base64)

구성에 추가

encrypt = "wxX/4ZJfY3jE..."

모든 노드(서버 + 클라이언트)에 동일 키 설정 필수.

키 로테이션 4단계

여기서 정말 중요한 시험 함정 — 키 로테이션 순서가 시험에 자주:

1. 새 키 생성
   NEW_KEY=$(consul keygen)

2. 모든 노드에 새 키 설치 (사용은 X, 받기만 가능)
   consul keyring -install "$NEW_KEY"

3. 새 키를 활성 키로 전환
   consul keyring -use "$NEW_KEY"

4. 모든 노드에서 옛 키 제거
   consul keyring -remove "$OLD_KEY"

키링 명령

# 현재 키링 상태
consul keyring -list

# 신규 키 설치 (받기만, 보내기 X)
consul keyring -install "<NEW_KEY>"

# 활성 키 변경 (보내기 + 받기)
consul keyring -use "<NEW_KEY>"

# 키 제거
consul keyring -remove "<OLD_KEY>"

여기서 정말 중요한 시험 함정 — -install은 받기만, -use는 활성 키 전환. 순서 반대로 = 일부 노드 통신 끊김.

LAN vs WAN 키

# LAN (단일 DC)
consul keyring -list -relay-factor=0

# WAN (다중 DC, 서버만)
consul keyring -list -wan

각 풀별로 별도 키링.

자동 암호화 — auto_encrypt

TLS와 다르게 Gossip 키는 수동 관리.

토큰 분실 복구

bootstrap 토큰 분실 시:

# 1. 클러스터 정지
sudo systemctl stop consul

# 2. ACL 디렉토리 삭제 (마지막 수단)
sudo rm -rf /opt/consul/raft

# 3. 백업 스냅샷 복원 (5편 참조)
consul snapshot restore backup.snap

# 4. 새 bootstrap (-reset 옵션, 60초 안에)
consul acl bootstrap-reset

보안 운영 체크리스트

신규 클러스터

  • Gossip 키 (encrypt) 모든 노드에 설정
  • CA·서버·클라이언트 인증서 발급
  • verify_incoming/outgoing/server_hostname = true
  • auto_encrypt 활성 (선택)
  • default_policy = "allow"로 시작
  • consul acl bootstrap → 마스터 토큰 안전 보관
  • 정책·토큰 생성·배포
  • default_policy = "deny"로 전환
  • Connect 활성·Intentions 정책

정기 운영

  • Gossip 키 6개월·1년 주기 로테이션
  • TLS 인증서 만료 모니터링·갱신
  • 토큰 회전 (개발자 퇴사 등)
  • 사용 안 하는 토큰 정리
  • ACL 정책 정기 검토

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 7편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • Consul 기본 보안 X — 평문 통신, 명시 활성 필요
  • 보안 4계층 — Gossip / TLS / mTLS (Connect) / ACL
  • TLS 3 검증 — verify_incoming / verify_outgoing / verify_server_hostname
  • 모두 기본 false
  • verify_incoming = 인바운드 클라이언트 인증서
  • verify_outgoing = 아웃바운드 TLS 강제
  • verify_server_hostname = SAN server.<DC>.consul 필수
  • 없으면 권한 상승 공격 (클라이언트가 서버처럼 가입)
  • 인증서 SAN — 서버 = server.<DC>.consul / 클라이언트 = client.<DC>.consul
  • 모든 인증서 동일 CA 서명 필수
  • auto_encrypt = 클라이언트 자동 인증서 수령
  • ACL 기본 비활성
  • default_policydeny (제로 트러스트) / allow
  • down_policyextend-cache 권장
  • ACL 활성화 6단계 — allow 시작 → bootstrap → policy → token → 재시작 → deny 전환
  • 처음부터 deny로 = 모든 통신 차단
  • consul acl bootstrap = 한 번만, 마스터 토큰 생성
  • 토큰 분실 = bootstrap-reset (60초 안에)
  • 정책 규칙 — key_prefix / service_prefix / node_prefix / operator / acl
  • policy 값 — read / write / deny / list (KV)
  • Service Identities = 서비스 이름 기반 정책 자동
  • Gossip 키 로테이션 4단계keygenkeyring -installkeyring -usekeyring -remove
  • -install = 받기만 / -use = 활성 전환
  • 모든 노드 동일 키
  • LAN / WAN 별도 키링

시리즈 마무리 — 7편 전체 요약

여기까지 오신 분이 있다면 진심으로 축하드립니다. 시리즈 전체에서 잡아 둔 핵심을 마지막으로 정리합니다.

  • 1편 — 입문 — 4기능, Server/Client/Dev, Raft, Gossip, 핵심 포트 7개
  • 2편 — 배포 — HCL 구성, 5 서버 부트스트랩, retry_join, systemd
  • 3편 — Service Discovery — 등록 2방법, DNS 8600, 헬스 체크 7종
  • 4편 — KV Store — CLI/API/UI, prefix, CAS, watch, consul-template
  • 5편 — 백업·복구snapshot save/restore, Cron 자동, restore 주의
  • 6편 — Service Mesh — Connect 활성, 사이드카, mTLS, Intentions, Envoy
  • 7편 — 보안 (현재 글) — TLS 3 검증, ACL 6단계, Gossip 키 로테이션 4단계

HashiCorp Certified Consul Associate 시험 — 57문항·60분·웹캠 모니터링 원격. 9 Objective를 이 7편이 모두 다룹니다.

응시 전 마지막 점검:

  • ✅ Hands-on 실습 (콘솔·CLI 직접)
  • ✅ 핵심 포트 7개 외우기
  • ✅ Raft 쿼럼 계산 ((N+1)/2)
  • ✅ TLS 3 검증 파라미터 차이
  • ✅ ACL 6단계 활성화 순서
  • ✅ Gossip 키 로테이션 4단계 순서
  • ✅ Connect 등록 vs 프록시 시작 차이

시리즈 다른 편

공식 문서: Consul SecurityHashiCorp Consul Associate Cert에서 더 깊이.

Consul은 한 번에 정복되는 도구가 아니에요. 매번 새 토폴로지·새 함정과 만나며 평생 다듬어 가는 영역입니다. 시리즈 끝까지 읽어 주셔서 감사합니다. 시험 합격을 응원합니다!

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!