diff --git a/ops-agents/heimdall/history/2026-04-21-outline-apisix-safeline.md b/ops-agents/heimdall/history/2026-04-21-outline-apisix-safeline.md new file mode 100644 index 0000000..cec9924 --- /dev/null +++ b/ops-agents/heimdall/history/2026-04-21-outline-apisix-safeline.md @@ -0,0 +1,55 @@ +--- +date: 2026-04-21 +topic: outline APISIX 라우트 + SafeLine WAF 부착 +areas: + - infra/network/apisix + - infra/network/k3s-ingress-architecture + - services/outline +--- + +# 2026-04-21 outline APISIX 라우트 + SafeLine WAF 부착 + +## 한 줄 요약 + +`outline.inouter.com` 을 Traefik 에서 APISIX 경유로 이전 (Bunny iron-kr-nowaf pull zone origin 전환 준비). TLS + route 를 `ApisixTls`/`ApisixRoute` CRD 로 등록 후 `chaitin-waf` plugin 부착해 SafeLine WAF 경유로 완성. 정상 요청 pass, SQLi 403 reject 검증 완료. Traefik IngressRoute 는 롤백 대비 유지. + +## 타임라인 (UTC) + +| 시각 | 이벤트 | +|---|---| +| 00:58 | Admin API 로 SSL `outline-inouter` 최초 생성 (status=null → SNI 매칭 실패) | +| 00:59 | SSL 재 PUT (`status:1` 추가) → TLS handshake 정상, `curl --resolve` 200 | +| 01:04 | apisix-ingress-controller full-sync 에 의해 SSL `outline-inouter` **purge** (orphan 판정) | +| 01:06 | `ApisixTls` + `ApisixRoute` CRD 생성 (`ingressClassName: apisix` 필수), synced → SSL `4e7704e0`, Route `ce4d2d80` | +| 01:11 | `chaitin-waf` plugin ApisixRoute 에 부착 | +| 01:12 | 검증 완료 (정상 200 pass, SQLi 403 reject) | + +## 최종 리소스 + +| 종류 | 위치 | APISIX ID | +|---|---|---| +| ApisixTls | `apisix/outline-inouter` | ssl `4e7704e0` | +| ApisixRoute | `outline/outline-inouter` | route `ce4d2d80` (name `outline_outline-inouter_outline-rule`) | +| K8s secret | `apisix/wildcard-inouter-tls` | GTS WR1, *.inouter.com, NotAfter 2026-06-21 | +| Traefik IngressRoute | `outline/outline` | 유지 (롤백 대비) | + +## 교훈 (이번 작업에서 새로 확인) + +1. **APISIX 3.15 Admin API PUT 으로 SSL 만들 때 `status: 1` 명시 필수** — 생략 시 etcd 저장은 되지만 `status: null` 로 SNI 매칭 되지 않음. +2. **apisix-ingress-controller 2.0.1 은 IngressClass 기준 authoritative sync** — CR 로 정의되지 않은 Admin API 직접 객체는 purge. 지속 가능한 운영은 ApisixRoute/ApisixTls CRD 로만. +3. **CR 에 `ingressClassName: apisix` 필수** — 누락 시 controller 가 CR 소유하지 않아 status.conditions 비어있고 sync 되지 않음. 기존 `wildcard-keepanker-cv`/`juiceshop` CR 과 스키마 정렬. +4. **cert-manager 자동 갱신 경로**: ApisixTls 는 secret 참조 방식이므로 `wildcard-inouter-tls` 갱신 시 controller 가 자동 재 sync. 별도 스크립트/cron 불필요. + +## 검증 요약 + +| 테스트 | 기대 | 결과 | +|---|---|---| +| `GET /` | 200 Outline SPA | 200, 4827 bytes, HTML | +| `GET /api/auth.info` | 404 (비로그인 시) | 404 Outline JSON (`x-apisix-chaitin-waf-action: pass`) | +| `GET /?id=1+OR+1=1` | 403 SafeLine block | 403 JSON `blocked by Chaitin SafeLine WAF` (`action: reject`, time 28ms) | + +## 관련 문서 + +- 상세 리포트: Outline `heimdall` 컬렉션 `2026-04-21 / APISIX outline 라우트 + SSL 설정 / kappa` (id `eb5d683b-47bd-4932-a585-fb232ac05cba`) +- [[../../infra/network/apisix]] +- [[../../infra/network/k3s-ingress-architecture]]