본문 바로가기
클라우드/Istio

내 서비스는 누가 지킬까? Istio의 깐깐한 신원 조회 방법 2가지 🕵️‍♂️

by gasbugs 2025. 11. 28.

복잡하게 얽힌 마이크로서비스(MSA) 환경에서 수많은 서비스들이 서로 통신하고 있습니다. 이때 이런 질문이 떠오릅니다.

"지금 내 서비스에 요청을 보낸 저 녀석, 믿을 수 있는 녀석인가?" 🤔

 

마치 우리 집 현관문처럼, 아무나 들여보내서는 안 되겠죠. 서비스 메시의 대표주자 Istio는 이런 보안 문제를 해결하기 위해 아주 깐깐하고 체계적인 '신원 조회' 시스템을 갖추고 있습니다. 바로 피어 인증(Peer Authentication)요청 인증(Request Authentication)입니다.

 

이 두 가지가 어떻게 우리의 서비스를 안전하게 지켜주는지, 전체적인 그림과 함께 상세히 파헤쳐 보겠습니다.


🗺️ 큰 그림 먼저 보기: 누구를 위한 인증인가?

Istio의 인증 전략을 이해하는 가장 쉬운 방법은 '인증 대상'이 누구인지 구분하는 것입니다.

  1. 서비스 🤝 서비스 (기계 간 통신): 내부에 있는 서비스들끼리 서로를 믿고 통신할 수 있을까?
  2. 사용자 👩‍💻➡️ 서비스 (사람/외부 시스템의 통신): 서비스를 사용하는 최종 사용자나 외부 시스템이 보낸 요청을 믿을 수 있을까?

Istio는 이 두 가지 시나리오에 맞춰 각각 다른 인증 방식을 제공합니다. 바로 이것이 피어 인증과 요청 인증의 핵심적인 차이입니다.

(Source: istio.io)


1️⃣ 피어 인증 (Peer Authentication): "우리끼리는 암호로 말해" 🤫

서비스 메쉬 내부에 있는 워크로드(파드, 서비스)들이 서로 통신할 때 사용하는 인증 방식입니다. 즉, 서비스 간(Service-to-Service) 통신의 신뢰성을 보장하죠.

마치 첩보 영화에서 요원들이 서로를 확인하기 위해 암호를 대는 것과 같습니다. 이 암호가 바로 상호 TLS (mTLS)입니다.

✨ 어떻게 동작하나요? (mTLS)

mTLS는 클라이언트와 서버가 서로에게 인증서를 제시하여 신원을 확인하는 방식입니다.

  1. reviews 서비스가 ratings 서비스에 요청을 보냅니다.
  2. reviews와 ratings는 통신을 시작하기 전, Istio가 발급한 인증서(certificate)를 서로 교환합니다.
  3. 서로의 인증서가 유효한지 확인하고, 신원이 증명되면 안전한 암호화 터널(TLS)을 생성합니다. 🔒
  4. 이 터널을 통해 모든 통신 내용은 암호화되어 안전하게 전달됩니다.

YAML 코드로 살펴보기

PeerAuthentication 정책을 통해 특정 네임스페이스에 mTLS를 강제할 수 있습니다.

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: "default"
  namespace: "production" # 'production' 네임스페이스에 적용
spec:
  mtls:
    mode: STRICT # 오직 mTLS 통신만 허용!
  • mode: STRICT: "암호(mTLS)를 모르는 녀석은 절대 통신 불가!" 라는 의미입니다. production 네임스페이스의 모든 서비스들은 mTLS로만 통신해야 합니다. 일반 텍스트(HTTP) 요청은 차단됩니다.
  • mode: PERMISSIVE: 기존 서비스와의 호환성을 위해 mTLS와 일반 텍스트 통신을 모두 허용하는 모드입니다. 점진적으로 mTLS를 도입할 때 유용합니다.

2️⃣ 요청 인증 (Request Authentication): "신분증(JWT) 좀 보여주시죠?" 🎟️

서비스 메쉬의 입구(Ingress Gateway)에서 최종 사용자(End-User)나 외부 시스템이 보낸 요청을 인증할 때 사용됩니다.

