[AWS] IRSA 란? (IAM Roles for Service Accounts)
IT/AWS

[AWS] IRSA 란? (IAM Roles for Service Accounts)

반응형

Intro

AWS에는 IAM(Identity and Access Management)이라는 강력한(?) RABAC기반 접근관리 서비스가 있습니다. 이 IAM의 Role(역할)을 통해서 리소스와 리소스간 접근 관리도 할 수 있고, User(사용자)에게 적절한 접근 정책을 줘서 유저의 접근 관리도 할 두 있습니다.

일반적으로 EC2에 IAM Role을 할당하여 EC2 위에서 동작하는 application이 AWS SDK를 사용하거나 AWS CLI를 사용할때 EC2에 부여된 IAM Role의 권한으로 S3나 Secretmanager와 같은 리소스에 접근할 수 있도록 사용할수 있죠.

그러면 EKS Cluster안에서 동작하는 kubernetes Pod에는 어떻게 IAM Role을 줄 수 있을까요? 오늘 이야기할 주제는 EKS Cluster 내부에서 pod에게 IAM Role권한을 주는 방식 IRSA 입니다.

EKS Cluster 내부 Pod에 리소스 접근 권한을 주는 방법은?

EKS Cluster 내부 pod에 리소스 접근을 주는 방법에는 크게 3가지가 있습니다.

  1. 첫번재는, EKS Cluster Node인 EC2에 IAM Role을 할당하여 Pod가 Node의 IAM Role을 자동으로 가져갈 수 있게 할 수 있습니다. 단, EC2 내부에 IMDSv1 방식을 사용할 수 있도록 허용이 되어있어야 합니다.

