사전 서비스 신원
개념

서비스 신원

gabury1고친 사람 github-actions[bot]

서비스 신원은 한 서비스가 다른 서비스에게 자기가 누구인지 밝히고 그 말을 증명하게 해 줍니다. 사람이 로그인할 때 아이디와 비밀번호를 쓰듯 서비스에도 자기 이름과 그 이름을 뒷받침할 증거가 필요합니다. 요청을 받는 쪽은 이 이름을 보고 누가 불렀는지 알아낸 뒤 들여보낼지 정합니다. 요즘은 서비스가 뜰 때 발급자가 이 이름과 증거를 자동으로 쥐여 줍니다. 발급자는 이런 증거를 만들어 서비스에 내주는 프로그램입니다.

쉽고 빠른 이해

서비스 신원은 서비스가 「나는 주문 서비스다」라고 말하고 그 말을 증명하게 해 줍니다. 주문 서비스가 결제 서비스를 부를 때 자기 이름이 담긴 자격 증명(이름이 진짜라는 증거)을 함께 내미는 식입니다.

이게 없으면 결제 서비스는 요청이 어디서 왔는지 주소로만 짐작해야 합니다. 사내망에 들어온 침입자도 주문 서비스인 척할 수 있습니다.

  1. 서비스가 뜨면 발급자가 어떤 서비스가 떴는지 확인하고 수명이 짧은 자격 증명을 줍니다
  2. 서비스는 다른 서비스를 부를 때마다 이 자격 증명을 내밉니다
  3. 받는 쪽은 발급자의 서명을 확인해 이름을 읽고, 그 이름에 허락된 일인지 따집니다

대가는 자격 증명을 내주는 발급자가 늘 살아 있어야 한다는 것입니다. 발급자가 멈추면 새로 뜨는 서비스가 이름을 못 받습니다.

서비스가 몇 개뿐이고 한 팀이 한 네트워크에서 굴리면 미뤄도 됩니다. 여러 팀이 나눠 맡거나 여러 클라우드로 퍼지면 들입니다.

상세

회사 건물에 들어갈 때는 사원증을 찍습니다. 사원증에는 이름과 부서가 적혀 있고 회사가 만들어 준 표시가 있습니다. 경비원은 얼굴을 몰라도 사원증만 보고 사람을 들여보냅니다.

서비스 신원은 이 사원증을 사람 대신 서비스에 주는 것입니다. 여기서 서비스는 요청을 받아 일을 해 주는 서버 프로그램 하나를 말합니다. 「주문 서비스」·「결제 서비스」처럼 이름이 붙습니다. 다른 서비스가 네트워크 너머에서 부릅니다.

서비스 신원은 두 조각으로 이루어집니다. 하나는 「주문 서비스」처럼 그 서비스를 가리키는 이름입니다. 다른 하나는 그 이름이 진짜라는 증거입니다. 이것을 자격 증명이라고 부릅니다. 이름만으로는 누구나 사칭할 수 있어서 자격 증명이 늘 함께 갑니다.

자격 증명을 만들어 내주는 프로그램이 발급자입니다. 발급자는 자격 증명에 서명을 붙입니다. 서명은 발급자만 만들 수 있는 표시라서 남이 자격 증명을 위조하지 못합니다. 사원증에 찍힌 회사 표시가 바로 이 서명에 해당합니다.

서비스를 잘게 나눈 마이크로서비스 구조에서는 요청 하나가 서비스 여럿을 거칩니다. 받는 쪽은 매번 「누가 불렀나」를 알아야 합니다. 그 물음에 답하는 일이 인증입니다. 서비스 신원은 서비스끼리 인증할 때 내미는 이름과 그 증거입니다.

아래 소절은 먼저 이런 이름이 왜 따로 필요한지 봅니다. 이어서 이름을 받는 흐름, 자격 증명의 두 종류, 이름의 생김새를 차례로 봅니다. 끝으로 신원 다음에 오는 일과 들이는 때를 봅니다.

주소로 믿던 방식의 한계

예전에는 서비스끼리 서로를 IP 주소(Internet Protocol address, 인터넷 프로토콜 주소)로 알아봤습니다. 「10.0.3.7 에서 온 요청은 주문 서버다」라고 정해 두는 식입니다. 바깥에서 오는 요청은 방화벽이 막았습니다. 안쪽 주소는 믿었습니다.

