OCI WAF 인증서 갱신: Certbot·OCI CLI 연동과 확인 사항

OCI WAF 인증서 갱신: 원본 서버와 클라우드 엣지의 배포 확인을 표현한 개념 그림

OCI WAF(Web Application Firewall)의 Edge 정책(WAAS)에 HTTPS를 구성하면 클라이언트와 WAF 사이의 인증서를 별도로 관리하게 됩니다. HTTP→HTTPS 리다이렉트는 해당 정책에서 활성화해야 하며, WAF 사용만으로 자동 적용되는 것은 아닙니다.

Certbot의 갱신 작업이 예약되어 있고 인증 절차가 성공해야 서버 인증서가 갱신됩니다. Edge 정책에 따로 업로드한 인증서는 서버 갱신만으로 교체되지 않습니다. 두 배포 지점의 인증서와 만료 상태를 각각 확인해야 합니다.

이 글은 WAF 인증서 만료를 다룬 사례와 certbot deploy hook·OCI CLI를 연결하는 예제를 정리합니다. 사례의 시점과 당시 결과를 현재 환경의 검증 결과로 간주하지 마세요. 아래 hook은 오류 처리·대상 정책·비동기 적용 확인을 별도로 검증해야 하는 예제입니다.

문제: 이중 인증서 구조

[사용자 브라우저] │ ▼ [OCI WAF] ←── WAF SSL 인증서 (수동 업로드) │ ▼ [Apache 서버] ←── 서버 SSL 인증서 (certbot 자동갱신)

certbot이 서버 인증서를 갱신해도, WAF 인증서는 그대로입니다. 두 인증서의 만료일이 다르기 때문에 서버 인증서가 유효해도 WAF 인증서가 만료되면 사이트 접속이 불가합니다.

⚠️ 실전 상황: 서버 certbot 인증서는 5월 21일까지 유효한데, WAF 인증서는 2일 후(3월 22일) 만료 예정이었습니다. deploy hook도 없고 OCI CLI도 없는 상태에서 발견.

진단: 현재 상태 파악

서버 인증서 확인

sudo certbot certificates
# Expiry Date: 2026-05-21 (VALID: 62 days) ← 정상

sudo ls -la /etc/letsencrypt/renewal-hooks/deploy/
# 비어있음 ← 자동화 없음

oci --version 2>/dev/null || echo "OCI CLI 미설치"
# OCI CLI 미설치 ← API 호출 불가

WAF 인증서 확인

OCI 콘솔 → WAF Policies → 정책 선택 → Settings → General settings에서 SSL certificate expiration date 확인.

긴급 처치: 수동 인증서 갱신

수동 업로드 범위: 이 절차는 OCI WAF Edge Policies(WAAS)의 인증서 업로드에만 해당합니다. 아래 경로는 실제 파일이 아닌 템플릿입니다. CERT_NAME은 확인된 Certbot 인증서 이름으로 바꾸며, 도메인과 같다고 가정하지 않습니다. 뒤의 자동 갱신 hook과 별도로 검토하세요.
1
원본을 유지하고 복사본 최소화
/etc/letsencrypt/live/CERT_NAME/fullchain.pem
/etc/letsencrypt/live/CERT_NAME/privkey.pem

fullchain.pem은 공개 서버 인증서와 중간 인증서 체인이고, privkey.pem은 비밀로 보관해야 하는 대응 개인키입니다. Certbot의 live 경로는 갱신 시 최신 파일을 가리킵니다. 수동 업로드를 위해 원본이나 archive 파일의 소유권·권한을 완화하거나 원본을 삭제하지 마세요.

기존에 승인·검증된 전송 방법이 관리자 권한으로 원본을 안전하게 읽을 수 있다면 서버 중간 복사본을 생략합니다. 일반 SFTP/scp가 자동으로 sudo 권한을 얻는다고 가정하지 마세요. 서버 임시 복사가 꼭 필요하면 동기화·백업·웹 공개 대상이 아닌 새 전용 디렉터리를 만들고, 승인된 전송 계정만 접근하도록 처음부터 디렉터리 0700, 두 복사 파일 0600을 적용합니다. 부모 경로도 신뢰할 수 있어야 하며 기존 파일·심볼릭 링크를 덮어쓰지 않습니다.

/home/TRANSFER_USER/.dih-waf-export-UNIQUE/fullchain.pem
/home/TRANSFER_USER/.dih-waf-export-UNIQUE/privkey.pem

TRANSFER_USER와 UNIQUE는 검토한 실제 계정과 새 작업별 이름으로 치환합니다. 소유권 지정은 이 두 복사 파일과 전용 디렉터리에만 한정하며 wildcard·재귀 변경은 사용하지 않습니다. 복사 후에야 권한을 제한하는 방식도 피합니다.

2
보호된 PC 작업 폴더로만 전송

관리되는 암호화된 PC에서 동기화·공유·백업 대상이 아닌 전용 폴더를 먼저 준비합니다. POSIX 환경에서는 승인된 로컬 사용자 소유의 디렉터리 0700과 파일 0600을 사용합니다. Windows에서는 NTFS ACL로 승인된 사용자와 필요한 시스템 관리자만 접근하도록 설정하고 상속된 광범위한 접근 권한을 점검합니다. Windows/WSL의 chmod만으로 Windows 접근이 차단된다고 가정하지 마세요.

/home/LOCAL_USER/.dih-waf-upload-UNIQUE/fullchain.pem
/home/LOCAL_USER/.dih-waf-upload-UNIQUE/privkey.pem

