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= SANserver.<DC>.consul필수- 없으면 권한 상승 공격 (클라이언트가 서버처럼 가입)
- 인증서 SAN — 서버 =
server.<DC>.consul/ 클라이언트 =client.<DC>.consul - 모든 인증서 동일 CA 서명 필수
auto_encrypt= 클라이언트 자동 인증서 수령- ACL 기본 비활성
default_policy— deny (제로 트러스트) / allowdown_policy— extend-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단계 —
keygen→keyring -install→keyring -use→keyring -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 프록시 시작 차이
시리즈 다른 편
- 1편 — Consul 입문 (아키텍처·Raft·Gossip)
- 2편 — 단일 DC 배포 (HCL 구성·5 서버 부트스트랩)
- 3편 — Service Discovery (등록·DNS·헬스 체크)
- 4편 — KV Store (CLI·API·Watch·Template)
- 5편 — 백업·복구 (Snapshot Save/Restore)
- 6편 — Service Mesh (Connect·Envoy·Intentions)
- 7편 — 보안 운영 (현재 글, 시리즈 완결)
공식 문서: Consul Security와 HashiCorp Consul Associate Cert에서 더 깊이.
Consul은 한 번에 정복되는 도구가 아니에요. 매번 새 토폴로지·새 함정과 만나며 평생 다듬어 가는 영역입니다. 시리즈 끝까지 읽어 주셔서 감사합니다. 시험 합격을 응원합니다!