๋กœ์ผ“๐Ÿพ
article thumbnail

 

์ด๋ฒˆ ๊ธ€์˜ ์ฃผ์ œ์ธ "IRSA" ๋Š” ์ดํ•ดํ•˜๊ธฐ๋„ ํž˜๋“ค์—ˆ์ง€๋งŒ, ์ด๊ฑธ ๊ธ€๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฑด ๋” ์–ด๋ ค์›Œ์„œ ๋งŽ์€ ๋ธ”๋กœ๊ทธ ๊ธ€๋“ค๊ณผ ๊ฐ•์˜๋ฅผ ์ฐธ๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•„๋ž˜์— ๋ช…์‹œํ•œ ์ฐธ๊ณ  ๋ธ”๋กœ๊ทธ๋“ค๋„ ์ฝ์–ด์ฃผ์„ธ์š”!

 

 

IRSA ๋Š” IAM Roles for Service Account ์˜ ์•ฝ์ž๋กœ, Kubernetes ์—์„œ AWS ๋ฆฌ์†Œ์Šค์— ์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค.

 

IRSA ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์˜ ํŠน์ • Service Account ์— AWS IAM Role ์„ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•ด๋‹น Service Account ์ด AWS ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ์–ป์Šต๋‹ˆ๋‹ค. 

 

IRSA ๋Š” AWS ์—์„œ ์ œ๊ณตํ•˜๋Š” OIDC ์™€ IAM Role ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํŒŒ๋“œ๊ฐ€ AWS ์ž๊ฒฉ ์ฆ๋ช…์„ ์ง์ ‘ ๊ด€๋ฆฌํ•  ํ•„์š” ์—†์ด AWS ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ๊ฐ„๋‹จํžˆ IRSA ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์œผ๋‹ˆ, ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

 

To the Code~!

 

 

Shallow Dive


์šฐ์„  IRSA ์„ ์–ด๋–ป๊ฒŒ ์ ์šฉํ•˜๋Š”์ง€๋ถ€ํ„ฐ ์‚ดํŽด๋ณด์ฃ !

 

serviceaccount ์™€ pod ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐฐํฌํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ,

apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: true
metadata:
  name: irsa-exam
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::xxxx:role/IRSA_Exam"
---
kind: Pod
apiVersion: v1
metadata:
  name: irsa-exam
spec:
  serviceAccountName: irsa-exam
  containers:
    - name: aws
      image: amazon/aws-cli
      command: [ "/bin/sh" ]
      args: [ "-c", "while true; do echo hello; sleep 1d;done" ]

 

serviceaccount ์— ๋ช…์‹œํ•  IAM Role ์˜ ARN ์ด ํ˜„์žฌ ์—†์œผ๋‹ˆ ๋งŒ๋“ค์–ด ์ค์‹œ๋‹ค.

 

IRSA ์šฉ IAM Role ์€ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์ง€๋งŒ, Terraform IAM Module ์„ ์ด์šฉํ•˜๋ฉด ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

https://github.com/terraform-aws-modules/terraform-aws-iam/blob/master/examples/iam-role-for-service-accounts-eks/main.tf#L32-L54

๊ธฐ๋ณธ IRSA ๋ง๊ณ ๋„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ๋“ค์— ๋Œ€ํ•œ IRSA ๋„ ์ œ๊ณตํ•ด์ฃผ๋‹ˆ ์ด์šฉํ•˜๋ฉด ๊ต‰์žฅํžˆ ํŽธํ•ฉ๋‹ˆ๋‹ค.
cert_manager_irsa_role, karpenter_controller_irsa_role ๋“ฑ

 

Terraform IAM Module ๋ฅผ ํ†ตํ•ด Role ์„ ์ƒ์„ฑํ–ˆ๋‹ค๋ฉด, ์‹ ๋ขฐ ๊ด€๊ณ„(Trust Relationships) ๋ฅผ ํ•œ๋ฒˆ ํ™•์ธํ•ด๋ด…๋‹ˆ๋‹ค.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ExplicitSelfRoleAssumption",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "ArnLike": {
                    "aws:PrincipalArn": "arn:aws:iam::xxxx:role/IRSA_Exam"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxx:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx:sub": "system:serviceaccount:default:irsa-exam",
                    "oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}

 

