---
type: note
tags: [istio, egress, mtls, passthrough, calico, networkpolicy, decision, spiffe]
created: 2026-06-08
---
# Egress 신원, 이중 TLS 없이 — passthrough + Calico가 HTTPS over mTLS를 대체하는 근거
> [!abstract]
> "egress에서 호출 워크로드 신원을 통제하려면 HTTPS over mTLS(이중 TLS)가 필요하다"는 통념에 대한 반론.
> 멘탈모델 한 줄: **강제(enforcement)는 어차피 chokepoint(egress gateway)에서 일어난다 — 패턴 선택은 "그 앞에서
> 호출자를 *어떻게 식별*하느냐"의 문제일 뿐이다.** 식별을 메시 mTLS handshake로 할지, **CNI(Calico)가 커널에서
> 이미 하는 pod-selector**로 할지. 단일 클러스터·노드 신뢰·Calico 단독관리 환경에선 후자가 **동일 결과를 더 싸게**
> 낸다. 이중 TLS의 추가 비용(handshake 2회·포트분리 함정·L7 사각)은 그 위협모델에서 보안 이득이 0에 가깝다.
> 대상 구조의 상세는 [HTTPS over mTLS 구조 정본](id__src-https-over-mtls.html) 참조 — 본 문서는 그 **반대 선택의 근거**다.
**맥락:** 사내 egress 도입에서 "HTTPS over mTLS냐 passthrough냐" 결정 토론용 근거 문서.
**환경 전제:** 단일 클러스터, CNI **Calico(플랫폼팀 단독관리)**, 노드 신뢰 위협모델, 외부 파트너 감사는 source IP로 충분.
**대상 독자:** egress 패턴을 고르는 DevOps/SRE. **선행 개념:** egress gateway가 chokepoint라는 것, mTLS=SPIFFE cert, NetworkPolicy의 selector.
---
## 1. 배경 — 애초에 "egress 신원"이 왜 문제인가
메시 내부 트래픽은 mTLS로 자동 식별된다. 문제는 **밖으로 나가는 트래픽**이다. `payment` pod가 `partner-bank.example.com:443`을 부를 때, 클러스터 운영자는 두 가지를 보장하고 싶다.
1. **누가 나가는지 통제** — `payment`만 partner-bank로 나가고 나머지는 차단.
2. **누가 나갔는지 귀속** — 외부 파트너 감사·내부 로그에서 "이 호출은 payments tier가 한 것"을 증빙.
그런데 외부 목적지는 메시 밖이라 **응답 측이 SPIFFE를 검증해 주지 않는다.** 식별은 전적으로 **나가는 경계(egress gateway)에서, 우리 손으로** 해야 한다. 그래서 "egress 신원"은 본질적으로 *경계 통과자를 어떻게 식별하느냐*의 문제로 환원된다.
표준 처방은 **HTTPS over mTLS(이중 TLS)** 다: 앱→egress gateway 구간에 메시 mTLS를 한 겹 더 씌워, gateway가 outer handshake의 client cert로 호출자 SPIFFE ID를 확정하고 `AuthorizationPolicy`를 건다. 본 문서는 *그게 정말 필요한 비용인가*를 따진다. 결론부터: 위 환경 전제에선 **CNI가 이미 공짜로 하는 식별로 동일 결과를 낸다.**
여기서 먼저 통념의 정체를 정확히 분해해야 토론에서 못 진다. 이중 TLS가 passthrough 대비 추가로 *사는 것*은 **딱 하나**다.
> egress gateway가 outer mTLS handshake에서 받은 client cert로 **호출 워크로드의 SPIFFE ID**
> (`cluster.local/ns/payments/sa/payment`)를 **암호학적으로 확정**하고, 그걸 키로 `AuthorizationPolicy`를 건다.
즉 사는 물건은 **"egress chokepoint를 통과하는 호출자를 SA 단위로 식별·인가"** 다. 그 이상도 이하도 아니다(L7은 여전히 못 봄 — outer/inner TLS 모두 불투명).
---
## 2. 핵심 — 식별과 강제를 분리하면 대안이 보인다
**멘탈모델 anchor:** egress 보안 = **식별(누구인가) + 강제(못 나가게 막기)**, 이 둘은 별개 축이다. **강제는 어느 패턴이든 똑같이 chokepoint(egress gateway + 그 앞의 NetworkPolicy)에서 일어난다.** 그러니 패턴 비교는 오직 **식별 한 축**으로 좁혀진다 — chokepoint 앞에서 호출자를 무엇으로 식별하느냐.
```mermaid
flowchart LR
M["식별방법 A
mTLS handshake
SPIFFE cert (이중 TLS)"]
C["식별방법 B
Calico pod-selector
커널 endpoint (handshake 0)"]
CHK["egress gateway
= 강제 chokepoint
(어느 방식이든 동일)"]
EXT["partner-bank.example.com:443"]
M -->|"outer mTLS로 식별"| CHK
C -->|"커널에서 식별·차단"| CHK
CHK --> EXT
```
왜 이 분리가 결정적인가. 식별 방법 A(mTLS handshake)는 이중 TLS·L7 사각·포트 머지 충돌·핸드셰이크 2회라는 비용을 동반한다. 식별 방법 B(Calico pod-selector)는 **CNI가 패킷 라우팅을 위해 어차피 유지하는 endpoint(IP↔pod 매핑)** 를 재사용하므로 추가 비용이 0이다. 두 방법이 *식별*이라는 같은 일을 하면서 가격표만 다르다면, 강제가 공유되는 한 더 싼 쪽이 합리적이다.
이 anchor에서 "더 싸게 근사"가 막연한 말이 아니라 **구체적 대안 3개**로 떨어진다.
### 식별 메커니즘의 핵심 — pod-selector는 "비-핸드셰이크 신원"이다
방법 B가 단순 ACL이 아니라 *신원 메커니즘*이라는 게 논거의 심장이다.
`app == 'payment'`는 pod가 헤더로 *주장*하는 값이 아니라 **Calico가 endpoint(IP↔pod 매핑)에 묶어 커널(iptables/eBPF)에서 강제**하는 라벨이다. 옆 pod가 `payment`를 사칭하려면 **그 pod의 네트워크 네임스페이스 자체를 위조**해야 하고, 그건 **노드 컴프로마이즈** 수준이다.
→ 즉 **"pod-selector NetworkPolicy는 그 자체로 비-핸드셰이크 신원 메커니즘"** 이다. mTLS가 cert로 하는 일(검증된 호출자 식별)을 Calico는 커널 endpoint로 한다 — handshake 비용 0. 이것이 §3·§4 두 논증(중복 구매·노드 신뢰)의 토대다.
---
## 3. 근사 3종 — 구체 시나리오 + 실제 YAML
시나리오 고정: **"`payment` 워크로드만 `partner-bank.example.com:443`으로 나갈 수 있다. 나머지는 차단."**
(전형적 사내 egress 요구) 세 근사는 §2의 식별 축을 **config 분배 / 커널 강제 / IP 귀속** 세 층위로 구현한 것이다.
### 근사 ① namespace = 신원 경계 (가장 쌈, config 분배로 강제)
`payment`를 `payments` 네임스페이스에 두고, 외부 등록을 **그 네임스페이스에만 export**한다.
```yaml
apiVersion: networking.istio.io/v1
kind: ServiceEntry
metadata: { name: partner-bank, namespace: payments }
spec:
hosts: [partner-bank.example.com]
exportTo: ["."] # ★ payments 네임스페이스에만 보임 — 다른 ns Envoy는 이 cluster를 아예 모름
ports: [{ number: 443, name: tls, protocol: TLS }]
resolution: DNS
location: MESH_EXTERNAL
```
메커니즘: 다른 네임스페이스의 sidecar는 **이 외부 cluster를 xDS로 받지조차 못한다** → partner-bank로 가는 route
자체가 Envoy에 없음 → 호출 불가. `REGISTRY_ONLY`면 미등록이라 BlackHole. **handshake 검증이 아니라
"설정을 아예 안 줌"으로 차단.** mTLS 0줄. (scope 메커니즘: [sidecar scope](mm__src-sidecar-scope.html))
### 근사 ② Calico NetworkPolicy = pod-selector가 곧 신원 (커널 강제 — 핵심)
```yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata: { name: egress-bank-payment-only, namespace: payments }
spec:
selector: all()
types: [Egress]
egress:
# payment 라벨 pod만 egress gateway(15443)로 나갈 수 있다
- action: Allow
source: { selector: "app == 'payment'" }
destination:
selector: "istio == 'egressgateway'"
namespaceSelector: "kubernetes.io/metadata.name == 'istio-system'"
# 그 외 모든 pod의 외부행 차단
- action: Deny
destination: { nets: ["0.0.0.0/0"] }
```
> 위 예시는 ns-scoped `NetworkPolicy`다(근사② 시나리오에 충분). 단, **클러스터 전역 default-deny**는
> 정본에서 `GlobalNetworkPolicy`로 거는 게 표준이다([Egress 개념 정본 §02](ref__src-egress-gateway.html) 참조).
> ⚠️ **적용 메모(개념 예시)**: `projectcalico.org/v3` 리소스는 calico-apiserver가 없으면 `kubectl apply`로 바로 안 들어갈 수 있다(kubespray 기본 구성 등) — 그 경우 `calicoctl apply`를 쓴다. egress rule의 `source.selector`는 top-level `selector`(정책 적용 대상)와 의미가 겹쳐 혼동되기 쉬우므로, 실제 적용 시 `app == 'payment'`를 top-level `selector`로 두는 형태로 `calicoctl`로 검증 권장. 본 YAML은 *논거용 개념 예시*다.
이 YAML이 §2에서 말한 "비-핸드셰이크 신원"을 그대로 코드로 옮긴 것이다. `app == 'payment'`는 Calico가 커널에서 endpoint에 묶어 강제하므로, mTLS의 client cert가 하는 일을 정확히 대체한다.
### 근사 ③ source IP = tier별 전용 egress gateway (감사 귀속용)
민감 tier에 **전용 egress gateway 배포**를 따로 띄우고(`istio-egressgateway-payments`), partner-bank route를
*그 게이트웨이에만* 존재시킨다. 그러면:
- partner-bank 접근 로그에 찍히는 source IP = **payments 전용 gateway pod IP** → "이 호출은 payments tier에서
나왔다"가 IP만으로 감사 귀속.
- 일반 워크로드는 그 gateway로 라우팅되지 않음(근사 ①②로 격리).
거칠지만 **외부 파트너 쪽 감사**라는 목적엔 충분하다(파트너는 어차피 SPIFFE를 모름, source IP만 봄).
> ⚠️ **"source IP" 단독은 가장 거친·시대에 뒤처진 형태**다. 현대적·강한 형태는 근사②의 **CNI label-identity
> (IP에서 분리)** 이고, 실명 규제기관이 쓰는 것도 그쪽이다(실증: §6①③). 여기 source IP는 *외부 파트너 감사*
> (파트너는 IP만 봄)에 한정된 좁은 용도일 뿐, 메시 내부의 1차 식별 수단으로 내세우지 말 것.
---
## 4. 비용 비교 — 같은 결과, 다른 가격표 (중복 구매 논증)
| 항목 | HTTPS over mTLS | 근사(ns + Calico + 전용 gw) |
|---|---|---|
| 추가 TLS handshake | **2회**(mesh mTLS + 앱) | 1회(앱만) |
| 추가 홉 | egress gw 1홉 | 동일(어차피 chokepoint는 둠) |
| 설정 함정 | 포트 머지 충돌·leg-2 tcp/tls·sni 3자 정렬 | 라벨 셀렉터(친숙) |
| L7 egress 정책 | **불가**(이중 TLS 사각) | **불가**(동일 — 둘 다 못 함) |
| 강제 계층 | Istio 라우팅 + **결국 Calico 필요**(sidecar 우회 차단) | **Calico 단독으로 끝**(이미 그게 강제 계층) |
| 식별 단위 | SA(SPIFFE) | pod 라벨/ns(= 사실상 SA와 1:1로 운영) |
| 디버깅 표면 | mTLS+xDS+filter chain | NetworkPolicy(L3/L4) |
**가장 강한 한 줄 — 중복 구매 논증:** 표의 "강제 계층" 행이 핵심이다. mTLS를 써도 강제는 결국 Calico가 한다.
```mermaid
flowchart TD
NEED["진짜 강제하려면
sidecar 우회를 막아야 함"]
CAL["Calico NetworkPolicy
(pod-selector 강제)"]
DONE["egress 신원 통제 완성"]
MTLS["HTTPS over mTLS
신원 레이어"]
NEED -->|"필수 — 패턴 무관"| CAL
CAL -->|"이미 '누가 나가나'를 강제함"| DONE
MTLS -.->|"같은 일을 한 번 더 = 중복 구매"| DONE
```
HTTPS over mTLS를 써도 **sidecar 우회를 막으려면 어차피 Calico NetworkPolicy가 필요**하다([Egress 개념 정본
§02 강제 계층](ref__src-egress-gateway.html) 그대로). 그런데 그 Calico 정책이 이미 pod-selector로 "누가 나갈 수
있나"를 강제한다면 — **mTLS 신원 레이어는 같은 일을 한 번 더 하는 중복**이다. 즉 이중 TLS는 *추가 비용을 내고
이미 가진 강제를 재구매*하는 셈. (이 논증은 §6②에서 Istio 공식 문서로 입증된다.)
---
## 5. "그래도 mTLS가 더 안전하지 않냐"는 반박의 무력화
흔한 반박은 이렇다: *"라벨 NetworkPolicy는 cryptographic identity가 아니잖아."*
반박:
> HTTPS over mTLS가 **유일하게** 막는 위협은 "악성 in-mesh 워크로드가 egress gateway에게 `payment`를 *사칭*해서
> 나가는 것"이다. 그런데 우리 강제점이 Calico면, 사칭하려면 **pod의 커널 endpoint를 위조** = **노드 컴프로마이즈**가
> 필요하다. 그리고 노드가 털리면 **그 노드의 mTLS 개인키(SDS로 내려온 cert)도 같이 털린다** → mTLS도 같이 뚫린다.
```mermaid
flowchart TD
Q{"노드를 신뢰하는가?"}
Q -->|"Yes (우리 환경)"| BOTH["둘 다 안전
mTLS 추가이득 ~ 0"]
Q -->|"No (노드 컴프로마이즈)"| FAIL["둘 다 무너짐
SDS mTLS 키도 노드에서 탈취됨"]
```
핵심 통찰: **두 방식의 보안 하한은 "노드를 신뢰하는가"라는 같은 단일 가정에서 같이 무너진다.** mTLS의 개인키가 SDS로 노드에 내려와 있으므로, Calico endpoint 위조가 가능한 컴프로마이즈 수준이면 그 키도 같이 탈취된다 — mTLS가 *추가로* 막는 위협 영역이 없다. 노드를 신뢰하는 위협모델(=우리 홈랩/사내 대부분)에선 mTLS가 주는 *추가* 보안은 거의 0이고, 가격은 이중 TLS다.
---
## 6. 적용 — "passthrough로 충분" 의사결정과 떴는지 확인
### 6-1. 체크리스트 (전부 Yes면 passthrough)
다음 5개를 점검한다. 전부 Yes면 이중 TLS는 over-engineering이다.
```mermaid
flowchart TD
C1{"식별 단위가 SA 아닌
워크로드/ns로 충분?"}
C2{"노드 신뢰 위협모델?"}
C3{"Calico를 어차피 운영?"}
C4{"파트너 감사 = source IP로 충분?"}
C5{"per-URL L7 정책 불필요?"}
PASS["passthrough + Calico
(이중 TLS 불필요)"]
MTLS["HTTPS over mTLS 고려"]
ORIG["L7 필요 -> origination"]
C1 -->|Yes| C2
C2 -->|Yes| C3
C3 -->|Yes| C4
C4 -->|Yes| C5
C5 -->|Yes| PASS
C1 -->|No| MTLS
C2 -->|No| MTLS
C3 -->|No| MTLS
C4 -->|No| MTLS
C5 -->|No| ORIG
```
1. egress 식별 단위가 **SA가 아니라 워크로드/네임스페이스 단위로 충분**한가? → 보통 Yes
2. 우리는 **노드를 신뢰**하는 위협모델인가(노드 루트=게임오버 인정)? → 보통 Yes (§5)
3. **Calico NetworkPolicy를 어차피 운영**하는가(sidecar 우회 차단용)? → Yes여야 정상 (§4 중복 구매)
4. **외부 파트너의 감사**엔 source IP/전용 gateway 귀속으로 충분한가(파트너는 SPIFFE 모름)? → 보통 Yes
5. **per-URL(L7) egress 정책이 필요 없는가**? → 필요하면 어차피 mTLS도 답이 아님(origination이어야 함)
### 6-2. 떴는지 한 번 확인 (passthrough + Calico 적용 후)
근사②를 적용했다면 "허용된 pod는 나가고, 나머지는 막힌다"를 직접 확인한다.
```bash
# payment pod에서: 나가야 한다 (200/TLS handshake 성공)
kubectl exec -n payments deploy/payment -- \
curl -sS -o /dev/null -w '%{http_code}\n' https://partner-bank.example.com
# 기대: 200 (egress gateway 경유)
# 비-payment pod에서: 막혀야 한다 (Calico Deny → connection timeout)
kubectl exec -n payments deploy/other-app -- \
curl -sS --max-time 5 https://partner-bank.example.com
# 기대: exit 28 (timeout) — 커널에서 drop, route 자체도 근사①로 없음
# 누가 나갔나 귀속 (근사③): 전용 gateway pod IP로 확인
kubectl get pod -n istio-system -l istio=egressgateway-payments -o wide
# partner-bank 로그의 source IP == 이 pod IP 면 payments tier 귀속 성립
```
검증 포인트: payment는 200, 나머지는 **timeout(=커널 drop)** 이면 식별·강제가 둘 다 동작한 것. handshake 실패가 아니라 패킷 자체가 안 나가는 게 정상 — 차단 계층이 mTLS가 아니라 Calico임을 그대로 보여준다.
---
## 7. 실증 사례 — "실제로 이렇게 한다"는 근거 (조사)
"많은 조직이 신원을 CNI/NetworkPolicy로 더 싸게 근사한다"는 주장의 실증 조사. **세 근사의 근거 강도가 다르므로**
구분해서 말해야 토론에서 안 밀린다.
| 근사 | 근거 강도 | 실제 |
|---|---|---|
| **NetworkPolicy / CNI identity** | ★★★ 강함 — 실명 규제기관 | Cilium identity 모델 채택 |
| **namespace 단독** | ★★☆ 중간 — "soft boundary" 단서 필요 | 신뢰 팀엔 OK, 보안엔 NetworkPolicy 병행 |
| **source IP (literal)** | ★☆☆ 약함 — 시대 뒤처짐 | CNI label-identity로 대체됨 |
### ① NetworkPolicy/CNI identity는 규제 산업이 *실제로* 쓴다 (강함)
- **Corner Banca SA (스위스 은행)**: 온프렘 k8s의 CNI로 Cilium 사용. *"규제상 Kubernetes pod 트래픽이 인증·암호화·
방화벽 규칙 적용을 위해 **식별 가능**해야 한다"* 는 요구를 — **Istio egress mTLS가 아니라 Cilium identity 모델**로 충족.
"규제 때문에 신원이 필요"라는 바로 그 요구를 CNI로 푼 실명 사례다.
- **통신사(telecom)**: Cilium egress gateway + FQDN 룰셋 + default-deny egress로 **zero-trust 네트워킹** 구현.
- 메커니즘: Cilium은 동일 라벨 pod 그룹에 **security identity를 부여해 패킷에 싣고 수신 노드에서 검증** —
*"network addressing(IP)과 decoupled된 identity-based model"*. 이게 §5 "사칭하려면 커널 endpoint 위조 필요"
논거의 **프로덕션 버전**이다.
### ② Istio 공식이 NetworkPolicy를 *필수*로 못박는다 (결정타)
NetworkPolicy는 mTLS의 *대안*이 아니라, **Istio가 egress를 강제하려면 반드시 깔라는 전제**다:
- Istio 공식: *"Istio는 모든 egress가 실제로 egress gateway를 통과하도록 **안전하게 강제할 수 없다**(sidecar 우회 가능)."*
→ 권고: *"NetworkPolicy로 gateway 외의 외부행을 전부 막아라. `REGISTRY_ONLY` + NetworkPolicy."*
- 즉 **HTTPS over mTLS를 써도 NetworkPolicy는 어차피 깔아야 한다.** 그 NetworkPolicy가 이미 pod-label로 "누가
나가나"를 강제하므로 — §4 **중복 구매 논증이 *Istio 자체 문서로* 입증**된다.
### ③ 정직한 보정 — "source IP" 표현 + namespace 단서
- **"source IP" 단독은 시대에 뒤처진 표현**이다. 강한 현대형은 ②의 **CNI label-identity(IP에서 분리)**. 팀 설득
시 "source IP"보다 **"CNI label-identity(Cilium/Calico label)"** 로 말하는 게 더 세다. (§3 근사③의 source IP는
*외부 파트너 감사* 한정 용도임을 명시했다.)
- **namespace 단독은 공식적으로 "soft boundary"** 다 — *"namespace는 기본적으로 security boundary가 아니다"*.
신뢰 팀 간 사고 방지엔 충분하나 **악의적 격리엔 NetworkPolicy·RBAC·PSS 병행 필수**. 근사①(exportTo)은 config
분배 격리로 유효하지만 "그것만으로 보안 경계"라고 주장하면 안 된다.
> **못 찾은 것(정직)**: "*Istio egress mTLS 대신* NetworkPolicy를 택한 조직 비율" 같은 **정량 통계는 없다**. 근거는
> "NetworkPolicy egress는 보편·문서화 + Istio egress mTLS는 niche·복잡"이라는 **정성적 방향성**이다. 그러니 "많은
> 조직이 통계적으로"라고 단언하기보다 **"규제 은행도 CNI identity로 푼다 + Istio 공식이 NetworkPolicy를 필수로
> 못박는다"** 는 실명 근거로 말하는 게 안전하고 더 세다.
> ⚠️ **Cilium ≠ 우리 Calico**: 위 강력 사례(identity 패킷 인코딩·FQDN 정책)는 **Cilium(eBPF)** 고유 기능이다.
> 우리는 **Calico** → Calico도 label-selector egress·FQDN(`GlobalNetworkSet`/일부 FQDN)을 하지만, identity를
> *패킷에 싣는* 방식은 Cilium 고유. Calico는 label-selector를 **노드의 endpoint↔IP 매핑**으로 강제(효과는 동등,
> 구현만 다름). "그건 Cilium 얘기"라는 반박엔 이렇게 답한다.
> 단, **정직한 한계**: Calico의 egress 정책 표현력엔 제약이 있어(도메인 기반 egress 등 일부 기능 미지원) 실제 강제는
> label-selector만으로 끝나지 않고 **노드 라우팅·egress 노드 한정 NAT에 더 의존**하게 된다([Egress 개념 정본 §02
> 강제 계층](ref__src-egress-gateway.html) 명시). 즉 "Calico 단독으로 끝"은 *label-selector 신원 식별* 차원에서
> 맞지만, FQDN/도메인 단위 강제까지 필요해지면 Calico만으로는 부족할 수 있다 — cost-parity 논증은 *워크로드 식별*에
> 한정될 때 성립한다.
---
## 핵심 정리
- **멘탈모델:** egress 보안 = 식별 + 강제. **강제는 어차피 chokepoint(egress gateway)에서** 일어나 양 패턴이 공유한다. 패턴 선택은 *식별* 한 축뿐 — mTLS handshake(SPIFFE cert) vs Calico pod-selector(커널 endpoint).
- **Calico pod-selector는 그 자체로 비-핸드셰이크 신원 메커니즘**이다. `app == 'payment'`는 pod가 주장하는 헤더가 아니라 Calico가 endpoint(IP↔pod)에 묶어 커널에서 강제하는 라벨 — 사칭하려면 노드 컴프로마이즈가 필요하다.
- **중복 구매 논증:** HTTPS over mTLS를 써도 sidecar 우회를 막으려면 Calico NetworkPolicy가 어차피 필요하고(Istio 공식이 못박음), 그 정책이 이미 "누가 나가나"를 강제하므로 mTLS 신원 레이어는 같은 일을 한 번 더 하는 중복이다.
- **노드 신뢰 위협모델에선 두 방식의 보안 하한이 같이 무너진다.** 노드가 털리면 SDS로 내려온 mTLS 개인키도 같이 털리므로 — 노드를 신뢰하면 둘 다 안전, 안 하면 둘 다 무너짐 → mTLS 추가이득 ~0.
- **5개 체크리스트가 전부 Yes(SA 불필요·노드 신뢰·Calico 운영·파트너 감사 IP로 충분·L7 불필요)면 passthrough + Calico**가 이중 TLS와 동일 결과를 더 싸게 낸다. 검증은 "payment는 200, 나머지는 timeout(커널 drop)".
- **단, FQDN/도메인 단위 강제까지 필요하면** Calico 표현력 한계로 부족할 수 있다(§7) — cost-parity는 *워크로드 식별*에 한정될 때 성립.
---
## What you might be missing — 이 논증이 *깨지는* 경계
정직하게: 아래 셋 중 하나라도 해당하면 근사가 무너지고 HTTPS over mTLS가 정답이 된다. 미리 알고 가야 토론에서 안 밀린다. 공통 패턴은 **"식별의 신뢰 뿌리가 노드/플랫폼팀 밖으로 나가는 순간"** 이다 — 그때만 cert 기반 SPIFFE가 본질적으로 더 강하다.
- **NetworkPolicy를 신뢰할 수 없는 환경**: 멀티테넌트인데 각 팀이 자기 네임스페이스의 Calico 정책을 직접 쓸 수
있다면, pod-selector 강제를 테넌트가 우회/수정 가능 → 그땐 중앙 mesh CA가 보증하는 SPIFFE가 더 강함.
*(우리는 Calico를 플랫폼팀이 단독 관리 → 해당 안 됨)*
- **게이트웨이 *자체 로그*에 호출자 신원을 남겨야 하는 규제**: "egress gateway 액세스 로그에서 호출 SA를 직접
증빙하라"가 요구사항이면 `%DOWNSTREAM_PEER_URI_SAN%`(=mTLS 필요)뿐. source IP 귀속으론 부족.
*(감사 요구 수위가 IP면 해당 안 됨)* — 신원 로깅 메커니즘: [SPIFFE 신원](../istio/sec__note-mtls-spiffe-identity.html)
- **trust-domain federation / 외부가 SPIFFE를 실제로 검증**: 멀티클러스터에서 신원을 cert로 전파해야 하면 mTLS.
*(단일 클러스터면 해당 안 됨)*
**결론**: 우리 환경(단일 클러스터, Calico 플랫폼팀 단독관리, 노드 신뢰, 파트너 감사는 IP로 충분, L7 정책 불필요)에선
5개 체크리스트가 전부 Yes이므로 **passthrough + Calico가 HTTPS over mTLS와 동일 결과를 더 싸게** 낸다. 이중 TLS의
추가 비용(handshake 2회·포트분리 함정·L7 사각)은 우리 위협모델에서 **보안 이득 0에 가깝다.**
---
## 결정 후기 (2026-06-10)
이 논쟁은 결론이 났다. 요건을 **Q1(외부행 유일 경로 강제)** 과 **Q2(워크로드별 최소권한 + 주체 식별 감사)** 로 분리했을 때, 프로덕션(PCI-DSS IDC) 보안 요건에 Q2가 포함되는 것으로 판단되어 **mTLS Passthrough(ISTIO_MUTUAL)가 채택**되었다 — 비교표와 채택 근거는 [도입 가이드 (사내 공유본)](cfg__guide-adoption-passthrough-vs-mtls.html). 본 문서의 논증은 기각된 게 아니라 **적용 조건이 명확해진 것**이다: 위 체크리스트가 전부 Yes인 환경(Q1까지만 요구, 단일 클러스터·신뢰 노드·CNI 식별로 충분)에서는 여전히 이 경로가 더 싸고 옳다.
---
## 8. 참조
**아카이브 내부 (대척점·근거)**
- [Egress Gateway 도입 가이드 (사내 공유본)](cfg__guide-adoption-passthrough-vs-mtls.html) — 이 논쟁의 **최종 결정 문서** (mTLS Passthrough 채택, Q1/Q2 분리 프레임)
- [HTTPS over mTLS 구조 정본](id__src-https-over-mtls.html) — 본 문서가 반대하는 구조의 상세
- [Egress mTLS 리포트 — 실측](rpt__report-2026-06-08_egress-mtls.html) · [Egress Gateway 개념 정본 §02 강제 계층](ref__src-egress-gateway.html)
- [HTTPS passthrough 가이드](cfg__guide-gateway-https.html) · [Egress 운영 정본](ref__src-operations.html)
- [AuthorizationPolicy 멘탈모델](../istio/sec__src-authorizationpolicy-mental-model.html) · [SPIFFE 신원](../istio/sec__note-mtls-spiffe-identity.html)
- [sidecar scope](mm__src-sidecar-scope.html) · [sidecar scope 노트](mm__note-sidecar-scope.html) — exportTo/scope 격리
**외부**
- ↗ [Calico NetworkPolicy (egress rules)](https://docs.tigera.io/calico/latest/network-policy/get-started/calico-policy/calico-network-policy)
- ↗ [Istio: Security Best Practices — egress는 Istio 단독 강제 불가](https://istio.io/latest/docs/ops/best-practices/security/)
- ↗ [Istio: ServiceEntry exportTo](https://istio.io/latest/docs/reference/config/networking/service-entry/)
**외부 — 실증 사례(§7 조사 출처)**
- ↗ [Cilium: Egress Gateway use cases (telecom zero-trust, Corner Banca 스위스은행)](https://cilium.io/use-cases/egress-gateway/)
- ↗ [Cilium: DNS/FQDN-based egress policy](https://docs.cilium.io/en/stable/security/dns/) · ↗ [Cilium: identity-based security model](https://github.com/cilium/cilium)
- ↗ [Istio: Egress Gateways — "cannot securely enforce" → NetworkPolicy 필요](https://istio.io/latest/docs/tasks/traffic-management/egress/egress-gateway/)
- ↗ [Tetrate: enforce egress with authorization policies](https://tetrate.io/blog/istio-how-to-enforce-egress-traffic-using-istios-authorization-policies) · ↗ [Sysdig: namespace는 soft boundary](https://www.sysdig.com/blog/multi-tenant-isolation-boundaries-kubernetes)