Istio mTLS 설정: Auto mTLS·PeerAuthentication STRICT·검증 순서

반응형

mTLS(mutual TLS)는 connection의 양쪽이 certificate를 제시하고 trust chain과 identity를 검증하는 TLS 방식이다. 암호화·무결성뿐 아니라 peer authentication을 제공한다. 그러나 mTLS를 켰다고 호출 권한까지 자동으로 정해지는 것은 아니다. 누구인지 확인하는 authentication과 무엇을 허용할지 정하는 authorization을 분리해야 한다.

Istio에서는 inbound 요구 조건, outbound TLS origination, workload mode를 나눠 봐야 한다. PeerAuthentication 하나와 DestinationRule 하나를 붙인 뒤 ‘모든 traffic이 안전하다’고 결론 내리면 migration과 예외 경로를 놓치기 쉽다.

Istio가 mTLS에서 맡는 일

Istio는 workload identity에 certificate를 발급하고 proxy 또는 ambient data plane이 service-to-service connection에서 mTLS를 사용하도록 한다. certificate의 identity는 Kubernetes service account와 trust domain 같은 workload identity에 연결된다.

이 구조가 줄여 주는 운영 부담은 크지만 다음은 별도 설계가 필요하다.

  • 어느 namespace와 workload가 mesh에 실제 참여하는가
  • plaintext bypass를 거부할 것인가
  • 어떤 source identity가 어떤 destination operation을 호출할 수 있는가
  • CA·trust domain·multi-cluster trust를 어떻게 관리하는가
  • certificate rotation과 control-plane 장애를 어떻게 관찰하는가
  • ingress·egress·external service의 TLS 경계가 어디인가

sidecar mode에서는 proxy 간 leg가 mTLS여도 application↔local proxy leg를 같은 암호화 connection으로 표현해서는 안 된다. ambient mode의 HBONE tunnel과 sidecar mode의 connection topology도 구분한다.

Auto mTLS와 PERMISSIVE의 의미

sidecar mode에서 explicit TLS setting이 없는 경우 Istio의 Auto mTLS는 destination이 mesh workload인지 판단해 가능한 곳에는 Istio mutual TLS를 보내고, mesh 밖 workload에는 plaintext를 보낼 수 있다. server side의 기본 PERMISSIVE는 mTLS와 plaintext를 모두 받을 수 있다.

즉 ‘proxy가 있는 workload 사이에서는 자동 mTLS를 사용한다’와 ‘plaintext connection을 거부한다’는 다른 상태다. 후자를 강제하려면 scope에 맞는 PeerAuthenticationSTRICT가 필요하다.

ambient mode에서는 ztunnel 사이 traffic에 HBONE과 mTLS가 사용되고 DISABLE mode는 지원되지 않는다. STRICT는 mesh를 우회한 plaintext connection을 막는 데 의미가 있다.

PeerAuthentication은 Inbound 요구 조건이다

namespace 전체에서 mTLS만 받도록 하려면 다음처럼 정책을 정의할 수 있다.

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: default
  namespace: payments
spec:
  mtls:
    mode: STRICT

이 YAML은 적용 예시가 아니라 review할 desired state다. 실제 적용 전에는 현재 Istio version, root namespace, sidecar·ambient mode, legacy client, policy precedence를 확인한다.

  • selector가 없으면 같은 namespace의 workload 전체에 적용된다.
  • mesh-wide policy는 설치의 root namespace에 두고 selector를 사용하지 않는다.
  • workload selector는 같은 namespace의 label과 일치해야 한다.
  • portLevelMtls의 port는 Kubernetes Service port가 아니라 workload port다.
  • 더 구체적인 policy와 parent setting의 inheritance를 확인한다.

DestinationRule을 언제 쓰는가

PeerAuthentication은 server가 무엇을 받을지, DestinationRule의 TLS setting은 client proxy가 destination으로 무엇을 보낼지를 다룬다. 과거 예제처럼 모든 service에 다음 설정을 반복할 필요는 없다.