ํ•ต์‹ฌ๋งŒ ์‚ดํŽด๋ณด๋ฉด ํ•ด๋‹น ARN ์„ ๊ฐ€์ง„ OIDC Provider ๋Š” sts:AssumeRoleWithWebIdentity ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ subject ๊ฐ€ system:serviceaccount:default:irsa-exam ๊ฐ€ ์ด์—ฌ์•ผ ํ•˜๊ณ , audience ๊ฐ€ sts.amazonaws.com ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ถ”๊ฐ€๋กœ "oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx:sub" ๋ถ€๋ถ„์˜ "system:serviceaccount:default:irsa-exam" ์€ ๋ฐ˜๋“œ์‹œ Service Account ์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์™€ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

StringEquals ๋ง๊ณ  StringLike ๋ฅผ ํ†ตํ•ด * ์‚ฌ์šฉ ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ถ”์ฒœ๋“œ๋ฆฌ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

 

์ดํ›„ ํŒŒ๋“œ์— ์ ‘๊ทผํ•˜์—ฌ aws s3 ls ์™€ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด AWS ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ํŒŒ๋“œ ๋‚ด์—์„œ WebIdentityToken ์„ ์ง€์›ํ•ด์ฃผ์–ด์•ผ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

IRSA ๊ฐ€ ๋™์ž‘ํ•˜๋Š”์ง€๋งŒ ํ™•์ธํ•˜๋ ค๋ฉด ์—ฌ๊ธฐ๊นŒ์ง€ ์ง„ํ–‰ํ•ด๋„ ์ „ํ˜€ ๋ฌธ์ œ ์—†์ง€๋งŒ, ์ €๋Š” ์ด ๋™์ž‘ ์•ˆ์—์„œ ๊ถ๊ธˆํ•œ ์ ์ด 2๊ฐ€์ง€ ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. ServiceAccount ์— Annotation ๋งŒ ๋‹ฌ์•˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ํ•ด๋‹น ServiceAccount ๋ฅผ ๋งˆ์šดํŠธํ•œ ํŒŒ๋“œ์—์„œ AWS ์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜์ง€?
  2. ServiceAccount ๋Š” JWT ํ˜•ํƒœ๋กœ ํ† ํฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ๋งŒ๋ฃŒ๊ฐ€ ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ๊ฐฑ์‹ ํ•˜์ง€?

IRSA ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋” ๊นŠ์ด์žˆ๊ฒŒ ๋“ค์–ด๊ฐ€๋ณด๋ฉด์„œ ํ•ด๋‹น ๊ถ๊ธˆ์ ์„ ๋ฐ”๋กœ ํ•ด์†Œํ•ด๋ณด์ฃ !

 

Deep Dive


ServiceAccount ์— ๋‹จ์ˆœํžˆ Annotation ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ AWS ์— ์ ‘๊ทผ์„ ๊ฐ€๋Šฅ์ผ€ ํ•ด์ฃผ๋Š”(Assume Role ์— ํ•„์š”ํ•œ) JWT ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด JWT ๋Š” ๊ฐ‘์ž๊ธฐ ์–ด๋””์„œ ํŠ€์–ด ๋‚˜์™”์„๊นŒ์š”?

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” JWT ๋Š” K8S SA Token ์„ ์˜๋ฏธํ•˜๋ฉฐ, ์‹ค์งˆ์ ์œผ๋กœ Assume Role ์— ํ•„์š”ํ•œ Token ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
AWS ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋Š” AWS Session Token ๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€์‹œ๋”๋ผ๋„ ๊ธ€์„ ๋‹ค ์ฝ์€ ํ›„์—๋Š” ์ดํ•ด๊ฐ€ ๋˜์‹ค๊ฒ๋‹ˆ๋‹ค!

 

 

์ฟ ๋ฒ„๋„คํ‹ฐ์Šคํ•œํ…Œ ๋ช…๋ น์„ ํ•  ๋•Œ, ๊ธฐ๋ณธ์ ์œผ๋กœ API Server ์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์€ ๋ฐ›์€ API Server ๋Š” ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

https://sysdig.com/blog/kubernetes-admission-controllers/

 

์—ฌ๊ธฐ์„œ Mutating Admission ๊ณผ Validating Admission ์„ ํ•ฉ์ณ Admission Controller ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

Mutating Admission ์—์„  ์š”์ฒญํ•œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•ด์ฃผ๊ณ , Validating Admission ์€ ์ตœ์ข… ๋งค๋‹ˆํŽ˜์ŠคํŠธ๊ฐ€ ์œ ํšจํ•œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ์ธ์ง€ ํŒ๋‹จ์„ ํ•ด์ฃผ์ฃ .

