최근 여러 서비스에서 보안 사고가 급증하면서 보안의 중요성이 대두되고 있다. 보안이라는 분야가 워낙 넓지만 그 중에서도 정말 많이 사용되는 것이 HTTP 관련 보안이다. 그래서 이번 글에서는 우리가 필수로 알아야 할 TLS 인증서를 알아보고, Kubernetes 클러스터 내부에서는 TLS 인증서를 어떻게 관리하는지 cert-manager를 통해 살펴보겠다.


TLS 인증서는 서로 믿을 수 있음을 증명하는 증서

우리가 웹 브라우저를 통해 외부 홈페이지, 즉 외부 서비스와 통신할 때는 암호화되지 않은 HTTP보다 보안이 강화된 HTTPS를 사용하는 경우가 많다.

(HTTPS를 사용하는 안전한 홈페이지인지 여부는 우리가 사용하는 웹 브라우저에서 위 사진과 같이 확인할 수 있다.)

HTTPS는 기존 HTTP에 TLS라는 프로토콜을 사용해서 암호화한 것으로, 이 TLS 덕분에 HTTPS는…

  • 외부의 제3자가 전송되는 데이터를 보지 못하게 숨기고, (암호화)
  • 정보를 교환하는 당사자가 실제로 요청된 당사자임을 보장하며, (인증)
  • 전송하는 데이터가 위조되거나 변조되지 않았음을 확인할 수 있다. (무결성)

이렇게 TLS가 보안 관점에서 뛰어난 이유는 인증서라는 개념을 사용하기 때문이다. 인증서의 역할을 쉽게 정리하면 아래와 같다.

  • 클라이언트(요청을 하는 쪽)에서 접근하려는 서버(요청을 받는 쪽)가 신뢰할 수 있는 서버임을 알 수 있음
  • 통신 중 암호화할 때 사용하는 정보를 클라이언트에게 전달

인증서에는 해당 서버에 대한 도메인 정보와 통신 중 암호화할 때 사용할 정보(정확히는 서버의 공개 키)가 담겨있다. 이 인증서는 서버가 가지고 있다가 클라이언트가 해당 서버에게 요청을 하면 서버가 클라이언트에게 전달한다.

클라이언트는 서버로부터 받은 인증서를 이용해서 해당 서버가 신뢰할 수 있는지 확인하고, 이후 해당 서버와 통신할 때 인증서에 포함된 서버의 공개 키를 이용하여 암호화 통신을 할 수도 있는 것이다.

이 인증서는 TLS 프로토콜을 사용한 인증서라고 해서 TLS 인증서라고 불린다.


신뢰할 수 있는 서버라는 것을 어떻게 TLS 인증서로 알 수 있을까?

TLS 인증서는 서버가 아닌 별도의 주체가 발급한다. CA(Certificate Authority)라고 하는 공인된 기관에서 주로 그 역할을 맡는다. 인증서를 발급해주고 신원을 보증해주는 제3자라고 생각하면 되겠다.

서버가 자신의 정보와 공개 키를 CA로 보내 인증서 생성을 요청하면, CA는 CA만의 비공개 키를 이용해서 서버가 보낸 도메인 정보와 서버의 공개 키를 암호화해 인증서를 생성하고, 서버로 전달한다.

아까 위에서 클라이언트가 해당 서버에 연결을 시도할 때 서버로부터 TLS 인증서를 받는다고 했었다. 이 TLS 인증서는 CA의 비공개 키로 암호화되어 있다.

CA의 공개 키는 누구에게나 공개되어 있기 때문에 클라이언트는 TLS 인증서를 CA의 공개 키로 복호화 시도를 할 것이고, 만약 TLS 인증서 복호화에 성공하면 해당 인증서는 CA가 발급한 진짜 인증서라는 뜻일 것이다.

이 과정을 통해 클라이언트는 자신이 연결하려는 서버가 실제 CA도 알고 있는 진짜 서버임을 알 수 있다.

TLS 인증서에 대해 살펴보다보니 은근슬쩍 공개 키와 비공개 키라는 개념이 튀어나왔다. TLS 인증서에서 공개 키와 비공개 키(또는 비대칭 암호화 방식) 개념은 뗄 수 없는 관계이다보니 가볍게 짚고 가보겠다.

주고 받는 데이터를 암호화하는 방식 중 하나인 비대칭 암호화는 한 쌍의 공개 키와 비공개 키를 가지고 데이터를 암호화할 수 있다. 이 방식은…

  • 공개 키로 암호화한 데이터는 같은 쌍의 비공개 키로 풀 수 있고,
  • 비공개 키로 암호화한 데이터는 같은 쌍의 공개 키로 풀 수 있는 것이다.

이렇게 데이터 암호화와 복호화에 두 가지 키를 사용하기 때문에 더 안전하다는 장점도 있지만, 여기에 독특한 점이 한 가지 더 있다. 암호화를 공개 키로 하느냐, 비공개 키로 하느냐에 따라 사용되는 분야가 달라진다는 점이다.

위에서 살펴봤던 TLS 인증서 사용 과정을 다시 보면, 비대칭 암호화를 사용하는 방식이 두 가지로 나뉜다.

  • CA가 자신의 비공개 키로 암호화한 인증서를 클라이언트가 CA의 공개 키로 복호화하여 CA가 발급한 인증서임을 확인
  • 클라이언트가 인증서에 포함된 서버의 공개 키로 통신을 암호화하여 서버로 전송 (이후 서버가 자신의 비공개 키로 복호화)

즉, 비공개 키로 암호화한 경우에는 인증에 중점을 둔 것이고, 공개 키로 암호화한 경우에는 데이터 보안에 중점을 둔 것이라고 할 수 있겠다.

지금까지 알아본 TLS 인증서를 Kubernetes 클러스터 내에서 쉽게 발급하고 서비스가 사용할 수 있도록 관리 가능한 것이 바로, 맨 위에서 이야기했던 cert-manager이다.


cert-manager가 k8s 내부에서 TLS 인증서를 관리하는 방법

cert-manager는 Issuer와 Certificate라는 두 가지 CRD(Custom Resource Definition)를 사용한다.

Issuer는 Kubernetes 클러스터 내에서 사용할 TLS 인증서를 발급해주는 리소스이다. Issue에는 발급이라는 뜻도 있기 때문에 Issuer(발급자)란 이름이 붙은 것인데, 위에서 살펴봤던 CA와 동일한 역할을 수행한다.

외부에 이미 존재하는 CA와 연동된 Issuer Type들이 이미 준비되어 있기 때문에 이걸 사용할 수도 있고, 클러스터 내부에서 직접 서명하는 Issuer Type을 사용해서 Issuer 리소스를 배포할 수 있다.

Certificate는 Issuer가 발급할 인증서에 대해 정의하는 리소스이다. 인증서 대상 도메인과 유효 기간, 갱신 시점 등을 정의한 Certificate 리소스가 배포될 경우, 대기하고 있던 Issuer 리소스가 이를 감지하여 서명한 인증서와 키 정보 등을 Kubernetes Secret 리소스로 저장한다.

이렇게 cert-manager는 Kubernetes 내에서 사용할 인증서를 쉽게 발급 및 관리할 수 있다는 특징 덕분에 널리 사용되고 있다.