[AWS] IAM Role for SeviceAccount (IRSA)
IAM과 RBAC
EKS 환경에서 사용자가 kubectl 명령어를 실행하면, 클러스터는 IAM을 통해 권한을 확인한다.
EKS에서의 인증, 인가 구조는 다음과 같다.
💡 자세히 알아보기
요청이 들어오면 IAM Client에 요청을해서 bearer 토큰을 받게 된다.
그 이후 Pre-signed URL이 생성되고 API 서버에서 Id Token을 확인한다 (AWS-IAM-Authenticator Server)
토큰 값이 일치하면 ConfigMap(AWS-Auth)와 K8s RBAC이 Rolebinding을 하여 Role을 확인한다.
IAM Roles for Service Accounts (IRSA)
AWS IRSA는 AWS EKS의 클러스터에서 실행되는 Pod에서 Service Account를 사용하여 AWS 서비스에 대한 액세스 권한을 부여하는 방법이다. 서비스 어카운트에 필요한 최소 권한만 부여하여 조금 더 세분화 해서 권한 관리를 할 수 있는 기능이라고 볼 수 있다.
💡 자세히 알아보기2
1. 파드가 S3 버킷의 list를 가져오기 위해서는 JWT(JSON Web Token)와 IAM의 ARN 권한을 요구한다.
2. STS(Security Token Service)는 IAM에 임시 자격 증명 부여가 가능한지 확인한다.
3. IAM은 OIDC Provider와 통신해 파드에 할당된 Service Account에 IAM 역할이 Annotate되어있는지 확인 후 응답한다.
4. IAM은 STS에게 임시 자격 증명 부여가 가능하다는 응답을 주고, STS는 SDK에 임시 자격증명을 전달한다.
5. 파드의 SDK는 S3 리스트를 가져올 수 있게 된다.
참고 : https://kim-dragon.tistory.com/279
실제로 어떻게 적용이 되는건지 더 자세히 알아보자. 아래 내용은 EKS 클러스터가 구성되어있고, AWS CLI가 설치되어있다고 가정한다.
권한 확인
먼저 파드 내부에서 `aws s3 list` 명령어를 실행하는 단일 파드를 하나 생성한다.
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
EOF
그 후 `kubectl get pod` 를 실행하면 파드가 실행이 되었지만 오류로 종료된 것을 확인할 수 있다.
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
eks-iam-test1 0/1 Error 0 37s
로그를 확인해보면 List Bucket을 호출하는 동안 액세스 거부 오류가 발생하는 것을 알 수 있다.
$ kubectl logs eks-iam-test1
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
파드에서 실행되는 워크로드가 EC2에 연결된 IAM 역할을 활용하여 S3 버킷의 리스트를 확인하려고 시도하는데, 이는 컨테이너에서 AWS 자격증명을 찾을 수 없기 때문에 SDK가 IAM 메타데이터 서버로 통신하기 때문이다.
EC2 프로필 내의 IAM 역할에는 GetList 권한이 없으므로 액세스 거부 오류를 수신한 것이다.
해당 컨테이너의 자격증명 default가 EC2 인스턴스 프로필로 설정되지 않도록 Pod 수준으로 제한이 필요하다.
쿠버네티스 서비스 어카운트
💡 (정말) 간단하게 알아보는 쿠버네티스의 서비스 어카운트
쿠버네티스는 서비스 어카운트를 통해 ID를 부여받고, ServiceAccount가 생성되면 JWT 토큰이 Secret으로 자동 생성된다. 그 후 Secret을 마운트하여 해당 Service Account에서 Kubernetes API Server에 인증하는 데 사용할 수 있다.
JWT 토근으로 IAM 인증을 사용할 수 없는 몇 가지 문제는 있는데 하나는 토큰을 검증하는 것이 쿠버네티스 API 서버 뿐이고, 두번째는 토큰이 만료되지않아 서명 키를 순환하는게 어려운 프로세스라는 점이다.
Kubernetes 1.12부터 ProjectedServiceAccountToken 기능이 도입되면서, OIDC JWT 토큰을 Pod에 마운트할 수 있게 되어, EKS 환경에서는 해당 토큰이 앞서 언급한 JWT 토큰 대신 각 Pod에 할당된다.
# 아래 명령어로 토큰을 검색하면 완전히 호환되는 OIDC 토큰임을 알 수 있다.
SA_TOKEN=$(kubectl exec -it eks-iam-test2 \
-- cat /var/run/secrets/kubernetes.io/serviceaccount/token)
jwt decode $SA_TOKEN --json --iso8601
이 OIDC 토큰은 AWS API 인증을 하는데 사용할 수 있는 토큰을 찾기 위한 기반을 제공한다.
EKS 클러스터에 사전 설치된 ID 웹훅(amazon-eks-pod-identity-webhook)으로 새 토큰을 파드에 주입할 수 있다.
웹훅이 새 토큰을 파드에 주입하기 위해선 Service Account를 만들고, 해당 계정에 AWS IAM 역할 ARN을 annotation으로 지정하면 해당 Service Account를 참고한다.
해당 과정은 eksctl 도구를 사용하면 자동화하여 생성한다.
# 서비스 계정을 생성하기 전 IAM OIDC 공급자를 연결한다.
eksctl utils associate-iam-oidc-provider \
--region=us-east-2 --cluster=eks-oidc-demo --approve
# Service Account를 생성한다.
# 쿠버네티스 서비스 계정, IAM 역할, 해당 IAM 역할에 대한 신뢰정책을 생성한다.
eksctl create iamserviceaccount \
--name my-sa \
--namespace default \
--cluster eks-oidc-demo \
--approve \
--attach-policy-arn $(aws iam list-policies \
--query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text)
새로 생성된 서비스 어카운트를 describe하면 어떤 role을 가지고있는지 확인이 가능하다.
kubectl describe sa my-sa
Name: my-sa
Namespace: default
Labels: app.kubernetes.io/managed-by=eksctl
Annotations: eks.amazonaws.com/role-arn:
arn:aws:iam::xxxx:role/eksctl-eks-oidc-demo-addon-iamserviceaccount-Role1-H47XCR6FPRGQ
Image pull secrets: <none>
Mountable secrets: my-sa-token-kv6kc
Tokens: my-sa-token-kv6kc
Events: <none>
IAM은 OIDC ID 공급자를 사용한 인증을 지원하며, 이 기능을 통해 OIDC JWT를 수신 후 API 호출을 인증할 수 있다.
그런 다음 이 토큰을 AWS STS API 작업에 전달하여 임시 IAM 자격 증명을 가지고 올 수 있게된다.
이제 Pod에서 해당 서비스 계정을 사용하도록 하면, 토큰을 사용하여 S3 API 인증을 할 수 있게 된다.
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: eks-iam-test4
spec:
serviceAccountName: my-sa
containers:
- name: my-aws-cli
image: amazon/aws-cli:latest
args: ["s3", "ls"]
restartPolicy: Never
EOF
파드가 성공적으로 완료되었음을 볼 수 있으며, 로그를 확인하면 s3 버킷을 볼 수 있다.
kubectl get pods
NAME READY STATUS RESTARTS AGE
eks-iam-test4 0/1 Completed 0 83s
kubectl logs eks-iam-test4
<s3 bucket list>
참고
https://aws.amazon.com/ko/blogs/containers/diving-into-iam-roles-for-service-accounts/
'💻 CSP > AWS' 카테고리의 다른 글
[AWS] S3의 ACL 구성 (0) | 2024.05.28 |
---|---|
[AWS] S3 수명 주기 정책 (Life Cycle Rule) (0) | 2024.04.05 |
[AWS] ECR 로그인 & 빌드 및 푸쉬 (0) | 2024.03.11 |
[AWS] Lambda Connection Handler (0) | 2024.02.29 |
[AWS] Transit Gateway (0) | 2024.02.28 |