๋” ์ž์„ธํ•˜๊ฒŒ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ์ธ์ฆ/์ธ๊ฐ€์™€ ECTD ์‚ฌ์ด ๊ทธ ๋…€์„ - Admission Controller ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!

 

์šฐ๋ฆฌ๋Š” ์ด Mutating Admission ๊ณผ์ •์„ ํ†ตํ•ด์„œ Assume Role ์— ํ•„์š”ํ•œ JWT ์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ง€์š”!

 

Mutating Admission ์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ๋‚ด์—์„œ mutatingwebhookconfigurations.admissionregistration.k8s.io ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, ๊ด€๋ จํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io

pod-identity-webhook

 

๋งค๋‹ˆํŽ˜์ŠคํŠธ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, 

pod-identity-webhook

 

pods ๋ผ๋Š” ๋ฆฌ์†Œ์Šค๊ฐ€ CREATE ๋  ๋•Œ ํ•ด๋‹น Admission ์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ https://127.0.0.1:23443/mutate ์—”๋“œํฌ์ธํŠธ๋กœ ํ•ด๋‹น ํŒŒ๋“œ์˜ ์ •๋ณด๋ฅผ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ https://127.0.0.1:23443/mutate ์€ amazon-eks-pod-identity-webhook ์˜ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ, kubectl get ์œผ๋กœ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์•„ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ์œ„์— ์žˆ๋Š”๊ฑฐ ๊ฐ™์ง„ ์•Š์Šต๋‹ˆ๋‹ค.

 

์ด๊ฑฐ๋Š” ๋‡Œํ”ผ์…œ์ธ๋ฐ, Control Plane ์— amazon-eks-pod-identity-webhook ๋ผ๋Š” ๋‹จ๋… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์กด์žฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ถ”์ธก๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— API Server ์—์„œ ๋กœ์ปฌ ์ฃผ์†Œ์ธ 127.0.0.1:23443 ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

https://aws.amazon.com/ko/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/

 

๊ฑด๋“œ๋ฆฐ๋‹ค๋ฉด ํด๋Ÿฌ์Šคํ„ฐ์— ํฐ ์žฅ์• ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Control Plane ์ฒ˜๋Ÿผ AWS ๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ˜น์‹œ ๊ด€๋ จ๋˜์„œ ์•„๋Š” ์ •๋ณด๊ฐ€ ์žˆ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š”! ๊ด€๋ จ๋œ ์˜คํ”ผ์…œํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜๊ฐ€ ์—†๋„ค์š” ใ…œใ…œ

 

์•„๋ฌดํŠผ https://127.0.0.1:23443/mutate ์„ ๊ฑฐ์ณ ๋ณ€ํ˜•๋œ ํŒŒ๋“œ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๊ฐ€ ์‹ค์งˆ์ ์œผ๋กœ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค.

 

๋ณ€ํ˜•๋˜์—ˆ๋‹ค๊ณ  ํ•ด์„œ ๊ฒฉ๋ณ€ํ•œ ๋ถ€๋ถ„์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ์ € ENV ์™€ ๋งˆ์šดํŠธ๋ณผ๋ฅจ๋งŒ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜ ๋งค๋‹ˆํŽ˜์ŠคํŠธ๋Š” Webhook ์œผ๋กœ ์ธํ•ด ๋ณ€ํ˜•๋œ ๋ถ€๋ถ„๋งŒ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 ...
    env:
    - name: AWS_STS_REGIONAL_ENDPOINTS
      value: regional
    - name: AWS_DEFAULT_REGION
      value: ap-northeast-2
    - name: AWS_REGION
      value: ap-northeast-2
    - name: AWS_ROLE_ARN
      value: arn:aws:iam::xxxx:role/IRSA_Exam
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
 ...
    volumeMounts:
    - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
      name: aws-iam-token
      readOnly: true
  ...
  volumes:
  - name: aws-iam-token
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          audience: sts.amazonaws.com
          expirationSeconds: 86400
          path: token
volumes ๋ฅผ ๋ณด๋ฉด projected ๋ผ๊ณ  ๋˜์–ด์žˆ๋Š”๋ฐ, ์ด ๊ธฐ๋Šฅ์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค 1.12 ์—์„œ ์ถ”๊ฐ€๋œ projectedServiceAccountToken ์ด๋ผ๋Š” ๊ธฐ๋Šฅ์œผ๋กœ ํ† ํฐ์— exp, aud ๋“ฑ์˜ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์ด ์ง€์›๋˜๊ธฐ ์ด์ „์—๋Š” ์ง์ ‘ ๋„ฃ์–ด์คฌ์–ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  /var/run/secrets/eks.amazonaws.com/serviceaccount/token ๊ฒฝ๋กœ์— Assume Role ์— ์‚ฌ์šฉํ•  JWT ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