(IMDS관련해서 다음 포스팅을 참고 바랍니다. https://kim-dragon.tistory.com/271 )

  1. 두번째는, IAM User의 Accesskey를 pod에서 사용하는 AWS SDK나 AWS CLI에 설정하는 방법입니다. 이 방법은 보안상 매우 취약하며 보안 정책상 Accesskey를 주기적으로 변경해야할 수 있기 때문에 관리도 매우 어렵습니다. 따라서 추천해드리지 않습니다.
  2. 마지막이 오늘 주인공 IRSA를 사용하는 방법 입니다. IRSA에 대해서는 아래에 이어서 계속 설명드리겠습니다.

IRSA란?

IRSA는 IAM Role for Service Account의 약자 입니다. 풀네임에서 볼 수 있듯이 kubernetes의 serviceaccount를 사용하여 pod의 권한을 IAM Role로 제어할 수 있도록 하는 기능을 말합니다.

serviceaccount는 AWS의 자원이 아닌데 어떻게 IAM Role을 할당할 수 있는 걸까요? 이걸 해주는게 바로 OIDC라고 부르는 OpenID Connect 입니다.

serviceaccount란?

우선 더 살펴보기전에 위에서 말씀드린 serviceaccount에 대해서 알아보도록 하겠습니다. 서비스 어카운트(Service Account) 는 Kubernetes 의 파드에서 API 서버에 요청을 보냈을 때 이 "파드"를 식별하기 위한 리리소스 입니다.

파드에서 API 서버에 요청을 보내면 이 파드의 정체가 무엇인지 알아야 어떤 권한을 가지고 있는지도 알 수 있고,

이를 기반으로 파드의 요청이 권한에 맞는지를 확인하여 요청을 처리해줄지 말지를 결정할 수 있게 되는데요. 실제로 권한을 정의하고, 설정하는 부분은 Role, ClusterRole, RoleBinding, ClusterRoleBinding의 역할이고, ServiceAccount 는 이러한 권한을 적용할 수 있는 주체 중 한가지로서, Pod에게는 신분증과 같은 인증서역할을 하게 됩니다.

OIDC란?

위에서 셜명 드린 OIDCD는 무엇일까요? OpenID Connect는 Google 등의 IdP(ID 공급자)에 로그인할 수 있도록 지원하는 표준 인증 프로토콜 입니다. 권한허가 프로토콜인 OAuth 2.0 기술을 이용하여 만들어진 인증 레이어로 JSON 포맷을 이용하여 RESTful API 형식을 사용하여 인증을 하게 됩니다. OIDC를 사용하면 손쉽게 외부 서비스를 통해 사용자 인증을 구현할 수 있게 됩니다.

즉, Kunernetes의 리소스와 AWS리소스 처럼 서로다른 리소스간의 인증을이 OIDC를 사용하여 손쉽게(?)할 수 있게 됩니다.

IRSA의 workflow

https://aws.amazon.com/ko/blogs/containers/diving-into-iam-roles-for-service-accounts/

위 그림은 AWS 공식 블로그에서 가져왔으며 pod위에서 동작하는 application이 AWS S3 Buket의 list를 가져올때의 동작 흐름 예시 입니다. 간단히 설명드리면

  1. pod위에서 동작하는 application이 AWS SDK를 사용하여 S3의 리스트를 가져오려고 합니다. 이때 JWT와 IAM Role 의 ARN정보를 AWS STS에게 전달 합니다.
  2. STS는 AWS IAM에게 임시 자격증명을 줄 수 있는지 확인을 요청합니다.
  3. IAM은 IAM OIDC Provider와 통신하고, pod에 할당된 serviceaccount에 IAM Role 정보가 잘 annotate되어 있는 지 확인한 후에 IAM에게 확인 되었다는 응답을 주게 됩니다.
  4. IAM은 STS에게 권한을 줘도 된다고 응답을 주게 되고
  5. AWS STS는 pod의 AWS SDK에게 임시 자격증명을 전달합니다.
  6. 최종적으로 pod의 AWS SDK는 aws s3의 리스트를 가져올 수 있게 됩니다.

** 참고 : JWT란? JSON Web Token의 약자로, 일반적으로 HTTP API 서버를 만들 때에 인증 방법으로 사용. 서버는 사용자가 로그인할 때 고유한 Token을 생성하고, 이를 사용자에게 알려주어 사용자가 다른 API를 사용할 때에 헤더에 이 Token을 넣으면, 자신이라는 것을 증명할 수 있게 하는 것.

** 참고 : AWS STS란? AWS리소스에 접근할 수 있는 권한에 대해 임시자격 증명을 가져오도록 하는 서비스 입니다.

IRSA를 사용하는 이유

EKS 에서 IRSA를 사용하는 이유는 보안 취약성을 줄이기 위해서 입니다. pod에 IAM Role을 할당하는 방법중에 위에서 설명드린 1번 Node에 IAM Role을 할당하면 IRSA를 사용하지 않아도 쉽게 권한 제어를 할 수 있습니다. 하지만 Node안에는 다양한 서비스의 pod들이 떠있을 가능성이 있습니다.

물론 서비스별로 Node affinify 나 selector를 사용해서 구분해놓았을 수도 있습니다만 그럴 경우 유휴자원이 생길 가능성이 높아집니다. 어쨋든 1번 방법은 노드에 IAM Role을 할당하기 때문에 pod별로 IAM Role관리를 할 수 없게 된다는 말이되는데요. 이렇게 되면 보안에 취약점이 생기게 되는 것이죠. 일반적으로 kubernetes자원은 각 어플리케이션 명칭 별로 namesapce 별로 구분하여 관리를 하게 되는데 여기서 IRSA를 사용하게 되면 namespace별로 각각 다른 serviceaccount를 만들고 해당 pod에 각각 다른 IAM Role을 부여할 수 있게 되는 것이죠.

IRSA 사용 해보기

IRSA를 사용하기 위해서는 아래와 같은 작업이 필요합니다.

  • AWS 에서 EKS cluster OICD provider 생성
  • AWS 에서 IAM Role 생성
  • K8s에서 serviceaccount 생성
  • k8s에서 pod에 serviceaccount 할당

각각을 자세한 생성 예시로 살펴보겠습니다.

AWS 에서 EKS cluster OIDC provider 생성

AWS EKS에서 자원을 쉽게 생성해주기위해 aws는 EKS CTL을 만들어줬습니다. 이를 활용하면 쉽게 EKS관련 자원을 생성할 수 있습니다.

eksctl utils associate-iam-oidc-provider --region=ap-northeast-2 --cluster=test-cluster --approve

AWS 에서 IAM Role 생성 + K8s에서 serviceaccount 생성

eksctl을 사용하면 cluster내부에 serviceaccount까지 생성해줄 수 있습니다.

eksctl create iamserviceaccount --cluster=test-cluster --name=test-role --attach-policy-arn=arn:aws:iam::aws:policy/AmazonS3FullAccess --approve

k8s에서 pod에 serviceaccount 할당

아래 serviceAccountName value에 위에서 생성한 serviceaccount name을 입력합니다.

반응형