[Kubernetes] Authenticate (인증)
🚀 Authenticate (인증)
쿠버네티스의 사용자
- Service Account(SA): 쿠버네티스가 관리하는 SA 사용자
- 사용자 X
- Pod 사용
- Normal User: 일반 사용자(쿠버네티스가 관리 X)
- 사용자 O
- Pod X
vagrant@k8s-node1 ~ kubectl api-resources | grep serviceacc
serviceaccounts sa v1 true ServiceAccount
Service Account
는 쿠버네티스가 관리한다.
Normal User
가 사용하기 위한 인증서는 쿠버네티스가 관리하지만 사용자라는 개념은 쿠버네티스가 관리하지 않는다.
vagrant@k8s-node1 ~ kubectl get secret
NAME TYPE DATA AGE
default-token-h87sc kubernetes.io/service-account-token 3 11d
vagrant@k8s-node1 ~ kubectl get sa
NAME SECRETS AGE
default 1 11d
쿠버네티스를 설치하면 default라는 sa가 존재한다.
vagrant@k8s-node1 ~ kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-h87sc
Tokens: default-token-h87sc
Events: <none>
sa의 토큰이 default-token-h87sc이다.
vagrant@k8s-node1 ~ kubectl get secret default-token-h87sc -o yaml
apiVersion: v1
data:
ca.crt: ==
namespace: ZGVmYXVsdA==
token:
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: cdaf6124-abc1-46fd-8dbc-b5810a59b044
creationTimestamp: "2022-05-16T07:32:08Z"
name: default-token-h87sc
namespace: default
resourceVersion: "393"
uid: 69097875-6596-4061-8957-0231533a6301
type: kubernetes.io/service-account-token
vagrant@k8s-node1 ~ echo "ZGVmYXVsdA==" | base64 -d
default%
NAMESPACE의 ZGVmYXVsdA==는 default이다.
sa의 토큰 정보는 secret에 저장된다.
secret에 보면 토큰 정보, 토큰을 발급한 CA 인증서, 사용자의 NAMESPACE를 볼 수 있다.
🚀 인증 방법
- x509 인증서
- 토큰
- Bearer Token
- http 헤더:
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269
- SA Token
- JSON Web Token: JWT
- OpenID Connect(OIDC)
- 외부 인증 표준화 인터페이스
- okta, AWS IAM
- OAuth2 Provider
- JSON Web Token: JWT
- Bearer Token
📌 x509 인증서
CA가 발급한 인증서와 인증서에 해당하는 key를 사용한다.
📌 토큰Bearer Token
은 HTTP 헤더에 인증 정보를 실어서 보내주는 방식으로 토큰을 실어 보낸다.31ada4fd-adec-460c-809a-9e56ceb75269
인증을 받기 위한 토큰으로 따로 암호화하지 않기 때문에 외부에 노출되기 쉽다.
간단한 인증 테스트 용도로 사용한다. HTTP basic 인증이라고도 한다.
📌 SA Token
- JSON Web Token
vagrant@k8s-node1 ~/autoscaling/hpa echo "토큰값" | base64 -d
디코딩된 토큰값이 출력된다. # 해당 토큰값 또한 RS256으로 인코딩된 값이다.
인코딩된 토큰을 base64로 디코딩하면 디코딩된 값이 나온다.
그 값 또한 RSA256이라는 알고리즘으로 인코딩된 값이므로 해당 값을 Encoded란에 붙여넣으면 디코딩된 값을 볼 수 있다.
알고리즘, kid, 해당 토큰의 발급자, 여러가지 쿠버네티스 정보를 JSON
형식으로 확인할 수 있다.
이 정보를 kube-apiserver가 보는 것이다.
아직 Invalid Signature
라고 뜨는 이유는 토큰이 실제로 유효한지 인증을 받지 않았기 때문이다.
인증을 받기 위해 인증서와 key가 필요하다.
vagrant@k8s-node1 ~ cd /etc/kubernetes/pki
vagrant@k8s-node1 /etc/kubernetes/pki ls
apiserver-kubelet-client.crt apiserver.crt ca.crt front-proxy-client.crt sa.key
apiserver-kubelet-client.crt.old apiserver.crt.old ca.key front-proxy-client.crt.old sa.pub
apiserver-kubelet-client.key apiserver.key front-proxy-ca.crt front-proxy-client.key
apiserver-kubelet-client.key.old apiserver.key.old front-proxy-ca.key front-proxy-client.key.old
vagrant@k8s-node1 /etc/kubernetes/pki cat ca.crt
-----BEGIN CERTIFICATE-----
인증서 값
-----END CERTIFICATE-----
vagrant@k8s-node1 /etc/kubernetes/pki sudo cat ca.key
-----BEGIN RSA PRIVATE KEY-----
개인키 값
-----END RSA PRIVATE KEY-----
/etc/kubernetes/pki
디렉토리의 ca.crt
값을 인증서 영역에 붙여넣고 ca.key
값을 개인키 영역에 붙여넣으면
Invalid Signature
→ Signature Verified
로 변경된다.
해당 토큰값이 네트워크를 타고 전송될 것이고 받는 쪽에서는 토큰의 검증을 해야한다.
해당 토큰은 CA 인증서와 키를 가지고 서명했기 때문에 CA 인증서와 키를 가지고 풀린다는 것은 부인 방지와 인증의 목적이 있는 것이다.
Pod가 sa를 사용한다는 것은 AWS에서의 sa와 유사하다. ec2 인스턴스를 생성할 때 sa를 지정할 수 있다.
IAM에서 계정을 만들고 그 계정을 VM에 할당하는 것이다. 그러면 VM의 App이 그 권한을 받게된다.
만약 EC2의 App이 S3에 접근해서 데이터를 읽고 써야한다면 권한이 필요하다.
App 수준에서 권한을 세팅하기 위해서는 App을 다시 개발해야 한다.
그럴 필요없이 sa를 만들어서 EC2에 할당하면 해당 App은 권한을 가지고 AWS의 다른 서비스들에 접근할 수 있다.
이와 동일한 방식으로 파드에 권한을 부여할 수 있다.
vagrant@k8s-node1 ~/pod kubectl get po myweb -o yaml | more
serviceAccount: default
따로 지정하지 않아도 파드를 만들 때 보면 spec
에서 serviceAccount
에 default가 적혀있다.
default라는 이름의 sa에 권한이 부여되어 있기 때문에
파드에서 실행하는 컨테이너의 App이 해당 권한을 가지고 다른 쿠버네티스 서비스에 접근할 수 있다.
vagrant@k8s-node1 ~/pod kubectl describe po myweb
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-smj46 (ro)
Volumes:
kube-api-access-smj46:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
Volumes 영역에는 kube-api-access-smj46
볼륨이 존재한다.
그리고 이 볼륨이 /var/run/secrets/kubernetes.io/serviceaccount
에 마운트되어있다.
볼륨을 세팅하지 않아도 반드시 하나의 kube-api-access-smj46
볼륨이 세팅된다. 이 볼륨은 sa의 토큰 정보를 가지며 그것이 마운트되는 것이다.
실제 App은 해당 토큰 정보를 가지고 쿠버네티스에 인증할 수 있다.
그래서 우리가 파드를 생성하면 sa의 토큰이 /var/run/secrets/kubernetes.io/serviceaccount
에 볼륨으로 할당된다.
App은 인증된 권한으로 쿠버네티스에 작업을 할 수 있게된다.
sa를 만들고
→ sa에 적절한 권한을 부여하고
→ 파드를 만들 때 생성한 sa를 부여하면
→ 그 파드에서 실행하는 App이 해당되는 권한으로 쿠버네티스의 작업을 할 수 있다.
nfs 스토리지 클래스를 사용하게 되면 pvc
가 pv
를 만드는데 이때 pv는 쿠버네티스가 만든다.
정확하게는 nfs 파드가 pv
를 만드는 것이다.
그러기 위해서는 nfs 파드가 쿠버네티스와 상호작용 할 수 있는 권한이 필요하고 그래서 별도의 sa가 있는 것이다.
📌 OpenID Connect(OIDC)
JWT 뿐만이 아니라 여러가지 타입의 토큰 인증 방식을 표준화 시켜 놓은 것이다.
AD, LDAP 같은 인증서버를 따로 구축하는 것이 아니라 okta
는 OIDC
라는 표준을 지키는 인증 서버를 SaaS 형태로 제공한다.
모든 인증을 통합한다. 중앙 집중화된 통제가 가능하다.