[AEKS2] 6주차 - EKS Security: K8S 인증/인가
쿠버네티스 환경에서 작업할 때, 클라이언트가 API 서버에 접근하기 위해서는 kubeconfig를 가지고 kubectl 이라는 툴을 사용한다.
이 때 클라이언트는 서버에 접근하기 위해 인증(Authentication) → 인가(Authorization) 단계를 거치게 된다. 더 나아가 Admission Control 단계도 있다.
- Authentication: 어느 페이지에 로그인하는 것과 같다. 해당 사용자를 인증하고 접속하게 되는 것이다. kubeconfig로 사용자를 증명할 수 있다.
- Authorization: 로그인한 이후에 해당 사용자에 대한 권한에 따라 접근할 수 있는 부분이 달라진다. SA에 바인딩되어 있는 Role에 따라 권한 부여가 가능하다.
- Admission Control: 인증/인가 단계를 거친 후에 요청을 가로챌 수 있다. 적절한 요청을 했는지 검증하는 단계로, 사용자의 요청에 더 나아가 추가로 설정해 주는 부분이 있다든지, 요청을 거부할 수도 있다.
Admission Control 단계는 Mutating admission과 Validating admission을 포함하고 있으며, 이 단계까지 거치고 나면 API 서버에 요청했던 데이터가 etcd에 저장된다.
이 글에서는 Admission Control은 언급되지 않는다.
kubeconfig
kubeconfig는 /$HOME.kube/config
에 정의된 환경파일이다.
[KubeConfig란? | devlog.akasai](https://akasai.space/kubernetes/about-kubeconfig/) |
kubconfig는 clusters, contexts, users 세 가지로 나뉜다.
- clusters: API 서버 정보(ip, port, ca 인증서)
- users: 사용자 인증 정보(클라이언트 키/인증서)
- contexts:
users@clusters
로 나타내며, users 정보를 가지고 clusters에 접근하겠다는 접속 정보 조합이다.
kubectl로 위 인증 정보들을 하나하나 옵션으로 주지 않아도 kubeconfig에 정의되어 있다면 간편하게 API를 요청할 수 있다.
인증/인가 실습
테스트 네임스페이스와 파드를 생성하여 Role/RoleBinding이 없는 SA와 있는 SA의 권한 테스트를 진행해 보겠다.
** 가시다님 그림 참조*
-
네임스페이스 생성 및 확인
# kubectl create namespace dev-team namespace/dev-team created # kubectl create ns infra-team namespace/infra-team created
-
SA 생성 및 확인
# kubectl create sa dev-k8s -n dev-team serviceaccount/dev-k8s created # kubectl create sa infra-k8s -n infra-team serviceaccount/infra-k8s created
-
현재 만들어진 리소스는 네임스페이스와 SA밖에 없다.
SA를 지정한 POD 생성
-
serviceAccountName
에 SA를 지정한 POD를 생성한다.cat <<EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata: name: dev-kubectl namespace: dev-team spec: serviceAccountName: dev-k8s containers: - name: kubectl-pod image: bitnami/kubectl:1.28.5 command: ["tail"] args: ["-f", "/dev/null"] terminationGracePeriodSeconds: 0 EOF
cat <<EOF | kubectl create -f - apiVersion: v1 kind: Pod metadata: name: infra-kubectl namespace: infra-team spec: serviceAccountName: infra-k8s containers: - name: kubectl-pod image: bitnami/kubectl:1.28.5 command: ["tail"] args: ["-f", "/dev/null"] terminationGracePeriodSeconds: 0 EOF
-
테스트 POD에 들어가서 POD를 조회해 보고
auth can-i
로 해당 SA가 가진 권한을 확인해 본다. 아직 아무런 권한이 없기 때문에 당연히 POD 조회할 수 없다. 아직 Authentication만 통과된 것이다. -
리소스 현황을 그림으로 보자면 아래와 같다.
Role & RoleBinding
이제 권한을 부여해 주는 작업을 한다. 이 작업이 바로 Authorization이다.
-
Role 생성
cat <<EOF | kubectl create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: **Role** metadata: name: role-dev-team namespace: dev-team rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"] EOF
cat <<EOF | kubectl create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: **Role** metadata: name: role-infra-team namespace: infra-team rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"] EOF
-
Rolebinding에서 위에 생성한 Role과 SA를 지정해 준다.
cat <<EOF | kubectl create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: **RoleBinding** metadata: name: roleB-dev-team namespace: dev-team roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: role-dev-team subjects: - kind: ServiceAccount name: dev-k8s namespace: dev-team EOF
cat <<EOF | kubectl create -f - apiVersion: rbac.authorization.k8s.io/v1 kind: **RoleBinding** metadata: name: roleB-infra-team namespace: infra-team roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: role-infra-team subjects: - kind: ServiceAccount name: infra-k8s namespace: infra-team EOF
-
권한을 부여한 Role을 RoleBinding 리소스를 통해 SA에게 연결해 주었다.
다시 POD 조회하고 권한을 확인해 보면!
이제 yes로 권한이 생겼다.
아래와 같은 그림으로 완성되어 이제 해당 POD에서 리소스 확인이 가능하다.
단, Role과 RoleBinding은 네임스페이스 리소스이기 때문에 kubectl get pods
하면 각각의 네임스페이스에서 생성한 POD만 보이는 것이다.
네임스페이스 한정이 아니라 전체를 보고 싶다면 ClusterRole과 ClusterRoleBinding을 사용할 수 있다.
Leave a comment