K8S 인증/인가
Kubernetes에서는 API 통신을 위하여 인증(Authentication), 인가/권한(Authorization), Admission Control(승인제어) 단계를 거치게 된다.
- 인증(Authentication): Kubernetes를 사용하는 사용자가 검증된 사용자인지를 확인하는 절차
- User Account: Kubernetes를 사용하는 사용자 계정
ex) AWS 로그인 계정
- Service Account: Pod에서 실행되는 프로세스에 대한 식별자를 제공 / Namespace로 구분
ex) AWS IAM - 인가/권한(Authorization): 사용자 행위에 대해서 권한이 있는지를 확인하는 절차 / RBAC기반으로 동작
- User Account 별 Role/Rolebinding / Cluster Role/ Cluster Rolebinding
- Service Account 별로 Role/Rolebinding / Cluster Role/ Cluster Rolebinding - Admission Control(승인제어): API 요청 검증 / API 요청에 대한 특정 기능을 제한 / 변경(ResourceQuota, LimitRange)
Service Account 실습 시나리오
- 서비스 어카운트(Service Account, SA)를 생성 : dev-k8s, infra-k8s
- 서비스 어카운트 별 Pod 생성 및 권한 Test
- 서비스 어카운트 별 권한(Role, 인가)생성 : dev-k8s(dev-team 네임스페이스 내 모든 동작) , infra-k8s(dev-team 네임스페이스 내 모든 동작)
- SA 를 지정하여 권한에 대한 테스트를 진행
1. 네임스페이스와 서비스 어카운트 생성 후 확인
# 네임스페이스(Namespace, NS) 생성 및 확인
kubectl create namespace dev-team
kubectl create ns infra-team
# 네임스페이스 확인
kubectl get ns
# 네임스페이스에 각각 서비스 어카운트 생성 : serviceaccounts 약자(=sa)
kubectl create sa dev-k8s -n dev-team
kubectl create sa infra-k8s -n infra-team
# 서비스 어카운트 정보 확인
kubectl get sa -n dev-team
kubectl get sa dev-k8s -n dev-team -o yaml | yh
kubectl get sa -n infra-team
kubectl get sa infra-k8s -n infra-team -o yaml | yh
2. 서비스 어카운트 별 Pod 생성 및 권한 Test
# 각각 네임스피이스에 kubectl 파드 생성 - 컨테이너이미지
# docker run --rm --name kubectl -v /path/to/your/kube/config:/.kube/config bitnami/kubectl:latest
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
# 확인
kubectl get pod -A
kubectl get pod -o dev-kubectl -n dev-team -o yaml
serviceAccount: dev-k8s
...
kubectl get pod -o infra-kubectl -n infra-team -o yaml
serviceAccount: infra-k8s
...
# 파드에 기본 적용되는 서비스 어카운트(토큰) 정보 확인
kubectl exec -it dev-kubectl -n dev-team -- ls /run/secrets/kubernetes.io/serviceaccount
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/token
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/namespace
kubectl exec -it dev-kubectl -n dev-team -- cat /run/secrets/kubernetes.io/serviceaccount/ca.crt
# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
# 권한 테스트
k1 get pods # kubectl exec -it dev-kubectl -n dev-team -- kubectl get pods 와 동일한 실행 명령이다!
k1 run nginx --image nginx:1.20-alpine
k1 get pods -n kube-system
k2 get pods # kubectl exec -it infra-kubectl -n infra-team -- kubectl get pods 와 동일한 실행 명령이다!
k2 run nginx --image nginx:1.20-alpine
k2 get pods -n kube-system
# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
no
3. 서비스 어카운트 별 권한(Role, 인가)생성 : dev-k8s(dev-team 네임스페이스 내 모든 동작) , infra-k8s(dev-team 네임스페이스 내 모든 동작)
# 각각 네임스페이스내의 모든 권한에 대한 롤 생성
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
# 롤 확인
kubectl get roles -n dev-team
kubectl get roles -n infra-team
kubectl get roles -n dev-team -o yaml
kubectl describe roles role-dev-team -n dev-team
...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
# 롤바인딩 생성 : '서비스어카운트 <-> 롤' 간 서로 연동
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
# 롤바인딩 확인
kubectl get rolebindings -n dev-team
kubectl get rolebindings -n infra-team
kubectl get rolebindings -n dev-team -o yaml
kubectl describe rolebindings roleB-dev-team -n dev-team
...
Role:
Kind: Role
Name: role-dev-team
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount dev-k8s dev-team
4. SA 를 지정하여 권한에 대한 테스트를 진행
# 각각 파드로 Shell 접속하여 정보 확인 : 단축 명령어(alias) 사용
alias k1='kubectl exec -it dev-kubectl -n dev-team -- kubectl'
alias k2='kubectl exec -it infra-kubectl -n infra-team -- kubectl'
# 권한 테스트
k1 get pods
k1 run nginx --image nginx:1.20-alpine
k1 get pods
k1 delete pods nginx
k1 get pods -n kube-system
k1 get nodes
k2 get pods
k2 run nginx --image nginx:1.20-alpine
k2 get pods
k2 delete pods nginx
k2 get pods -n kube-system
k2 get nodes
# (옵션) kubectl auth can-i 로 kubectl 실행 사용자가 특정 권한을 가졌는지 확인
k1 auth can-i get pods
yes
EKS 인증/인가
- AWS EKS의 경우 사용자 인증은 AWS IAM / 인가는 K8S의 RBAC을 사용
EKS 인증/인가 세부 과정
1. EKS Service endpoint(STS)에 토큰 요청
2. 전달받은 토큰을 Bearer Token 형식으로 EKS API Cluster EndPoint에 인증 요청
3. EKS API는 Token Review 를 Webhook token authenticator에 요청 ⇒ (STS GetCallerIdentity 호출) AWS IAM 해당 호출 인증 완료 후 User/Role에 대한 ARN 반환
3. 쿠버네티스 RBAC 인가를 처리
실습 - myeks-bastion-2에 burst사용자 생성
1. burst 사용자 생성(Bastion1 서버 실행)
# 사용자 생성
aws iam create-user --user-name burst
# 사용자에게 프로그래밍 방식 액세스 권한 부여
aws iam create-access-key --user-name burst
# 사용자에 정책을 추가
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name burst
# get-caller-identity 확인
aws sts get-caller-identity --query Arn
"arn:aws:iam::590183955668:user/yjsong"
kubectl whoami
"arn:aws:iam::590183955668:user/yjsong"
# EC2 IP 확인 : myeks-bastion-EC2-2 PublicIPAdd 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
2. burst 유저 자격증명 설정 및 확인 (Bastion2 서버 실행)
# get-caller-identity 확인 >> 왜 안될까요?
aws sts get-caller-identity --query Arn
# testuser 자격증명 설정
aws configure
AWS Access Key ID [None]: My-Access-Key
AWS Secret Access Key [None]: My-Secret-Key
Default region name [None]: ap-northeast-2
# get-caller-identity 확인
aws sts get-caller-identity --query Arn
# kubectl 시도 >> testuser도 AdministratorAccess 권한을 가지고 있는데, 실패 이유는?
kubectl get node -v6
ls ~/.kube
3. burst에 system:masters 그룹 부여로 EKS 관리자 수준 권한 설정 (Bastion1 서버 실행)
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username burst --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/burst
4. burst kubeconfig 생성 및 kubectl 사용 확인 (Bastion2 서버 실행)
# burst kubeconfig 생성 >> aws eks update-kubeconfig 실행이 가능한 이유는?, 3번 설정 후 약간의 적용 시간 필요
aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias burst
# kubectl 사용 확인
kubectl ns default
kubectl get node -v6
EKS 신규기능 access management controls
aws-auth configmap 잘못 수정 시 Node전체에 장애가 발생 할 수 있음
이를 보안하기 위해 신규 기능인 access management controls 기능이 추가
기존 복잡하고 configmap을 통한 사용자 관리를 보다 쉽게 제어 및 컨트롤 할 수 있는 장점이 있음
- 기본 인증모드는 EKS API 및 ConfigMap으로 설정되어 있으나 정책 중복 시 EKS API가 우선되며, ConfigMap은 무시됨
실습 - EKS access management controls
1. EKS 인증방식을 EKS API모드로 변경
# EKS API 액세스모드로 변경
aws eks update-cluster-config --name $CLUSTER_NAME --access-config authenticationMode=API
# List all access policies : 클러스터 액세스 관리를 위해 지원되는 액세스 정책
## AmazonEKSClusterAdminPolicy – 클러스터 관리자
## AmazonEKSAdminPolicy – 관리자
## AmazonEKSEditPolicy – 편집
## AmazonEKSViewPolicy – 보기
aws eks list-access-policies | jq
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq
2. burst 계정 설정
- access-entry 생성 / associate-access-policy 연동
- 간단하고 직관적으로 EKS 사용자를 관리 할 수 있음
# burst2 의 access entry 생성
aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst
aws eks list-access-entries --cluster-name $CLUSTER_NAME | jq -r .accessEntries[]
# burst에 AmazonEKSClusterAdminPolicy 연동
aws eks associate-access-policy --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster
#
aws eks list-associated-access-policies --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst | jq
3. bastion2에서 burst2 확인
# burst2 정보 확인
aws sts get-caller-identity --query Arn
kubectl whoami
# kubectl 시도
kubectl get node -v6
kubectl api-resources -v5
kubectl rbac-tool whoami
kubectl auth can-i delete pods --all-namespaces
kubectl get cm -n kube-system aws-auth -o yaml | kubectl neat | yh
eksctl get iamidentitymapping --cluster $CLUSTER_NAME
4. 직접 생성한 Cluster-role 사용
#
cat <<EoF> ~/pod-viewer-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-viewer-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list", "get", "watch"]
EoF
cat <<EoF> ~/pod-admin-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-admin-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["*"]
EoF
kubectl apply -f ~/pod-viewer-role.yaml
kubectl apply -f ~/pod-admin-role.yaml
#
kubectl create clusterrolebinding viewer-role-binding --clusterrole=pod-viewer-role --group=pod-viewer
kubectl create clusterrolebinding admin-role-binding --clusterrole=pod-admin-role --group=pod-admin
#
aws eks create-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst --kubernetes-group pod-viewer
5. 직접 생성한 Cluster-role 사용 ( kubernetesGroups 업데이트 적용)
#
aws eks update-access-entry --cluster-name $CLUSTER_NAME --principal-arn arn:aws:iam::$ACCOUNT_ID:user/burst --kubernetes-group pod-admin | jq -r .accessEntry
...
"kubernetesGroups": [
"pod-admin"
...
'AEWS Study' 카테고리의 다른 글
6주차 - EKS Security - Kyverno & 보안 위협 시나리오 (0) | 2024.04.14 |
---|---|
6주차 - EKS Security - IRSA & Pod Identity (0) | 2024.04.13 |
5주차 - EKS Autoscaling - Karpenter (1) | 2024.04.07 |
5주차 - EKS Autoscaling - (Node Autoscaling) (0) | 2024.04.05 |
5주차 - EKS Autoscaling - (Pod Autoscaling) (0) | 2024.04.05 |