Cloud/k8s-CKA

[CKA] 37. k8s에서의 상호 인증 원리

jinkwon.kim 2023. 10. 13. 03:50
728x90
반응형

개요

k8s에서 어떻게 상호 인증을 하는지 알아보겠습니다. 

사전 필수 지식

[CKA] 35. Security - TLS통신 이해를 위한 PKI 기본 지식

상호 인증 원리

k8s에 있는 여러 service(apiserver, etcd, kubelet ...) 들은 상호 인증을 위해서 인증서와 개인키를 사용합니다. 

service 별 인증서

아래 그림은 service별 인증서(*.crt) 및 개인키(*. key)를 분리해 놓은 자료입니다. 

위 그림에서 모든 인증서 admin.crt, scheduler.crt, controller-manager.crt, kube-proxy.crt 등등은 모두ca.crt 와 ca.key를 사용하여 전자 서명이 되어있습니다.

admin.crt 생성 과정

모든 인증서 생성과정은 이름만 변경될뿐 모두 동일한 방식으로 생성이 됩니다.

 

그리고 인증서의 실제 위치는 위치는 다음과 같습니다. 

실제 위치

controlpane에서 인증서 위치

/etc/kubernets/pki에 존재합니다.

kubelet 인증서 위치

/var/lib/kubelet/pki 에 존재합니다.

여기서 보면 kubelet-client는 crt, 과 key가 존재하는 것이 아니라 pem으로 존재하는데요. 이 파일은 crt와 key을 합쳐 놓은 파일입니다.

인증서 및 개인 키의 필요성

클라이언트와 서버 간의 상호 인증을 하는데 사용이 됩니다. 이렇게 되면 따로 인증 체계를 만들 이 않아도 되는 장점이 존재합니다. 

그러나 인증서가 털리면 다 뚫리는 상황도 발생합니다. k8s에서의 인증서 및 개인키의 역할은 아래의 개념처럼 이해하면 좋습니다

 

certificate  == User ID

private key == password

 

그러면 이번에는 인증서와 개인키로 가지고 실제로 정상적올 apiserver와 통신이 되는지 확인을 해보겠습니다.

통신 테스트

명령어는 아래와 같고, 통신 테스트는 woker node에서 진행하겠습니다. 

 

curl  https://192.168.0.26:6443/api/v1/namespaces/default/pods --cert /var/lib/kubelet/pki/kubelet-client-current.pem --cacert /etc/kubernetes/pki/ca.crt

 

위 명령을 실행하기 위해서 우리는 3가지 정보를 알아야 합니다.

1. controlplane의 apiserver 정보

2. kubelet-client 인증서 위치

3. ca 인증서 위치

controlplane의 apiserver 정보

controlplane의 IP와 port 그리고 지원하는 api, 지원하는 API는 https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#api-overview  에서 확인이 가능합니다. 저는 여기서 pods 정보만 가져오는 api를 사용하겠습니다.

 

https://192.168.0.26:6443/api/v1/pods

kubelet-client 인증서 위치

 /etc/kubernetes/kubelet.conf 이 파일의 마지막줄에 나와있습니다. 

인증서의 파일명이 crt가 아니고  kubelet-client-current.pem인 이유는 이 파일 안에는 인증서와 개인키가 들어가 있기 때문입니다. 

그래서 인증서와 개인키의 파일명이 동일합니다. 

인증서 확인

root@master:/var/lib/kubelet/pki# cat kubelet-client-2023-01-16-22-52-13.pem
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIIHegmr52Po6cwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
.... 생략 ....
m+V0S9tY2d3FDif47c235WIbtZiT9PfBm1JnZx/UNj+owbMKAg==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA0IXuM57aRZMyfmYwoKghvEQ0VAUf8zcn7BW9EtfT+PensonX
.... 생략 ....
iAEU3poL4RAi34UknKrytpY3MJLgYs0cVpdhWZNift3syyH3/Xf9
-----END RSA PRIVATE KEY-----

ca 인증서 위치

/etc/kubernetes/pki 에 존재합니다.

통신 검증

그럼 이제 통신에 필요한 모든 정보를 알아냈으니 아래 명령을 실행해 보겠습니다. 

 

curl  https://192.168.0.26:6443/api/v1/namespaces/default/pods --cert /var/lib/kubelet/pki/kubelet-client-current.pem --cacert /etc/kubernetes/pki/ca.crt

 

통신이 잘되고 Pod list의 정보가 잘 나옵니다. 

이를 통해서 알 수 있는 것은 apiserver와 통신을 위해서는 k8s에서 제공하는 ca.crt로 인증된 인증서가 필요하다입니다.

