AWS IRSA OIDC Condition Matching

정의 (Definition)

AWS IRSA(IAM Roles for Service Accounts)의 OIDC Condition Matching은 Kubernetes ServiceAccount가 AWS IAM Role을 임시 자격 증명으로 교환(AssumeRole)할 때, IAM Trust Policy의 sub(Subject) 조건과 실제 요청자의 ServiceAccount 식별자가 정확히 일치하는지 검증하는 보안 절차입니다. 불일치 시 403 AccessDenied 에러가 발생합니다.

문제가 되는 배경 (Problem Context)

Helm Chart를 사용하여 애플리케이션을 배포할 때, 릴리즈 이름(Release Name)이 리소스 이름에 접두사로 붙는 경우가 많습니다.

  • Terraform(IAM): Role의 신뢰 관계에 system:serviceaccount:ns:my-app만 허용하도록 설정.
  • Kubernetes(Helm): 실제 생성된 ServiceAccount 이름이 release-name-my-app으로 변경됨. 이 불일치로 인해 “분명히 Role을 줬는데 권한이 없다”는 상황(sts:AssumeRoleWithWebIdentity 실패)이 발생합니다.

핵심 메커니즘 (How it Works)

  1. JWT 토큰 발급: EKS는 Pod에 주입된 토큰에 sub 클레임(system:serviceaccount:<namespace>:<service-account-name>)을 포함합니다.
  2. AWS STS 검증: Pod가 이 토큰으로 AWS STS에 역할을 요청하면, AWS는 IAM Role의 Trust Relationship을 확인합니다.
  3. StringEquals 조건: Trust Policy의 Condition 블록에서 oidc.eks...:sub 키의 값이 토큰의 sub 값과 문자열 단위로 완전히 일치해야 합니다.
"Condition": {
  "StringEquals": {
    "oidc.eks.region.amazonaws.com/id/EXAMPLED539D986783...:sub": "system:serviceaccount:default:my-service-account"
  }
}

불변 조건과 보장 범위 (Invariants & Guarantees)

  • 정확한 일치(Exact Match): 와일드카드(*)는 StringLike 연산자에서만 동작하며, 보안상 ServiceAccount 이름에는 권장되지 않습니다. 보통 StringEquals를 사용하므로 1글자라도 다르면 거부됩니다.
  • 네임스페이스 포함: 검증 대상은 SA 이름뿐만 아니라 네임스페이스까지 포함된 전체 경로입니다.

실무적 함의 (Operational Implications)

  • 변수화(Variable) 전략: Terraform과 Helm Values 간의 SA 이름 불일치를 막기 위해, SA 이름을 고정된 변수로 정의하고 양쪽에서 참조하도록 구성해야 합니다.
  • Helm fullnameOverride: Helm Chart 배포 시 릴리즈 이름에 의한 변형을 막기 위해 fullnameOverride 또는 serviceAccount.name 값을 명시적으로 고정하는 것이 IRSA 운영에 유리합니다.

주의사항 / 오해 (Pitfalls & Misconceptions)

  • “Role ARN만 맞으면 된다?”: ServiceAccount에 eks.amazonaws.com/role-arn Annotation이 잘 붙어 있어도, Trust Policy의 조건이 틀리면 동작하지 않습니다. Annotation은 “요청할 Role 위치”를 알려줄 뿐, “허가”를 보장하지 않습니다.

References