k8s sa token

 

๊ทธ๋Ÿผ /var/run/secrets/eks.amazonaws.com/serviceaccount/token ์— ์žˆ๋Š” k8s sa token ์œผ๋กœ ๋ญ˜ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋ฐ”๋กœ AWS ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ AWS Session Token ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (Assume Role ์— ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ ๊ถŒํ•œ์ด ์žˆ์–ด์•ผํ•จ)

#-- /run/secrets/eks.amazonaws.com/serviceaccount ์— ์žˆ๋Š” token ๊ฐ’
$ IRSA_TOKEN="<JWT>"

$ aws sts assume-role-with-web-identity \
    --role-arn arn:aws:iam::xxxx:role/IRSA_Exam \
    --role-session-name test \
    --web-identity-token $IRSA_TOKEN

 

์œ„ ๋ช…๋ น์–ด๋ฅผ ๋ณด๋ฉด $IRSA_TOKEN ์— k8s sa token ์„ ๋„ฃ์–ด์ฃผ์–ด AWS Session Token ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

AWS Session Token

 

๋ˆˆ์น˜๋ฅผ ์ฑ„์…จ์„ ๋ถ„๋„ ์žˆ์„ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, k8s sa token ์„ ์–ป์–ด๋‚ด๊ธฐ๋งŒ ํ•œ๋‹ค๋ฉด ๋งŒ๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ์–ด๋””์„œ๋“  ํ•ด๋‹น k8s sa token ์„ ํ†ตํ•ด AWS Session Token ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋”ฐ๋ผ์„œ k8s sa token ์ด ๋…ธ์ถœ๋œ๋‹ค๋ฉด, ํ•ด๋‹น ํ† ํฐ์„ ํ†ตํ•ด IRSA_Exam Role ์ธ๊ฒƒ์ฒ˜๋Ÿผ ์œ„์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์œ„ํ—˜์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ๋Š˜ k8s sa token ์€ ๋ณด์•ˆ์— ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค!

 

๋งŒ์•ฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ผ๋ฉด AWS SDK ๋ฅผ ์ด์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ž๋ฐ”๋กœ ์˜ˆ๋ฅผ ๋“ค๋ฉด WebIdentityTokenCredentialsProvider ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด์„œ ์œ„์™€ ๊ฐ™์€ ๊ณผ์ •์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ๋Š” ๋” ๋‚˜์•„๊ฐ€ k8s sa token ์ด ์œ ํšจํ•œ ํ† ํฐ์ธ์ง€ ์–ด๋–ป๊ฒŒ ํŒ๋‹จ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด IAM OIDC Provider ๋ฅผ ํ†ตํ•ด ์œ ํšจํ•œ JWT ์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

EKS ์—์„œ ์ƒ์„ฑ๋œ OIDC Provider URL ์€ ํผ๋ธ”๋ฆญ์œผ๋กœ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋””์„œ๋“  ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ช…๋ น์–ด๋ฅผ ์ฃผ๋ฉด, 

$ curl https://oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx/.well-known/openid-configuration

 

json ํ˜•์‹์˜ ์‘๋‹ต์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

{
    "issuer": "https://oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx",
    "jwks_uri": "https://oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx/keys",
    "authorization_endpoint": "urn:kubernetes:programmatic_authorization",
    "response_types_supported": [
        "id_token"
    ],
    "subject_types_supported": [
        "public"
    ],
    "claims_supported": [
        "sub",
        "iss"
    ],
    "id_token_signing_alg_values_supported": [
        "RS256"
    ]
}

 

์‘๋‹ต ๋ฐ›์€ jwks_uri ๋กœ ํ•œ๋ฒˆ ๋” ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

$ curl https://oidc.eks.ap-northeast-2.amazonaws.com/id/xxxx/keys

 

๊ทธ๋Ÿผ JWK ์„ ์–ป์„ ์ˆ˜ ์žˆ์ฃ . ์ˆ˜๋งŽ์€ key ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•œ ํ›„ PEM ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค!

 