이 방식은 두 군데서 깨집니다. 첫째, 요즘 서비스는 컨테이너라는 작은 실행 단위로 떴다가 사라지기를 되풀이합니다. 주소가 그때마다 바뀝니다. 방금 주문 서비스가 쓰던 주소를 다음에는 다른 서비스가 받습니다.

둘째, 안쪽 네트워크에 한 번 들어온 공격자는 믿을 만한 주소를 손에 넣습니다. 서버 하나가 뚫리면 거기서 나가는 요청이 다른 서비스 눈에는 정상 요청과 똑같아 보입니다.

이 문제 때문에 네트워크 위치를 믿지 말고 요청마다 상대를 확인하자는 생각이 나왔습니다. 이 생각이 제로 트러스트입니다. 서비스 신원은 그 확인에 쓰는 이름과 증거입니다.

사람의 신원과 다른 점

서비스에도 아이디와 비밀번호를 주면 되지 않을까요. 사람의 로그인과 견주어 보면 서비스 쪽이 무엇이 다른지 보입니다.

사람의 신원 서비스 신원
증거를 내미는 쪽 사람이 직접 입력한다 프로그램이 스스로 내민다
한 이름을 쓰는 수 한 사람 같은 서비스를 여러 벌 띄운 전부
증거를 처음 받는 때 가입할 때 한 번 서비스가 뜰 때마다
증거의 수명 사람이 바꿀 때까지 짧게 잡고 자동으로 바꾼다

가장 큰 차이는 입력할 사람이 없다는 것입니다. 비밀번호나 API 키(Application Programming Interface key, 서비스를 부를 때 내미는 비밀 문자열)를 서비스에 주려면 코드나 설정 파일에 적어 둬야 합니다. 그렇게 적힌 비밀은 저장소나 로그로 새기 쉽습니다. 한 번 새면 누가 바꾸기 전까지 계속 쓸 수 있습니다.

같은 서비스가 여러 벌 뜬다는 점도 다릅니다. 이렇게 똑같이 띄운 한 벌을 인스턴스라고 합니다. 주문 서비스를 열 벌 띄우면 열 인스턴스가 모두 「주문 서비스」라는 한 이름을 씁니다. 받는 쪽이 알고 싶은 것은 몇 번째 인스턴스인지가 아니라 어느 서비스인지이기 때문입니다.

신원을 받는 흐름

이 소절은 서비스가 이름과 자격 증명을 어떻게 손에 넣는지 봅니다. 등장하는 쪽은 셋입니다. 이름을 받는 서비스, 자격 증명을 내주는 발급자, 요청을 받는 상대 서비스입니다.

발급자는 보통 회사가 미리 깔아 둡니다. 여러 서비스 팀이 함께 쓰는 바탕을 만드는 플랫폼 엔지니어링 팀이 이것을 운영하는 경우가 많습니다. 덕분에 서비스 팀은 자격 증명을 손으로 신청하지 않습니다.

sequenceDiagram
    participant 서비스 as 주문 서비스
    participant 발급자
    participant 상대 as 결제 서비스
    Note over 서비스: 막 떴다
    서비스->>발급자: 자격 증명을 청한다
    Note over 발급자: 어디서 무엇이 떴는지 확인한다
    발급자-->>서비스: 이름이 담긴 자격 증명
    서비스->>상대: 요청과 자격 증명
    Note over 상대: 서명을 확인하고 이름을 읽는다
    상대-->>서비스: 허락된 일이면 응답

그림에서 걸리는 대목은 발급자가 확인하는 단계입니다. 발급자는 무엇을 보고 「이게 주문 서비스가 맞다」고 믿을까요. 자격 증명을 받으려고 또 다른 비밀을 내밀게 하면, 그 비밀은 어디서 받느냐는 물음이 다시 생깁니다. 맨 처음 비밀 하나를 어떻게 건네느냐는 이 물음을 흔히 secret zero 문제라고 부릅니다.

그래서 발급자는 비밀 대신 실행 환경을 봅니다. 이 프로그램이 어느 기계, 어느 컨테이너에서 어떤 실행 파일로 떴는지를 서비스를 띄운 쪽, 곧 컨테이너를 실행하고 관리하는 시스템에게 직접 물어 확인합니다. 서비스가 무엇을 아는지가 아니라 어디서 어떻게 떴는지로 신원을 정하는 것입니다. 이 확인을 영어로 attestation 이라고 부릅니다.

자격 증명의 두 종류

