terraform ハンズオン EKS 認証認可②(irsa)

2023/09/04に公開2

自己紹介

都内SaaS 企業でSRE エンジニア 2年目のFujihara Akitoです。
週一程度簡単なmemo書を残したいと思っています。

EKSの認証認可

EKSの認証認可の方法には大きく2種類あります。

  • aws-auth
  • IAM Roles for Service Accounts (IRSA)
    今回の記事ではまずirsaについて説明します。

EKSのirsaによる認証認可

irsaとはIAM Role for Service Accountの略で文字通りIAM Roleのk8sの ServiceAccountに紐付ける機能です。
そしてIAM Roleが紐づけられたService Accountをk8sのリソースに結びつけることによってAWSリソースにアクセス可能になります。

実際にアクセスする時の概略図は以下

(準備)EKS clusterを作成

  1. awscli & terraform の install
  2. IAM Userの作成 & awscliの設定
  3. 環境変数にuserarn & usernameを設定
export TF_ENV_userarn=arn:aws:iam::××××××××××××:user/hogehoge
export TF_ENV_username=hogehoge
  1. github clone & terraform apply
git clone https://github.com/Akito-Fujihara/aws-auth-and-irsa.git
terraform init
terraform apply
  1. kubeconfigを設定
aws eks update-kubeconfig --name eks-aws-infra-and-irsa
  1. S3のtxt fileのupload
❯ aws s3 cp node-role-access.txt s3://node-role-access-bucket
❯ aws s3 cp irsa-access.txt s3://irsa-access-bucket

EKS NodeのInstance Profileの認可

準備編で作成したEKS NodeのInstance ProfileにはS3(node-role-access-bucket)にアクセスするためのIAM policy(node_role_access)が付与されています。

①IAM role credentialの取得

PodがEKS Nodeの起動時にアタッチするAWS IAM instance profileからIAM credentailを取得します

❯ k apply -f node_role_pod.yaml
pod/node-role-pod created

❯ k exec -it node-role-pod -- bash

bash-4.2# TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    56  100    56    0     0  10481      0 --:--:-- --:--:-- --:--:-- 11200

bash-4.2# ROLE_NAME=`curl -H "X-aws-ec2-metadata-token: $Tta/iam/security-credentials/`

bash-4.2# curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/${ROLE_NAME}/
{
  "Code" : "Success",
  "LastUpdated" : "2023-09-03T13:15:09Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "HOGEHOGE",
  "SecretAccessKey" : "HOGEHOGE",
  "Token" : "HOGEHOGE",
  "Expiration" : "2023-09-03T19:24:56Z"
}

②Get file

実際にS3にアクセスしてみます

❯ k exec -it node-role-pod -- bash

bash-4.2# aws s3 cp s3://node-role-access-bucket ./ --recursive
download: s3://node-role-access-bucket/node-role-access.txt to ./node-role-access.txt

bash-4.2# cat ./node-role-access.txt
node-roleによって取得できるtxt file

bash-4.2# aws s3 cp s3://irsa-access-bucket ./ --recursive
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

nodeのroleを使用しているためirsa-access-bucketにはアクセスできません

irsaの認証認可

準備編で作成したirsaにはS3(irsa-access-bucket)にアクセスするためのIAM Policy(irsa_access)が付与されています。

❯ k apply -f irsa.yaml
serviceaccount/s3-irsa-access created
rolebinding.rbac.authorization.k8s.io/s3-irsa-access-rb created

❯ k apply -f irsa_pod.yaml
pod/irsa-access-pod created

①OIDC JWT tokenの取得

kubectl apply -fコマンドを使ってPodを起動する時に k8s api-serverにあるAmazon EKS Pod Identity webhookがService AccountとそのService AccountのAnnotationにAWS IAM Role ARNがあるか確認しています。
Service AccountのAnnotationにAWS IAM Role ARNがある場合にOIDC経由で取得したJWT トークンを/var/run/secrets/eks.amazonaws.com/serviceaccount/tokenに保存しています。

❯ k get pod irsa-access-pod -o yaml
・・・
spec:
  containers:
  - command:
    - sleep
    - "600"
    env:
    - name: AWS_STS_REGIONAL_ENDPOINTS
      value: regional
    - name: AWS_DEFAULT_REGION
      value: ap-northeast-1
    - name: AWS_REGION
      value: ap-northeast-1
    - name: AWS_ROLE_ARN
      value: arn:aws:iam::××××××××××××:role/s3-irsa-access # < IAM role ARNがインジェクトされている
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token # < IAM roleをAssumeするためのJWT token
    image: amazon/aws-cli
・・・

❯ k exec -it irsa-access-pod -- bash

bash-4.2# cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token
HOGEHOGE

②IAM role credentialの取得

PodがAWS_WEB_IDENTITY_TOKEN_FILEに保存されたトークンを使ってsts:assume-role-with-web-identityコマンドを実行し、AWS IAM roleをAssumeする。

IAM role credentialの取得の再現

❯ k exec -it irsa-access-pod -- bash

bash-4.2# OIDC_TOKEN=`cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token`

bash-4.2# AWS_ROLE_ARN=arn:aws:iam::××××××××××××:role/s3-irsa-access

bash-4.2# aws sts assume-role-with-web-identity \
>               --role-arn ${AWS_ROLE_ARN} \
>               --web-identity-token ${OIDC_TOKEN} \
>               --role-session-name "oidc" \
>               --duration-seconds 900 \
>               --query "Credentials" \
>               --output "json"
{
    "AccessKeyId": "HOGEHOGE",
    "SecretAccessKey": "HOGEHOGE",
    "SessionToken": "HOGEHOGE",
    "Expiration": "2023-09-03T15:01:58+00:00"
}

AssumeしたRoleの確認

bash-4.2# aws sts get-caller-identity # < assumeしたroleを確認
{
    "UserId": "AROA3FFDE7MHRFF4AREEW:botocore-session-1693751200",
    "Account": "××××××××××××",
    "Arn": "arn:aws:sts::××××××××××××:assumed-role/s3-irsa-access/botocore-session-1693751200"
}

③Get file

❯ k exec -it irsa-access-pod -- bash

bash-4.2# aws s3 cp s3://node-role-access-bucket ./ --recursive
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

bash-4.2# aws s3 cp s3://irsa-access-bucket ./ --recursive
download: s3://irsa-access-bucket/irsa-access.txt to ./irsa-access.txt

bash-4.2# cat ./irsa-access.txt
irsaによって取得できるtxt file

irsaを使用しているためnode roleで取得できるfileは取得できない

GitHubで編集を提案

Discussion