trafficPolicy:
  tls:
    mode: ISTIO_MUTUAL

일반적인 in-mesh traffic은 Auto mTLS가 처리할 수 있다. explicit DestinationRule은 host scope와 subset, external service TLS origination, non-default requirement를 이해한 경우에 사용한다. 잘못된 DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL 설정은 plaintext, certificate mismatch, double TLS 같은 문제를 만들 수 있다.

특히 application이 이미 TLS를 시작하는 protocol과 proxy가 새 TLS connection을 originate하는 설정을 겹치지 않는지 connection leg별로 그린다.

PERMISSIVE에서 STRICT로 옮기는 순서

  1. Inventory: namespace·workload별 data-plane 참여, service account, port, legacy·external client를 목록화한다.
  2. 현재 policy 확인: mesh·namespace·workload PeerAuthentication, DestinationRule, AuthorizationPolicy의 effective scope를 본다.
  3. PERMISSIVE 관찰: plaintext와 mTLS source, 실패, 예상 밖 identity를 metrics·proxy configuration에서 확인한다.
  4. Canary scope: 작은 namespace나 workload selector에서 STRICT를 검증한다.
  5. Negative test: mesh 밖 또는 certificate 없는 client가 실제로 거부되는지 확인한다.
  6. Authorization 추가: 허용할 principal·namespace·operation을 최소 권한으로 정의한다.
  7. 확장과 rollback: SLO·error·latency, certificate issue·rotation signal을 보며 범위를 넓힌다.

kubectl apply부터 시작하면 legacy path를 outage로 발견하게 된다. 먼저 현재 traffic이 정말 mTLS인지, STRICT 전환 뒤 어떤 client가 실패할지를 증거로 만든다.

무엇으로 검증할까

  • istioctl x describe pod와 proxy configuration으로 policy 적용 상태를 본다.
  • Istio telemetry의 connection_security_policy="mutual_tls"과 source·destination identity를 확인한다.
  • sidecar·ambient mode에 맞는 official verification command를 사용한다.
  • plaintext negative test와 정상 mTLS positive test를 모두 수행한다.
  • application error, p95·p99 latency, CPU, certificate expiration·rotation failure를 전후 비교한다.

X-Forwarded-Client-Cert 같은 header 하나만 security proof로 쓰지 않는다. gateway나 proxy가 header를 sanitize·rewrite하는 경계와 trusted hop을 확인한다.

mTLS가 해결하지 않는 것

  • compromised workload가 가진 유효 identity의 misuse
  • overly broad AuthorizationPolicy
  • application-level injection·broken access control
  • plaintext인 local leg나 mesh 밖 egress
  • sensitive data가 log·trace에 남는 문제
  • 잘못된 trust domain·CA federation

그래서 mTLS는 zero trust 전체가 아니라 workload identity와 transport protection의 한 층이다. network policy, authorization, secret handling, application validation, audit를 함께 둔다.

Kubernetes control plane과 data plane의 큰 구조는 Kubernetes control plane·data plane, network 문제 검증 흐름은 Kubernetes network troubleshooting로 이어갈 수 있다.

자주 묻는 질문

PeerAuthentication STRICT만 적용하면 client 설정도 끝나나

in-mesh proxy는 Auto mTLS로 맞출 수 있지만 explicit DestinationRule, legacy client, unsupported traffic, scope 문제가 있을 수 있다. STRICT 전에 실제 client path를 검증한다.

mTLS면 AuthorizationPolicy가 필요 없나

필요하다. mTLS는 peer identity를 인증한다. 어떤 identity가 어느 workload·method를 호출할 수 있는지는 authorization rule이 정한다.

모든 통신 구간이 암호화되나

mode와 topology에 따라 proxy-to-proxy, local application leg, ingress·egress 경계가 다르다. ‘mesh 내부’라는 말보다 connection leg를 그려 확인한다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글