자격 증명으로는 두 가지를 씁니다. 인증서와 토큰입니다. 둘 다 발급자가 이름에 서명했다는 점은 같습니다. 누가 훔쳐 갔을 때 무슨 일이 생기는지가 다릅니다.

인증서를 보려면 열쇠 한 쌍부터 알아야 합니다. 공개키는 남에게 나눠 주는 열쇠입니다. 그 짝인 개인 키는 서비스 혼자만 쥡니다. 개인 키로 만든 서명은 짝인 공개키로 맞는지 확인할 수 있습니다.

인증서는 서비스 이름과 그 서비스의 공개키를 한 문서에 묶고 발급자가 서명한 것입니다. 인증서 쪽에서는 발급자를 인증 기관이라는 이름으로 부릅니다.

서비스는 자기 개인 키로 서명을 만들어 보여야 상대가 믿습니다. 인증서만 내밀어서는 안 됩니다. 개인 키는 서비스 밖으로 나가지 않으니 인증서 파일만 훔쳐서는 행세할 수 없습니다.

서비스끼리 쓰는 인증서는 공개 기관이 아니라 회사가 직접 운영하는 사설 인증 기관이 서명합니다. 공개 기관은 누구나 접속하는 웹사이트의 인증서를 서명하는 곳입니다. 회사 안 서비스의 이름은 바깥에서 알아볼 필요가 없어서 회사가 스스로 인증 기관을 세웁니다.

인증서는 통신을 암호화하는 규약인 TLS(Transport Layer Security, 전송 계층 보안)로 연결을 맺을 때 주고받습니다. 웹사이트 접속에서는 서버만 인증서를 내밉니다. 서비스끼리는 양쪽이 다 내밀어 서로를 확인합니다. 이 방식이 상호 TLS입니다.

토큰은 발급자가 서명한 짧은 문자열입니다. 안에 이름과 만료 시각이 들어 있습니다. 받는 쪽은 발급자의 서명만 확인하면 됩니다. 흔히 JWT(JSON Web Token)를 씁니다. JWT 는 JSON(JavaScript Object Notation)이라는 데이터 표기 형식에 서명을 붙인 토큰입니다.

토큰은 가진 쪽이 곧 주인으로 통합니다. 그래서 누가 토큰을 가로채면 만료될 때까지 남이 다시 쓸 수 있습니다. 이렇게 가로챈 증거를 다시 내미는 공격을 재전송 공격이라고 합니다. 인증서는 개인 키가 있어야 쓸 수 있어서 이 공격에 더 강합니다.

표에 앞서 낱말 하나를 풉니다. 프록시는 요청을 받아 다른 곳으로 넘겨 주는 중계 서버입니다. 요청이 프록시를 지나면 암호화 연결이 프록시에서 끝납니다. 프록시는 다음 서비스로 새 연결을 맺습니다.

아래 표는 인증서와 토큰을 나란히 놓은 것입니다. 마지막 줄은 어떤 길에 어느 쪽이 맞는지를 보입니다.

인증서 토큰
내미는 때 연결을 맺을 때 한 번 요청마다 헤더에 실어서
받는 쪽이 확인하는 것 서명과 개인 키를 쥐었는지 서명과 만료 시각
가로채이면 개인 키 없이는 못 쓴다 만료까지 남이 쓸 수 있다
맞는 길 서비스끼리 바로 잇는 연결 연결이 프록시에서 끝나고 새로 맺히는 길

연결이 프록시에서 새로 맺히면 인증서로 확인한 상대는 프록시가 됩니다. 토큰은 요청에 실려 가므로 프록시를 지나도 원래 서비스의 이름이 남습니다.

짧은 수명과 자동 교체

서비스 신원의 자격 증명은 수명을 짧게 잡습니다. 발급자가 자동으로 새것을 내주니 사람이 손으로 갱신할 일이 없기 때문입니다. 수명이 짧으면 새어 나간 자격 증명도 금방 쓸모를 잃습니다.

대가는 모든 서비스가 발급자에게 기댄다는 것입니다. 발급자가 멈추면 새로 뜨는 서비스는 이름을 못 받습니다. 이미 떠 있는 서비스도 자격 증명이 만료되면 통신이 끊깁니다. 그래서 발급자는 여러 벌로 띄우고 따로 지켜봅니다.

