docs(cloudflare-vault): 문서 전면 개선 (68→540줄)

- 아키텍처 다이어그램 추가
- Vault 초기 설정 (KV 시크릿 엔진, 정책, AppRole)
- Cloudflare API Token 생성 가이드
- CLI 사용법 및 자동화 스크립트 (Fish, Bash)
- Terraform 통합 예제
- CI/CD 통합 (GitHub Actions, GitLab CI)
- 문제 해결 가이드
- 보안 체크리스트

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-16 00:51:47 +09:00
parent 76f8f421af
commit e0b2a22575

View File

@@ -1,69 +1,540 @@
# Cloudflare Vault 통합 가이드 # Cloudflare + HashiCorp Vault 통합 가이드
## 저장 방식 권장사항 > Cloudflare API 크레덴셜을 Vault에서 안전하게 관리하는 완벽 가이드
## 목차
1. [개요](#개요)
2. [아키텍처](#아키텍처)
3. [Vault 초기 설정](#vault-초기-설정)
4. [Cloudflare API Token 생성](#cloudflare-api-token-생성)
5. [Vault에 크레덴셜 저장](#vault에-크레덴셜-저장)
6. [CLI 사용법](#cli-사용법)
7. [자동화 스크립트](#자동화-스크립트)
8. [Terraform 통합](#terraform-통합)
9. [CI/CD 통합](#cicd-통합)
10. [문제 해결](#문제-해결)
---
## 개요
### 왜 Vault를 사용하는가?
| 문제 | Vault 해결책 |
|------|-------------|
| 크레덴셜 하드코딩 | 중앙 집중식 시크릿 관리 |
| 평문 저장 | 암호화된 저장소 |
| 무제한 유효기간 | 동적 시크릿, TTL 설정 |
| 감사 불가 | 모든 접근 로깅 |
| 권한 관리 어려움 | 세분화된 ACL 정책 |
### 지원하는 Cloudflare 크레덴셜
| 유형 | 용도 | 권장 |
|------|------|------|
| **API Token** | 특정 권한만 부여 | ✅ 권장 |
| **Global API Key** | 전체 권한 | ⚠️ 레거시 |
| **Tunnel Credentials** | cloudflared 터널 | ✅ 필수 |
| **Origin CA Key** | 오리진 인증서 | 필요시 |
---
## 아키텍처
```
┌─────────────────────────────────────────────────────────────┐
│ HashiCorp Vault │
│ (https://vault.anvil.it.com) │
├─────────────────────────────────────────────────────────────┤
│ secret/cloudflare/ │
│ ├── tokens/ │
│ │ ├── dns-edit # DNS 편집용 토큰 │
│ │ ├── zone-read # Zone 읽기 전용 │
│ │ └── workers-deploy # Workers 배포용 │
│ ├── tunnels/ │
│ │ ├── production # 프로덕션 터널 │
│ │ └── staging # 스테이징 터널 │
│ └── global/ # Global API Key (레거시) │
└─────────────────────────────────────────────────────────────┘
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Terraform │ │ n8n │ │ CI/CD │
│ │ │ Workflows │ │ Pipeline │
└───────────┘ └───────────┘ └───────────┘
```
---
## Vault 초기 설정
### 1. Vault 로그인
### 1. **API Token 방식 (권장)**
```bash ```bash
# Vault에 저장 # 환경변수 설정
vault kv put secret/cloudflare/tokens \ export VAULT_ADDR="https://vault.anvil.it.com"
api_token="your-api-token" \
# 토큰 로그인
vault login
# 또는 토큰 직접 지정
vault login hvs.xxxxxxxxxxxxx
```
### 2. KV Secrets Engine 활성화
```bash
# KV v2 시크릿 엔진 활성화 (이미 있으면 스킵)
vault secrets enable -path=secret kv-v2
# 확인
vault secrets list
```
### 3. Cloudflare 정책 생성
```bash
# 정책 파일 생성
cat > cloudflare-policy.hcl << 'EOF'
# Cloudflare 토큰 읽기 권한
path "secret/data/cloudflare/*" {
capabilities = ["read", "list"]
}
# 토큰 메타데이터 읽기
path "secret/metadata/cloudflare/*" {
capabilities = ["read", "list"]
}
EOF
# 정책 적용
vault policy write cloudflare-read cloudflare-policy.hcl
# 정책 확인
vault policy read cloudflare-read
```
### 4. AppRole 설정 (자동화용)
```bash
# AppRole 활성화
vault auth enable approle
# Role 생성
vault write auth/approle/role/cloudflare-automation \
token_policies="cloudflare-read" \
token_ttl=1h \
token_max_ttl=4h \
secret_id_ttl=24h
# Role ID 확인
vault read auth/approle/role/cloudflare-automation/role-id
# Secret ID 생성
vault write -f auth/approle/role/cloudflare-automation/secret-id
```
---
## Cloudflare API Token 생성
### Cloudflare 대시보드에서 생성
1. https://dash.cloudflare.com/profile/api-tokens 접속
2. **Create Token** 클릭
3. 템플릿 선택 또는 **Custom token** 생성
### 권장 토큰 템플릿
#### DNS 편집용 토큰
| 권한 | 리소스 |
|------|--------|
| Zone - DNS - Edit | 특정 Zone 또는 All zones |
| Zone - Zone - Read | 특정 Zone 또는 All zones |
#### Workers 배포용 토큰
| 권한 | 리소스 |
|------|--------|
| Account - Workers Scripts - Edit | 계정 |
| Account - Workers KV Storage - Edit | 계정 |
| Account - Workers Routes - Edit | 계정 |
#### Zone 읽기 전용 토큰
| 권한 | 리소스 |
|------|--------|
| Zone - Zone - Read | All zones |
| Zone - DNS - Read | All zones |
| Zone - Analytics - Read | All zones |
### API 토큰 테스트
```bash
# 토큰 유효성 검증
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer YOUR_API_TOKEN"
# 성공 응답
{
"result": { "status": "active" },
"success": true
}
```
---
## Vault에 크레덴셜 저장
### 1. API Token 저장 (권장)
```bash
# DNS 편집용 토큰 저장
vault kv put secret/cloudflare/tokens/dns-edit \
api_token="your-dns-edit-token-here" \
account_id="your-account-id" \
description="DNS record management"
# Workers 배포용 토큰 저장
vault kv put secret/cloudflare/tokens/workers-deploy \
api_token="your-workers-token-here" \
account_id="your-account-id" \
description="Workers deployment"
# 확인
vault kv get secret/cloudflare/tokens/dns-edit
```
### 2. Global API Key 저장 (레거시)
```bash
# Global API Key 저장 (권장하지 않음)
vault kv put secret/cloudflare/global \
email="your-email@example.com" \
api_key="your-global-api-key" \
account_id="your-account-id" account_id="your-account-id"
# 사용
export CLOUDFLARE_API_TOKEN=$(vault kv get -field=api_token secret/cloudflare/tokens)
``` ```
### 2. **Global API Key 방식 (현재)** ### 3. Tunnel 크레덴셜 저장
```bash
# 현재 Vault 구조
secret/cloudflare/
├── email
└── api_key
# 사용
export CF_API_EMAIL=$(vault kv get -field=email secret/cloudflare)
export CF_API_KEY=$(vault kv get -field=api_key secret/cloudflare)
```
### 3. **Tunnel 별 크레덴셜**
```bash ```bash
# Vault에 터널별로 저장 # cloudflared tunnel 생성 시 credentials.json 내용 저장
vault kv put secret/cloudflare/tunnels/production \ vault kv put secret/cloudflare/tunnels/production \
tunnel_id="uuid" \ tunnel_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
tunnel_secret="base64-secret" \ account_tag="your-account-tag" \
account_id="account-id" tunnel_secret="base64-encoded-secret"
# 또는 JSON 파일 전체 저장
vault kv put secret/cloudflare/tunnels/production \
credentials="$(cat ~/.cloudflared/xxxxxxxx.json | base64)"
```
### 4. 시크릿 버전 관리
```bash
# 시크릿 버전 목록
vault kv metadata get secret/cloudflare/tokens/dns-edit
# 특정 버전 읽기
vault kv get -version=2 secret/cloudflare/tokens/dns-edit
# 시크릿 삭제 (소프트 삭제)
vault kv delete secret/cloudflare/tokens/old-token
# 영구 삭제
vault kv destroy -versions=1 secret/cloudflare/tokens/old-token
```
---
## CLI 사용법
### 환경변수로 로드
```bash
# API Token 방식 (권장)
export CLOUDFLARE_API_TOKEN=$(vault kv get -field=api_token secret/cloudflare/tokens/dns-edit)
# Global API Key 방식 (레거시)
export CF_API_EMAIL=$(vault kv get -field=email secret/cloudflare/global)
export CF_API_KEY=$(vault kv get -field=api_key secret/cloudflare/global)
# Account ID
export CLOUDFLARE_ACCOUNT_ID=$(vault kv get -field=account_id secret/cloudflare/tokens/dns-edit)
```
### Tunnel credentials.json 복원
```bash
# JSON 파일로 추출 # JSON 파일로 추출
vault kv get -format=json secret/cloudflare/tunnels/production | \ vault kv get -format=json secret/cloudflare/tunnels/production | \
jq '.data.data' > ~/.cloudflared/production.json jq -r '.data.data | {
AccountTag: .account_tag,
TunnelID: .tunnel_id,
TunnelSecret: .tunnel_secret
}' > ~/.cloudflared/production.json
chmod 600 ~/.cloudflared/production.json
``` ```
### 한 번에 모든 크레덴셜 로드
```bash
# JSON에서 환경변수로 변환
eval $(vault kv get -format=json secret/cloudflare/tokens/dns-edit | \
jq -r '.data.data | to_entries[] | "export CF_\(.key | ascii_upcase)=\(.value)"')
```
---
## 자동화 스크립트 ## 자동화 스크립트
### Fish Shell 함수 ### Fish Shell 함수
```fish ```fish
# ~/.config/fish/functions/cf-auth.fish
function cf-auth function cf-auth
set -gx CF_API_EMAIL (vault kv get -field=email secret/cloudflare) set -l token_name $argv[1]
set -gx CF_API_KEY (vault kv get -field=api_key secret/cloudflare) if test -z "$token_name"
echo "Cloudflare 인증 설정 완료" set token_name "dns-edit"
end
set -gx CLOUDFLARE_API_TOKEN (vault kv get -field=api_token secret/cloudflare/tokens/$token_name)
set -gx CLOUDFLARE_ACCOUNT_ID (vault kv get -field=account_id secret/cloudflare/tokens/$token_name)
echo "✅ Cloudflare 인증 설정 완료 (토큰: $token_name)"
end
function cf-auth-clear
set -e CLOUDFLARE_API_TOKEN
set -e CLOUDFLARE_ACCOUNT_ID
set -e CF_API_EMAIL
set -e CF_API_KEY
echo "🧹 Cloudflare 환경변수 정리 완료"
end end
``` ```
### Bash 별칭 ### Bash 함수
```bash ```bash
alias cf-auth='eval $(vault kv get -format=json secret/cloudflare | jq -r ".data.data | to_entries[] | \"export CF_\" + (.key | ascii_upcase) + \"=\" + .value")' # ~/.bashrc 또는 ~/.bash_aliases
cf-auth() {
local token_name="${1:-dns-edit}"
export CLOUDFLARE_API_TOKEN=$(vault kv get -field=api_token "secret/cloudflare/tokens/${token_name}")
export CLOUDFLARE_ACCOUNT_ID=$(vault kv get -field=account_id "secret/cloudflare/tokens/${token_name}")
echo "✅ Cloudflare 인증 설정 완료 (토큰: ${token_name})"
}
cf-auth-clear() {
unset CLOUDFLARE_API_TOKEN CLOUDFLARE_ACCOUNT_ID CF_API_EMAIL CF_API_KEY
echo "🧹 Cloudflare 환경변수 정리 완료"
}
# 자동 완성
_cf_auth_completions() {
local tokens=$(vault kv list -format=json secret/cloudflare/tokens 2>/dev/null | jq -r '.[]')
COMPREPLY=($(compgen -W "${tokens}" -- "${COMP_WORDS[COMP_CWORD]}"))
}
complete -F _cf_auth_completions cf-auth
``` ```
## 보안 고려사항 ---
1. **최소 권한 원칙**: API Token 사용 시 필요한 권한만 부여 ## Terraform 통합
2. **임시 인증**: 환경변수는 세션 종료 시 자동 삭제
3. **파일 권한**: `chmod 600 ~/.cloudflared/*`
4. **Vault 통합**: 모든 크레덴셜은 Vault에서 중앙 관리
## 추천 워크플로우 ### Provider 설정
1. Vault에 API Token 저장 (Global Key 대신) ```hcl
2. 필요시 환경변수로 로드 # providers.tf
3. 작업 완료 후 환경변수 정리 terraform {
4. CI/CD에서는 Vault Agent 사용 required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
vault = {
source = "hashicorp/vault"
version = "~> 3.0"
}
}
}
provider "vault" {
address = "https://vault.anvil.it.com"
# 토큰은 VAULT_TOKEN 환경변수에서 자동 로드
}
# Vault에서 Cloudflare 토큰 읽기
data "vault_kv_secret_v2" "cloudflare" {
mount = "secret"
name = "cloudflare/tokens/dns-edit"
}
provider "cloudflare" {
api_token = data.vault_kv_secret_v2.cloudflare.data["api_token"]
}
```
### DNS 레코드 관리 예시
```hcl
# dns.tf
data "cloudflare_zone" "main" {
name = "example.com"
}
resource "cloudflare_record" "api" {
zone_id = data.cloudflare_zone.main.id
name = "api"
value = "192.168.1.100"
type = "A"
proxied = true
}
```
### Tunnel 설정 예시
```hcl
# tunnel.tf
data "vault_kv_secret_v2" "tunnel" {
mount = "secret"
name = "cloudflare/tunnels/production"
}
resource "cloudflare_tunnel" "production" {
account_id = data.vault_kv_secret_v2.cloudflare.data["account_id"]
name = "production-tunnel"
secret = data.vault_kv_secret_v2.tunnel.data["tunnel_secret"]
}
```
---
## CI/CD 통합
### GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy to Cloudflare
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Import Secrets from Vault
uses: hashicorp/vault-action@v2
with:
url: https://vault.anvil.it.com
method: approle
roleId: ${{ secrets.VAULT_ROLE_ID }}
secretId: ${{ secrets.VAULT_SECRET_ID }}
secrets: |
secret/data/cloudflare/tokens/workers-deploy api_token | CLOUDFLARE_API_TOKEN ;
secret/data/cloudflare/tokens/workers-deploy account_id | CLOUDFLARE_ACCOUNT_ID
- name: Deploy Worker
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ env.CLOUDFLARE_API_TOKEN }}
accountId: ${{ env.CLOUDFLARE_ACCOUNT_ID }}
```
### GitLab CI
```yaml
# .gitlab-ci.yml
variables:
VAULT_ADDR: "https://vault.anvil.it.com"
.vault-auth: &vault-auth
before_script:
- export VAULT_TOKEN=$(vault write -field=token auth/approle/login role_id=$VAULT_ROLE_ID secret_id=$VAULT_SECRET_ID)
- export CLOUDFLARE_API_TOKEN=$(vault kv get -field=api_token secret/cloudflare/tokens/dns-edit)
deploy:
<<: *vault-auth
script:
- wrangler deploy
```
---
## 문제 해결
### 일반적인 오류
| 오류 | 원인 | 해결 |
|------|------|------|
| `permission denied` | Vault 정책 부족 | 정책에 경로 추가 |
| `token expired` | Vault 토큰 만료 | `vault login` 재실행 |
| `secret not found` | 잘못된 경로 | `vault kv list` 로 확인 |
| `authentication error` | CF 토큰 만료/삭제 | Cloudflare에서 토큰 재생성 |
### Vault 연결 확인
```bash
# Vault 상태 확인
vault status
# 토큰 정보 확인
vault token lookup
# 시크릿 경로 목록
vault kv list secret/cloudflare/
vault kv list secret/cloudflare/tokens/
```
### Cloudflare 토큰 검증
```bash
# 토큰 유효성 확인
curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer $(vault kv get -field=api_token secret/cloudflare/tokens/dns-edit)" | jq
# 권한 확인
curl -s -X GET "https://api.cloudflare.com/client/v4/user" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result.id'
```
### 디버그 모드
```bash
# Vault 상세 로그
VAULT_LOG_LEVEL=debug vault kv get secret/cloudflare/tokens/dns-edit
# curl 상세 출력
curl -v -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```
---
## 보안 체크리스트
- [ ] Global API Key 대신 API Token 사용
- [ ] 토큰별 최소 권한 원칙 적용
- [ ] Vault 정책으로 접근 제한
- [ ] 환경변수는 세션 종료 시 정리
- [ ] CI/CD에서 AppRole 사용
- [ ] 정기적인 토큰 로테이션
- [ ] Vault 감사 로그 활성화
---
## 참고 자료
- [Cloudflare API Tokens](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/)
- [HashiCorp Vault KV Secrets](https://developer.hashicorp.com/vault/docs/secrets/kv/kv-v2)
- [Vault AppRole Auth](https://developer.hashicorp.com/vault/docs/auth/approle)
- [Terraform Cloudflare Provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs)
---
*마지막 업데이트: 2026-01*