์ด๋•Œ key ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ๋‚˜์˜ฌํ…๋ฐ ์•„๋ฌด key ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ผ ์•„๋‹ˆ๋ผ JWT Header ์— ์žˆ๋Š” kid(key id) ์™€ ์ผ์น˜ํ•˜๋Š” key ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Kid ํ™•์ธ
https://8gwifi.org/jwkconvertfunctions.jsp

 

๋ฐ›์€ Public Key ๋ฅผ Verify Signature ๋ถ€๋ถ„์— ๋„ฃ์œผ๋ฉด ์œ ํšจํ•œ JWT ์ธ์ง€๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Signature Verified

 

ํŒŒ๋“œ ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ AWS SDK ๋ฅผ ์ด์šฉํ•  ๋•Œ๋„ ๊ฒฐ๊ตญ ์ด๋Ÿฐ ๊ฒ€์ฆ ๊ณผ์ •๊ณผ ๋ฐœ๊ธ‰ ๊ณผ์ •์„ ๊ฑธ์ณ Session Token ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ , ๋„์‹ํ™” ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

 

์ด๋ ‡๊ฒŒ "ServiceAccount ์— Annotation ๋งŒ ๋‹ฌ์•˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ํ•ด๋‹น ServiceAccount ๋ฅผ ๋งˆ์šดํŠธํ•œ ํŒŒ๋“œ์—์„œ AWS ์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜์ง€?" ๋ผ๋Š” ๊ถ๊ธˆ์ ์„ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋” ๋‚˜์•„๊ฐ€ ์–ด๋–ป๊ฒŒ ์œ ํšจํ•œ ํ† ํฐ์ธ์ง€ ๊ฒ€์ฆํ•˜๋Š”์ง€๋„ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด์ œ ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์„ ๊ฒฝ์šฐ๋Š” ์–ด๋–จ๊นŒ์š”? ๋งŒ๋ฃŒ๋œ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ ์ด๊ฑธ ๋ˆ„๊ฐ€ ํ•ด์ค„๊นŒ์š”?

 

์šฐ์„  ์ง€๊ธˆ๊นŒ์ง€ ํ”„๋กœ์„ธ์Šค์—์„œ ์‚ฌ์šฉ๋œ ํ† ํฐ์€ ํฌ๊ฒŒ 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. K8S SA Token ๊ณผ AWS Session Token ์ž…๋‹ˆ๋‹ค.

 

K8S SA Token ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” kubelet ์ด ์ง„ํ–‰ํ•ด์ค๋‹ˆ๋‹ค. ๊ณต์‹ ๋ฌธ์„œ์— ๋‚˜์™€์žˆ์ฃ .

https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#launch-a-pod-using-service-account-token-projection

 

๊ทธ๋Ÿผ AWS Session Token ์€ ๋ˆ„๊ฐ€ ๊ฐฑ์‹ ํ•ด ์ค„๊นŒ์š”? ๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด ์ฝ”๋“œ๋กœ ๊ตฌํ˜„์„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

AWS SDK for JAVA ๊ฐ™์€ ๊ฒฝ์šฐ ๋‹คํ–‰ํžˆ ๋งŒ๋ฃŒ๋˜๊ธฐ ์ง์ „์— ์•Œ์•„์„œ ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ํ•ด์ค€๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/credentials-temporary.html

 

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ๊ทธ์ € Web Identity Token(K8S SA Token) ๋งŒ ์ž˜ ์œ„์น˜์‹œํ‚ค๋ฉด ๋ฉ๋‹ˆ๋‹ค!

 

์ถ”๊ฐ€๋กœ ๊ด€๋ จ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

STSAssumeRoleWithWebIdentitySessionCredentialsProvider
ShouldDoAsyncSessionRefresh

 

์ด๋ ‡๊ฒŒ "ServiceAccount ๋Š” JWT ํ˜•ํƒœ๋กœ ํ† ํฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ๋งŒ๋ฃŒ๊ฐ€ ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ๊ฐฑ์‹ ํ•˜์ง€?" ๋ผ๋Š” ๊ถ๊ธˆ์ ๋„ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

ํ‰์ƒ์‹œ์— ์‰ฝ๊ฒŒ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๋˜ IRSA ์˜€์ง€๋งŒ, ์•Œ๊ณ ๋ณด๋‹ˆ ๊ฝค๋‚˜ ๋ณต์žกํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋„ค์š”!

 

๊ทธ๋Ÿผ ์˜ค๋Š˜์€ ์—ฌ๊ธฐ๊นŒ์ง€~!

 

 

References

profile on loading

Loading...