콘서트장에 들어갈 때 입구에서 티켓을 검사하는 것과 같습니다. 이때 사용되는 표준 디지털 티켓이 바로 JWT(JSON Web Token)입니다.

✨ 어떻게 동작하나요? (JWT)

JWT는 사용자의 정보(누구인지, 어떤 권한이 있는지 등)와 서명을 담고 있는 암호화된 토큰입니다.

  1. 사용자가 로그인을 통해 인증 서버로부터 JWT를 발급받습니다.
  2. 사용자는 API를 요청할 때마다 HTTP 헤더(e.g., Authorization: Bearer )에 이 JWT를 포함하여 보냅니다.
  3. Istio Ingress Gateway는 RequestAuthentication 정책에 따라 이 JWT가 유효한지 검증합니다.
  4. 서명이 유효하고, 만료되지 않았으며, 발급자가 신뢰할 수 있다면 요청을 내부 서비스로 전달합니다.

YAML 코드와 Raw 데이터로 살펴보기

RequestAuthentication 정책은 JWT 발급자(issuer)와 공개키(JWKS) 위치를 지정합니다.

apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: "jwt-example"
  namespace: istio-system
spec:
  selector:
    matchLabels:
      istio: ingressgateway
  jwtRules:
  - issuer: "https://accounts.google.com" # JWT 발급자
    jwksUri: "https://www.googleapis.com/oauth2/v3/certs" # 공개키 위치

 

이 정책은 istio-ingressgateway로 들어오는 요청에 대해, 발급자가 https://accounts.google.com인 JWT가 있는지 확인하라는 의미입니다.

 

- 샘플 JWT Raw 데이터:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoidXNlcjEyMyIsImV4cCI6MTY3ODg4NjQwMCwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIn0.SIG_PART

(위 토큰은 3부분으로 구성됩니다: Header.Payload.Signature)

 

- 디코딩된 Payload:

{
  "iss": "https://example.com",
  "sub": "user123",
  "exp": 1678886400,
  "email": "test@example.com"
}

Istio는 이 Payload의 내용을 보고 iss(발급자)가 정책과 일치하는지, exp(만료시간)가 지나지 않았는지 등을 검증합니다.


🤔 흔한 오해 바로잡기

  • "API Key만으로 인증하면 안 되나요?"
    • API Key는 주로 '어떤 애플리케이션'이 요청했는지 식별하는 데 사용됩니다. 반면 JWT는 '어떤 사용자'가 요청했는지, 그 사용자의 역할은 무엇인지 등 훨씬 풍부한 정보를 담을 수 있어 사용자 중심의 인증에 더 적합하고 표준적입니다.
  • "내부망이니까 서비스끼리는 그냥 HTTP로 통신해도 안전하지 않나요?"
    • 절대 아닙니다! 🙅‍♂️ '제로 트러스트(Zero Trust)' 보안 모델에 따르면, 내부 네트워크라고 해서 무조건 신뢰해서는 안 됩니다. 만약 서비스 하나가 해킹당하면, 그 서비스를 통해 내부의 다른 모든 서비스로 공격이 확산될 수 있습니다. 피어 인증(mTLS)은 이런 내부 확산을 막는 가장 중요한 방어선입니다.

🏁 정리하며

Istio의 두 가지 인증 방식을 다시 한번 요약해 보겠습니다.

  • 피어 인증 (Peer Authentication): 서비스 간 통신을 mTLS로 암호화하고 서로의 신원을 확인합니다. (내부 보안 강화🛡️)
  • 요청 인증 (Request Authentication): 최종 사용자의 요청을 JWT로 검증하여 인가된 사용자만 접근하도록 허용합니다. (외부 경계 보안🚪)

이 두 가지 인증 매커니즘은 함께 작동하며, 외부로부터의 침입과 내부에서의 무단 접근을 모두 차단하는 강력한 다층 방어 체계를 구축합니다. Istio를 통해 서비스의 보안을 한 단계 업그레이드해 보세요!