위는 POSIX 경로 템플릿이며 Windows에서는 검토한 절대 경로를 따로 정합니다. 서버 호스트 키를 확인한 암호화 전송으로 두 파일만 정확한 목적지에 받습니다. 현재 폴더·Downloads·OneDrive 같은 위치는 사용하지 않습니다. 전송 확인 직후 서버 임시 복사본이 있다면 정확한 두 파일과 빈 전용 디렉터리를 정리합니다. 키 본문은 터미널 출력·클립보드·채팅·로그·Git에 남기지 마세요.

3
승인된 OCI 인증서 입력에 파일로 전달

대상 Edge 정책과 변경 승인을 확인한 뒤 Console의 인증서 입력에서 fullchain.pem을 SSL certificate, privkey.pem을 Private key에 파일로 지정합니다. PEM 형식이며 인증서는 leaf 다음 중간 인증서 순서여야 합니다. WAAS 입력 개인키는 암호(passphrase)로 암호화된 형식일 수 없습니다. 형식·대응 관계가 불확실하면 임의 변환하거나 업로드하지 말고 중단합니다.

Let's Encrypt 인증서에는 Self signed certificate를 체크하지 않습니다. 저장·정책 적용과 결과 확인은 별도 승인된 인증서 변경 절차를 따릅니다. 이 안내 자체가 변경 승인이나 배포 성공 증거는 아닙니다.

4
성공·실패·취소 모두 임시 복사본 정리

업로드 시도가 끝나거나 작업을 중단하면 로컬의 정확한 두 임시 파일과 빈 전용 폴더를 정리하고, 서버 임시 파일도 남지 않았는지 확인합니다. 실패한 전송의 부분 파일도 포함합니다. Certbot 원본·archive·기존 OCI 인증서 리소스는 정리 대상이 아닙니다. 도구가 만든 임시 파일·휴지통·동기화/백업 복사본의 처리 정책도 확인하세요. 일반 삭제만으로 SSD·스냅샷에서 완전 소거됨을 보장할 수 없으므로 처음부터 복사 범위와 보관 시간을 줄입니다. 작업 기록에는 경로·시각·정리 결과만 남기며 키 본문을 첨부하지 않습니다.

갱신 연동 검토: OCI CLI + certbot deploy hook

OCI CLI 설치

# Oracle Linux 8
sudo yum install -y python36-oci-cli
oci --version

OCI CLI 설정

기존 설정이 있을 수 있으니 먼저 확인:

cat ~/.oci/config 2>/dev/null

설정이 없거나 인증 실패하면 oci setup config를 실행합니다. 필요한 값:

항목확인 위치
User OCIDOCI 콘솔 → 우측 상단 사람 아이콘 → My profile → OCID Copy
Tenancy OCIDOCI 콘솔 → 사람 아이콘 → Tenancy → OCID Copy
Region콘솔 우측 상단 (예: ap-chuncheon-1)

설정 완료 후 생성된 공개키를 OCI에 등록:

cat ~/.oci/oci_api_key_public.pem
# 출력 내용 복사 → My profile → API keys → Add API key → Paste
💡 API 키 제한: OCI는 사용자당 API 키 3개까지 허용합니다. 이미 3개면 미사용 키를 삭제 후 추가하세요. OCI에서 어떤 키가 사용 중인지 직접 알 수 있는 기능은 없으며, Audit 로그에서 fingerprint로 간접 확인 가능합니다.

deploy hook 스크립트

sudo tee /etc/letsencrypt/renewal-hooks/deploy/upload-to-waf.sh << 'SCRIPT'
#!/bin/bash
LOG="/var/log/waf-cert-upload.log"
OCI="/usr/bin/oci --config-file /home/opc/.oci/config"
WAF_ID="<WAF_POLICY_OCID>"

echo "$(date) ==============================" >> "$LOG"
echo "$RENEWED_DOMAINS" | grep -q "도메인" || { echo "$(date) 스킵" >> "$LOG"; exit 0; }

CERT_PATH="$RENEWED_LINEAGE/fullchain.pem"
KEY_PATH="$RENEWED_LINEAGE/privkey.pem"
COMPARTMENT_ID=$(${OCI} waas waas-policy get \
    --waas-policy-id ${WAF_ID} \
    --query 'data."compartment-id"' --raw-output)

# 1. 인증서 리소스 생성
CERT_RESULT=$(${OCI} waas certificate create \
    --compartment-id "$COMPARTMENT_ID" \
    --certificate-data "$(cat ${CERT_PATH})" \
    --private-key-data "$(cat ${KEY_PATH})" \
    --display-name "auto-$(date +%Y%m%d%H%M%S)")

CERT_OCID=$(echo "$CERT_RESULT" | \
    python3 -c "import sys,json; print(json.load(sys.stdin)['data']['id'])")

# 2. WAF 정책에 연결
${OCI} waas waas-policy update \
    --waas-policy-id "$WAF_ID" \
    --policy-config "{\"certificateId\":\"${CERT_OCID}\",\"isSniEnabled\":true,\"isHttpsEnabled\":true,\"isHttpsForced\":true,\"tlsProtocols\":[\"TLS_V1_2\",\"TLS_V1_3\"]}" \
    --force >> "$LOG" 2>&1

echo "$(date) 완료: $CERT_OCID" >> "$LOG"
SCRIPT

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/upload-to-waf.sh

트러블슈팅 포인트

증상원인해결
certificateData is not validfile:// 형식 전달$(cat 파일)로 변경
No such option: --configWAAS API 파라미터명 상이--policy-config 사용
업데이트 후 변경 안 됨비동기 처리 (최대 15분)oci waas work-request get으로 확인
✅ 확인 사항: 서버 인증서 갱신에 성공한 뒤, 올바르게 설정한 deploy hook으로 WAF 배포를 연동할 수 있습니다. 대상 정책, 비동기 적용 상태와 방문자에게 제공되는 인증서를 확인해야 하며, 수동 점검이 필요할 수 있습니다.
위로 스크롤