Lionel Blog

The road is under your feet, the heart looks to the distance

서비스 간 인증 및 권한 부여

사용자로부터의 접근 요청 외에도, 마이크로서비스 애플리케이션 내의 각 마이크로서비스는 서로 많은 접근을 합니다. 다음 시나리오를 포함합니다.

  • 사용자 간접적으로 트리거되는 마이크로서비스 간 상호 접근
    예를 들어 온라인 상점 애플리케이션에서 사용자가 장바구니 마이크로서비스에 접근하여 결제할 때, 장바구니 마이크로서비스는 사용자 등급 마이크로서비스에 접근하여 사용자의 회원 등급을 얻어 사용자가 받을 수 있는 쇼핑 할인을 확인해야 할 수 있습니다.
  • 사용자 트리거가 아닌 마이크로서비스 간 상호 접근
    예를 들어 데이터 동기화 또는 백그라운드 정기 작업으로 인한 마이크로서비스 간 상호 접근.

애플리케이션 시스템의 데이터 민감도에 따라 시스템 내 마이크로서비스 간 상호 접근에 대해 다른 보안 요구 사항이 있을 수 있습니다.

마이크로서비스 간 상호 접근에 대한 보안 제어 없음

일부 시나리오에서는 동일한 애플리케이션 내 마이크로서비스 간의 상호 접근이 모두 신뢰할 수 있다고 가정할 수 있습니다. 이 경우 애플리케이션은 내부 네트워크의 방화벽 및 기타 네트워크 보안 조치에 의존하여 보안을 보장합니다. 이 경우 침입자가 내부 네트워크에 침입한 후에는 보호 조치가 없습니다. 침입자는 통신 내용을 도청하거나, 통신 데이터를 위조 및 수정하거나, 심지어 합법적인 마이크로서비스인 것처럼 가장하여 통신하는 등 마이크로서비스 간 통신에 대한 일반적인 중간자 공격을 수행할 수 있습니다.

서비스 계정(Service Account)을 사용한 보안 제어

“내부 네트워크의 마이크로서비스 간 모든 통신은 신뢰할 수 있다"는 가정은 일부 시나리오에서는 성립하지 않습니다. 특히 마이크로서비스에 사용자 정보와 같은 매우 중요한 데이터가 저장되어 있는 경우 더욱 그렇습니다. 민감한 정보를 내부 공격에 직접 노출하는 것은 매우 위험합니다. 이 문제를 해결하는 한 가지 방법은 서비스 계정을 사용하여 마이크로서비스 간의 상호 접근을 제어하는 것입니다.

사용자 권한 제어의 일반적인 방법은 “사용자 계정(User Account)“을 사용하여 시스템 사용자를 식별하고, 이에 대한 신원 인증 및 작업 권한 부여를 수행하는 것입니다. 유사하게, 시스템의 각 서비스에 대해서도 계정을 생성할 수 있으며, 이를 “서비스 계정(Service Account)“이라고 합니다. 이 서비스 계정은 마이크로서비스의 신원을 나타내며, 해당 마이크로서비스가 시스템의 다른 마이크로서비스에 접근할 수 있는 권한, 예를 들어 어떤 마이크로서비스의 어떤 리소스에 어떤 작업을 수행할 수 있는지 등을 제어하는 데 사용됩니다. 한 마이크로서비스가 다른 마이크로서비스에 접근할 때, 접근되는 마이크로서비스는 접근자의 서비스 계정을 확인하여 신원과 리소스 작업 권한을 확인해야 합니다.

SPIFEE 표준

Secure Production Identity Framework For Everyone (SPIFFE)는 서비스 간 상호 신원 식별을 위한 표준 세트로, 주로 다음 내용을 포함합니다.

  • SPIFFE ID 표준, SPIFFE ID는 서비스의 고유 식별자로, “Uniform Resource Identifier (URI)” 형식으로 구현됩니다.
  • SVID(SPIFFE Verifiable Identity Document) 표준, SPIFFE ID를 암호화된 검증 가능한 문서로 인코딩합니다.
  • SVID 발급/철회를 위한 API 표준 세트.