갱신을 서비스 코드가 직접 하지 않게 서비스 메시가 맡기도 합니다. 서비스 메시는 서비스마다 곁에 작은 프록시를 붙여 통신을 대신 처리하는 계층입니다. 이 프록시가 자격 증명을 받아 오고 상호 TLS 연결도 대신 맺습니다.

이름의 생김새

이름은 사람이 읽을 수 있는 문자열입니다. 이름 짓는 법을 표준으로 정해 둔 것으로 SPIFFE(Secure Production Identity Framework For Everyone)가 있습니다. 아래는 그 체계의 이름 하나를 세 조각으로 나눠 본 것입니다.

spiffe://          // 체계 표시
acme.com           // 신뢰 도메인
/billing/payments  // 도메인 안의 서비스

셋을 이어 붙이면 spiffe://acme.com/billing/payments 한 줄이 됩니다. 맨 앞은 이 문자열이 SPIFFE 이름이라는 표시입니다.

가운데 신뢰 도메인은 이 이름을 보증하는 조직의 범위입니다. 같은 신뢰 도메인 안의 서비스끼리는 같은 발급자의 서명을 믿습니다. 뒤쪽 경로는 그 안에서 서비스를 가립니다.

이 이름은 앞에서 본 인증서나 JWT 안에 담겨 전달됩니다. 이름 자체는 비밀이 아닙니다. 증명은 이름을 감싼 서명이 맡습니다.

신원 다음에 오는 일

신원은 「누가 불렀나」까지만 답합니다. 「그 일을 해도 되나」는 따로 정합니다. 이 일이 인가입니다. 「주문 서비스는 결제 요청은 부를 수 있지만 환불은 못 부른다」 같은 규칙을 이름에 걸어 둡니다.

필요한 만큼만 허락하자는 원칙이 최소 권한입니다. 서비스 신원이 있어야 이 원칙을 서비스 하나하나에 걸 수 있습니다. 주소로 믿던 때는 「안쪽이면 다 된다」 말고는 가를 기준이 마땅치 않았습니다.

이름은 기록에도 남습니다. 어느 서비스가 언제 무엇을 불렀는지가 감사 로그에 서비스 이름으로 찍힙니다. 사고가 나면 이 기록으로 어디서 시작됐는지 거슬러 올라갑니다.

들이는 때와 미루는 때

서비스가 몇 개뿐이고 한 팀이 한 네트워크 안에서 굴리면 방화벽과 공유 비밀로 버티기도 합니다. 발급자를 세우고 지키는 품이 얻는 것보다 클 수 있기 때문입니다.

서비스가 늘어 여러 팀이 나눠 맡거나 여러 클라우드와 데이터센터에 걸치면 사정이 달라집니다. 주소도 비밀도 믿기 어려워집니다. 누가 무엇을 불렀는지 가려야 할 일도 늘어납니다. 이때 서비스 신원을 들입니다.

관련 항목

서비스 신원이 속하는 상위 분류

인증 · 인증과 인가 · 신원 및 접근 관리 · 제로 트러스트 · 정보 보안

서비스 신원을 증명하는 수단

자격증명 · 인증서 · X.509 · 상호 TLS · TLS · 토큰 · JWT · 공개키 · 개인 키

서비스 신원을 내주고 갱신하는 기반

인증 기관 · 사설 인증 기관 · 인증서 발급 · 인증서 자동 갱신 · 시크릿 관리 · 서비스 메시 · 플랫폼 엔지니어링

서비스 신원의 이름을 정하는 표준

SPIFFE · SPIFFE ID · SVID · 신뢰 도메인

서비스 신원을 구현·채택한 제품

SPIRE · Istio · Linkerd · Kubernetes · AWS IAM

서비스 신원을 받는 주체

서비스 · 마이크로서비스 · 인스턴스 · 컨테이너 · 파드

서비스 신원이 대신하는 신뢰 수단

IP 주소 · 방화벽 · 네트워크 분할 · API 키 · 비밀번호 · 공유 비밀

서비스 신원 다음에 이어지는 판단

인가 · 최소 권한 · 역할 기반 접근 제어 · 접근 제어 · 감사 로그

서비스 신원이 막는 공격

사칭 · 재전송 공격 · 중간자 공격 · 자격 증명 유출 · 측면 이동

서비스 신원과 맞세워지는 사람의 신원

사용자 계정 · 신원 증명 · 다중 인증 · 싱글 사인온

다른 이름: service identity · workload identity · 워크로드 신원 · 서비스 아이덴티티