일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- k8s
- AWS
- keda
- 국비지원교육
- kubernetes
- 합격 후기
- volume
- HPA
- aews vault
- POD
- karpenter
- Terraform
- aews ci/cd
- eks endpoint access
- EKS
- CAS
- Python
- 외부 모듈
- observability
- aews
- Jenkins
- 클라우드 엔지니어
- 공부 방법
- 도커
- storageclass
- 클라우드 국비지원교육
- 클라우드 국비지원교육 후기
- docker
- VPA
- 단기 합격
- Today
- Total
모험가
AEWS 6주차 - EKS Security(OIDC, IRSA, Pod Identity) 본문
본 글은 가시다님이 진행하시는 AEWS(AWS EKS Workshop Study)를 참여하여 정리한 글입니다. 모르는 부분이 많아서 틀린 내용이 있다면 말씀 부탁드리겠습니다! |
OIDC
Oauth란?
OAuth는 인증 및 권한 부여를 위한 개방형 표준 프로토콜입니다. 사용자가 자신의 계정 정보를 공개하지 않고도 다른 애플리케이션이 사용자를 대신하여 특정 작업을 수행할 수 있도록 해줍니다. |
- OpenID Connect: 사용자 인증 및 사용자 정보 제공 (id token)
- OAuth: 권한 부여 (access token) - 페이스북 posting 권한, 유저 profile view 권한 등
간단하게 말해서 OAuth는 사용자 인증 정보 대신 토큰을 사용하며, 사용자는 자신의 계정 정보를 공개하지 않고도 다른 애플리케이션에 대한 접근 권한을 부여할 수 있습니다.
OIDC란?
OIDC는 OAuth 2.0 프로토콜을 기반으로 하는 인증 프레임워크입니다. OIDC는 OAuth 2.0의 기능을 확장하여 사용자 인증을 제공합니다. |
OIDC OpenID Connect = OpenID 인증 + OAuth2.0 인가, JSON 포맷을 이용한 RESful API 형식으로 인증
제가 이해한 순서로는
1. 사용자가 중개서버로 인증 요청을 보내면 OAuth에게 권한이 있는지 누구인지 요청합니다.
2. 이때 OAuth는 사용자에 대한 정보와 권한에 대해서 판단하고 허가해주면서 id_token을 발급해줍니다.
3. 이를 받은 중대서버는 사용자 정보(id_token)에 대해서 다시 반환합니다.
이떄 id_token은 jwt 형식으로 되어있어서 IdP를 통해 생성되어 사용자로 전달된 토큰이 변조 되었는지 쿠버네티스쪽에서 쉽게 확인할 수 있습니다.
너무 어렵네요..
자세한 내용은 커피 고래님의 글을 보시면 이해하기 쉬우실겁니다.
https://coffeewhale.com/kubernetes/authentication/oidc/2020/05/04/auth03/
k8s 인증 완벽이해 #3 - OpenID Connect
쿠버네티스 인증 완벽 이해 시리즈 3탄, OpenID Connect를 이용한 쿠버네티스 인증에 대해서 살펴보는 시간을 가져 보겠습니다.
coffeewhale.com
IRSA(IAM Roles for Service Accounts)
IRSA란?
IRSA는 Kubernetes에서 AWS 리소스에 안전하게 접근하기 위한 방법입니다. IRSA를 사용하면 Kubernetes 내부의 Pod가 AWS 리소스에 접근할 수 있는 권한을 가질 수 있습니다 |
IAM Role for Service Account을 줄여서 IRSA라고합니다. 이름부터 IAM Role을 Service Account에게 부여한다는 것.
즉 AWS 리소스들 혹은 정책들을 AWS IAM에 정의하고 해당 Role을 sa에게 부여해서 해당 pod가 허용된 행동을 할 수 있게 해줍니다.
IRSA가 나오기전에는 node에 역할을 부여해서 pod가 해당 권한을 획득하였는데 이는 보안상 많이 취약하여, sa->pod단의 권한제어를 하기 위해서 IRSA가 나왔습니다.
그래서 어떠한 방법으로 어떤 플로우로 인증이 될까요?
형식 : JWT(JSON Web Token), JWKS(JSON Web Key Set)
pod는 무슨 역할을 지니는지 확인해봅니다.
# 파드1 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test1
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
args: ['s3', 'ls']
restartPolicy: Never
automountServiceAccountToken: false
terminationGracePeriodSeconds: 0
EOF
# 확인
kubectl get pod
# 로그 확인
k logs eks-iam-test1
파드가 s3 ls에 대한 권한이 없기 때문에 Error와 위와 같은 권한 오류 로그를 볼 수 있습니다.
=> 여기에서 나와있는 Role은 해당 노드에 부착되어있는 Role입니다.
콘솔에서도 확인이 가능합니다.
물론 내용은 이벤트 실패에 대한 내용입니다.
# 파드 삭제
kubectl delete pod eks-iam-test1
pod의 token을 분석해봅니다.
# 파드2 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test2
spec:
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
# 확인
kubectl get pod
kubectl describe pod
kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token ;echo
# aws 서비스 사용 시도
kubectl exec -it eks-iam-test2 -- aws s3 ls
# 서비스 어카운트 토큰 확인
SA_TOKEN=$(kubectl exec -it eks-iam-test2 -- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
echo $SA_TOKEN
아까와 동일하게 권한이 없으니 오류를 뱉습니다. 해당 pod가 지닌 token의 속성을 봅시다.
iss 속성
EKS OpenID Connect Provider(EKS IdP) 주소 > 이 EKS IdP를 통해 쿠버네티스가 발급한 토큰이 유요한지 검증
이제 IRSA를 생성해봅니다.
# Create an iamserviceaccount - AWS IAM role bound to a Kubernetes service account
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster $CLUSTER_NAME \
--approve \
--attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
# 확인 >> 웹 관리 콘솔에서 CloudFormation Stack >> IAM Role 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
생성하면 Cloudformation에서 해당 role이 만들어진 것을 확인할 수 있습니다.
# Inspecting the newly created Kubernetes Service Account, we can see the role we want it to assume in our pod.
kubectl describe sa my-sa
해당 sa는 Annotations에 방금 만든 role을 지니고 있네요
그래서 저 Role은 무슨 권한과 무슨 신뢰관계를 지니고 있을까요??
"Action": "sts:AssumeRoleWithWebIdentity"과 default 네임스페이스의 my-sa와 연결되어있음이 보입니다.
이제 해당 sa를 사용하는 pod를 생성해서 다시 s3 ls을 실행해봅니다.
# 파드3번 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test3
spec:
serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
# 해당 SA를 파드가 사용 시 mutatingwebhook으로 Env,Volume 추가함 : AWS IAM 역할을 Pod에 자동으로 주입
kubectl get mutatingwebhookconfigurations pod-identity-webhook -o yaml
# 파드 생성 yaml에 없던 내용이 추가됨!!!!!
# Pod Identity Webhook은 mutating webhook을 통해 아래 Env 내용과 1개의 볼륨을 추가함
kubectl get pod eks-iam-test3
kubectl get pod eks-iam-test3 -o yaml
...
volumeMounts:
- mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
name: aws-iam-token
readOnly: true
...
volumes:
- name: aws-iam-token
projected:
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
...
해당 pod의 토큰을 확인해봅니다.
kubectl describe pod eks-iam-test3
...
Environment:
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_ROLE_ARN: arn:aws:iam::911283464785:role/eksctl-myeks-addon-iamserviceaccount-default-Role1-GE2DZKJYWCEN
AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
Mounts:
/var/run/secrets/eks.amazonaws.com/serviceaccount from aws-iam-token (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-69rh8 (ro)
...
Volumes:
aws-iam-token:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 86400
kube-api-access-sn467:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
...
파드를 보면 이와 같이 projected 타입으로 volume이 있으며, Env에 Role에 대한 정의가 되어있습니다.
이제 이전에 안되던 s3 ls가 가능한지 확인합니다.
# 파드에서 aws cli 사용 확인
kubectl exec -it eks-iam-test3 -- aws sts get-caller-identity --query Arn
# 확인
kubectl exec -it eks-iam-test3 -- aws s3 ls
kubectl exec -it eks-iam-test3 -- aws ec2 describe-instances --region ap-northeast-2
이렇게 s3 ls 명령어가 가능함을 확인했습니다.
그러면 ec2 describe은 왜 안되었을까요?
=> role에 s3의 읽기에 관한 policy만 들어가있기때문이죠
# 실습 확인 후 파드 삭제 및 IRSA 제거
kubectl delete pod eks-iam-test3
eksctl delete iamserviceaccount --cluster $CLUSTER_NAME --name my-sa --namespace default
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
kubectl get sa
Pod Identity
새로 출시한 Pod Identity는 위의 그림으로도 충분히 설명이되지만 크게 뭐가 바뀌고 좋을까요??
여러가지 장점이 있겠지만 재사용성, 편리성이 좋습니다.
기존에 IRSA을 사용해서 role의 신뢰정책로 sa를 지정하고 pod가 이 sa을 사용하였다면 같은 권한을 지닌 role을 다른 클러스터의 pod가 이용하고 싶으면 해당하는 클러스터에 대한 role을 생성하고 신뢰정책을 구성해야합니다.
만약 멀티 클러스터의 구성에서는 오버헤드가 증가하죠
Pod Identity를 이용하면 addon으로 관리하여 중앙관리가 가능하여 해당 권한을 지닌 role을 재사용이 가능해서 오버헤드가 크게 줄어들 것 같네요
따라서 EKS Pod Identity를 사용하면 IRSA에 비해 IAM 역할 관리가 더 효율적이며, 동일한 권한을 지닌 역할을 중복해서 생성할 필요가 줄어듭니다. 이는 운영 및 관리 측면에서 큰 장점이 될 수 있습니다.
eks-pod-identity-agent 설치
# 설치
aws eks create-addon --cluster-name $CLUSTER_NAME --addon-name eks-pod-identity-agent
혹은
eksctl create addon --cluster $CLUSTER_NAME --name eks-pod-identity-agent --version 1.3.5
# 확인
eksctl get addon --cluster $CLUSTER_NAME
daemonset을 확인해봅니다.
kubectl get ds -n kube-system eks-pod-identity-agent -o yaml
...
containers:
- args:
- --port
- "80"
- --cluster-name
- myeks
- --probe-port
- "2703"
command:
- /go-runner
- /eks-pod-identity-agent
- server
....
ports:
- containerPort: 80
name: proxy
protocol: TCP
- containerPort: 2703
name: probes-port
protocol: TCP
...
securityContext:
capabilities:
add:
- CAP_NET_BIND_SERVICE
...
hostNetwork: true
...
podidentityassociation 설정
# podidentityassociation 설정
eksctl create podidentityassociation \
--cluster $CLUSTER_NAME \
--namespace default \
--service-account-name s3-sa \
--role-name s3-eks-pod-identity-role \
--permission-policy-arns arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--region ap-northeast-2
# 확인
kubectl get sa
eksctl get podidentityassociation --cluster $CLUSTER_NAME
# ABAC 지원을 위해 sts:Tagsession 추가
aws iam get-role --query 'Role.AssumeRolePolicyDocument' --role-name s3-eks-pod-identity-role | jq .
Cloudformation에도 Role로 생성이 되었습니다.
그러면 생성된 Role을 한번 봅니다.
권한은 이전과 같이 S3 Read에 대한 권한이 있지만,
신뢰 관계가 이전에 IRSA와 차이가 있습니다.
바로 Condition 항목에 sa가 지정되어있지 않다는 점입니다.
그리고 EKS 콘솔에서 보다 간편하게 확인이 가능합니다.
그런데 저는 지금 s3-sa라는 서비스어카운트가 없는데 만들어지네요 이렇게 지정해서 만든 이후에 사용하는게 가능한 것 같습니다.
이제 sa를 생성후 해당 권한을 확인해봅니다.
# 서비스어카운트, 파드 생성
kubectl create sa s3-sa
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-pod-identity
spec:
serviceAccountName: s3-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
command: ['sleep', '36000']
restartPolicy: Never
terminationGracePeriodSeconds: 0
EOF
#
kubectl get pod eks-pod-identity -o yaml | kubectl neat
# 토큰 확인
kubectl exec -it eks-pod-identity -- env | grep AWS
serviceaccount/아래에 token이 들어가있습니다.
토큰을 확인해봅니다.
# 토큰 정보 확인
kubectl exec -it eks-pod-identity -- ls /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/
kubectl exec -it eks-pod-identity -- cat /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
최종 확인 및 삭제
# 해당 권한 확인
kubectl exec -it eks-pod-identity -- aws s3 ls
# 리소스 정리
eksctl delete podidentityassociation --cluster $CLUSTER_NAME --namespace default --service-account-name s3-sa
kubectl delete pod eks-pod-identity
kubectl delete sa s3-sa
이렇게 EKS Pod Identity에 대해서 알아보았습니다. IRSA를 사용하는 환경이면 Pod Identity 도입을 고려해보면 좋을 것 같습니다.
'쿠버네티스 > AEWS' 카테고리의 다른 글
AEWS 7주차 - EKS Mode/Nodes(EKS Automode) (1) | 2025.03.20 |
---|---|
AEWS 7주차 - EKS Mode/Nodes(EKS Fargate) (0) | 2025.03.19 |
AEWS 6주차 - EKS Security(k8s 인증/인가, EKS 인증/인가, access management controls) (0) | 2025.03.13 |
AEWS 6주차 - EKS Security(x.509, k8s config) (0) | 2025.03.13 |
AEWS 5주차 - EKS Autoscaling(CAS, CPA, Karpenter - 실습) (0) | 2025.03.06 |