SPIFFE SVID는 현재 X.509 디지털 인증서로 구현되며, X.509 SVID에서는 X.509 디지털 인증서의 SAN(Subject Alternative Name) 확장 필드를 사용하여 SPIFFE ID를 저장합니다.

Istio Auth 오픈 소스 구현

Istio 서비스 메시 프로젝트의 Auth 구성 요소는 SPIFFE 표준을 구현하여 메시 내 서비스에 SPIFFE SVID 표준을 준수하는 인증서를 발급하고, 서비스에 신원 인증, 세분화된 작업 권한 부여 및 통신 암호화를 제공합니다. Istio의 아키텍처는 아래 그림과 같습니다.

Istio Auth는 Kubernetes의 서비스 계정을 서비스 식별자로 사용하며, SPIFFE ID 형식은 spiffe:///ns//sa/입니다. 각 구성 요소는 다음과 같습니다.

  • domain 도메인 이름
  • namespace Kubernetes 서비스 계정이 있는 네임스페이스
  • serviceaccount Kubernetes에 정의된 서비스 계정 이름

Istio Auth는 인증서 발급을 위한 CA를 제공합니다. 서비스 배포 시 CA는 Kubernetes API 서버를 감시하고, 클러스터의 각 서비스 계정에 대해 한 쌍의 키와 인증서를 생성합니다. Pod가 생성될 때, Kubernetes는 해당 Pod와 연결된 서비스 계정에 따라 키와 인증서를 Kubernetes Secrets 리소스 형태로 Pod의 Volume으로 로드하여 Envoy가 사용할 수 있도록 합니다.

서비스 런타임 시, 서비스 간 통신은 Envoy에 의해 가로채지며, Envoy는 인증서를 사용하여 서비스 간 양방향 SSL 핸드셰이크를 통해 통신하는 두 서비스의 신원을 확인하고 암호화된 통신 채널을 제공합니다.

사용자 신원을 통한 보안 제어

서비스 계정을 사용하여 서비스 간 상호 작용에 대한 권한을 부여하는 것은 사용자 단위의 접근 권한을 제어할 수 없으며, 이는 일부 시나리오에서 데이터 유출 문제를 야기할 수 있습니다.

예를 들어 온라인 상점 애플리케이션에서 사용자가 장바구니 마이크로서비스에 접근하여 결제할 때, 장바구니 마이크로서비스는 다른 마이크로서비스의 사용자 구매 기록 데이터에 접근해야 합니다. 장바구니 마이크로서비스에 대해서만 서비스 계정을 사용하여 보안 제어를 수행하면, 사용자 A가 장바구니 마이크로서비스를 통해 백엔드 마이크로서비스에 사용자 B의 구매 기록 데이터를 가져오도록 요청할 위험이 있습니다. 백엔드 마이크로서비스는 요청을 시작한 사용자가 누구인지 알 수 없으므로, 장바구니 마이크로서비스가 요청한 사용자 구매 기록 데이터를 무분별하게 반환할 것입니다.

해결책은 사용자 정보를 사용자가 직접 접근하는 첫 번째 마이크로서비스에서 호출 체인의 모든 마이크로서비스로 전달하는 것입니다. 호출 체인의 모든 마이크로서비스는 해당 사용자 정보를 사용하여 사용자가 접근할 수 있는 리소스를 판단합니다. 대규모 마이크로서비스 시스템에서는 호출 체인이 매우 길어질 수 있어 이 솔루션의 구현이 복잡해집니다.

우리는 애플리케이션의 사용 시나리오와 각 마이크로서비스의 데이터 민감도에 따라 서비스 간 보안 구현 방식을 결정해야 합니다.