그럼 지금 까지는 잘되는 환경을 테스트하였으니 잠시 인증서에 문제가 있을 때 어떻게 처리해야 하는지 알아보겠습니다. 

인증서 정보확인 방법

openssl x509 -in {인증서} -text -noout

주요 정보

Issuer

인증서 발행자의 정보 

Validity

    Not Before: [시작 날짜]
    Not After : [만료 날짜]

유효기간

Subject

인증서 주체의 정보

X509v3 Subject Alternative Name

(주로 SAN, SubjectAltName로 알려짐)은 X.509 인증서에 포함된 확장 필드 중 하나입니다. SAN은 주체의 추가 식별 정보를 제공하는 데 사용되며, 주로 여러 도메인 이름이나 IP 주소를 하나의 인증서에 연결할 때 사용됩니다.

예제

openssl x509 -in apiserver.crt -text -noout

root@master:/etc/kubernetes/pki# openssl x509 -in apiserver.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 6064824178665716266 (0x542a95752a91fa2a)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = kubernetes
        Validity
            Not Before: Jan 16 13:52:10 2023 GMT
            Not After : May  4 13:48:03 2024 GMT
        Subject: CN = kube-apiserver
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:a5:10:67:70:af:76:8c:13:00:80:e1:c6:51:0f:
                    ... 생략 ...
                    d9:36:c6:2e:4f:34:6c:70:63:c0:07:49:03:3f:fb:
                    0d:ad
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Authority Key Identifier: 
                keyid:39:00:D7:1A:58:4A:C0:55:72:D6:BC:C5:36:0A:82:8F:85:7D:F7:C3

            X509v3 Subject Alternative Name: 
                DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:master, IP Address:10.96.0.1, IP Address:192.168.0.26
    Signature Algorithm: sha256WithRSAEncryption
         03:3c:dd:20:3d:94:28:17:89:2e:2d:f4:64:98:d6:8f:c2:76:
         ... 생략 ...
         4f:08:60:b4

service 별 인증서 관련 설정

k8s에서 존재하는 service 별 yaml 파일에서의 인증서 관련 설정 정보

apiserver

파일 명

/etc/kubernetes/manifests/kube-apiserver.yaml

인증 설정

spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.0.26
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt

        # etcd에서 사용하는 ca 인증서
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt

        # apiserver가 etcd server에 접근할때 사용하는 인증서 
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key

        # apiserver가 etcd server에 접근할때 사용하는 개인키
    - --etcd-servers=https://127.0.0.1:2379
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt

        # apiserver가 kubelet server에 접근할때 사용하는 인증서
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key

        # apiserver가 kubelet server에 접근할때 사용하는 개인키
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt

        # apiserver가 api aggregation layer에 연결할 때 사용하는 사용하는 인증서
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key

        # apiserver가 api aggregation layer에 연결할 때 사용하는 사용하는 개인키
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-issuer=https://kubernetes.default.svc.cluster.local
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-account-signing-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt 

         #apiserver가 service를 위해서 사용하는 인증서
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

         #apiserver가 service를 위해서 사용하는 개인키

etcd

파일 명

/etc/kubernetes/manifests/etcd.yaml

인증 설정

spec:
  containers:
  - command:
    - etcd
    - --advertise-client-urls=https://192.168.0.26:2379
    - --cert-file=/etc/kubernetes/pki/etcd/server.crt

         #etcd가 사용하는 인증서
    - --client-cert-auth=true
    - --data-dir=/var/lib/etcd
    - --experimental-initial-corrupt-check=true
    - --experimental-watch-progress-notify-interval=5s
    - --initial-advertise-peer-urls=https://192.168.0.26:2380
    - --initial-cluster=master=https://192.168.0.26:2380
    - --key-file=/etc/kubernetes/pki/etcd/server.key

         #etcd가 사용하는 개인키
    - --listen-client-urls=https://127.0.0.1:2379,https://192.168.0.26:2379
    - --listen-metrics-urls=http://127.0.0.1:2381
    - --listen-peer-urls=https://192.168.0.26:2380
    - --name=master
    - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
    - --peer-client-cert-auth=true
    - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
    - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
    - --snapshot-count=10000
    - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt

         #etcd가 사용하는 root ca 인증서

정리 

k8s에서는 상호인증을 하기 위해서 인증서와 개인키를 사용합니다. 여기서 인증서는 ID의 역할, 개인키는 password의 역할을 합니다.

그리고 모든 service는 자신들만의 인증서 및 개인키를 가지고 있으며 모든 인증서는 ca 인증서와, ca 개인키로 전자 서명되어 있습니다.

Next Post

[CKA] 38. k8s에서 사용자 추가 및 권한 제어

 

728x90
반응형