LoginSignup
46
8
お題は不問!Qiita Engineer Festa 2023で記事投稿!

KubernetesクラスターからAWSリソースへのアクセスを制御してくれる「IRSA」とは?

Last updated at Posted at 2023-06-16

「アクセス制御」ってややこしいですよね。
AWSでもIAMが苦手!って方多そうですが、Kubernetesの世界でもアクセス制御を知っておかないとセキュリティ事故に繋がります。

今回はそれらの合わせ技となる、AWS上でKubernetesを使う際の両プラットフォーム間でのアクセス制御の組み合わせについてのお話です。

AWS上でKubernetesを使う際のセキュリティ課題

EKSを使ってKubernetesワークロードをAWS環境上でホストしてるよ!という方は多いんじゃないかと思います。
特にAWSでKubernetesを使っていると「PodからAWSリソースにアクセスさせたい」という要件が出てきます。

以下のようなプロダクトを例として想像してみましょう。
スクリーン ショット 2023-06-11 に 11.25.36 午前.png
この例では同じEKSクラスター上でKubernetes Podを2種類がバックエンドアプリケーションとして稼働しています。

Pod①へは大量のリクエストが飛んできますが、処理はPod内で完結しています。
一方で右側のPod②へはたまにリクエストが来るだけですが、DBへのデータ操作が発生するためAmazon Auroraクラスターに接続しています。

このときAWSの世界で「Pod②からAuroraクラスターへのアクセスを許可する」設定をしてあげる必要があります。これを実現するための機能がIRSAです。

IRSAとは?

IAM Roles for Service Accountsの略です。

実はAmazon EKSがGAしてまだ間もない2019年ごろ、Pod単位でAWSリソースへのアクセス許可を設定する機能がAWSネイティブでは存在していませんでした。

EKSノード(=当時はEC2インスタンスのみ)はAWSリソースなのでIAMロールを付与することは出来たのですが、PodはあくまでKubernetesプラットフォーム内の概念なのでAWSの世界とマッピングしてあげる手段が一部の3rdパーティソフトウェア( kube2iamkiam など)しかありませんでした。

もしEKSノード(=EC2インスタンスやFargate)単位でしかIAMロールを設定できない場合、何が問題か分かりますか?
スクリーン ショット 2023-06-11 に 11.27.11 午前.png
同じEKSクラスター内のPodが一つでも悪意あるクラッカーに攻撃されてしまうと、そこからアクセスを許可しているAurora上の大事なデータが漏洩してしまう可能性があります。
本来、このAuroraデータベースはPod②だけが触れればいいのに、これだとPod①が攻撃されてしまうだけで本来無関係なAuroraのデータがリスクに晒されてしまうわけです。

IR = AWSの世界における「認証」

改めておさらいしておくと、IRSAのIRの部分(=IAMロール)はAWSにおける権限管理機能の一つです。

  • 人間が直接AWSマネコンやCLIを操作してAWSリソースへアクセスする場合は「IAMユーザー」を利用
  • 人間以外のもの(AWSリソースなど)にアクセス権限を設定する場合は「IAMロール」を利用

SA = Kubernetesにおける「認証」

いっぽうでIRSAのSAの部分(=サービスアカウント)はK8sにおける権限管理リソースの一つです。
K8sの世界で認証に使われる「ユーザー」は実は2種類あります。

  • 通常のユーザー( User = IAMユーザーに近いもの)
  • サービスアカウント( ServiceAccount = IAMロールに近いもの)

すごく雑に言うと、「通常のユーザー」はAWSでいうIAMユーザーに近いもので、後者の「サービスアカウント」はIAMロールに近いものです。サービスアカウントはPodに対して権限を付与する際に使います。

そしてKubernetesの世界では「通常のユーザー」を扱うオブジェクトは無い(あくまでKubernetes外でユーザー管理される前提で、証明書などによる認証手段のみ存在)のですが、「サービスアカウント」はちゃんとKubernetes APIで管理されます。

IRSAの仕組みを図解

例えば、とあるPodからS3バケットへのアクセスを許可してあげたいとします。
スクリーンショット 2023-06-12 18.02.02.png

このEKSクラスターを指定して「IAM OIDCプロバイダー」を作成します。
スクリーン ショット 2023-06-18 に 16.36.18 午後.png

そしてEKSクラスター内に「サービスアカウント」を作成します。
一方でS3バケットへの許可ポリシーを付与したIAMロールを作成しておき、「サービスアカウント」のアノテーション(注釈)としてこのIAMロールのARNを記載しておきます。
スクリーンショット 2023-06-12 18.02.49.png

ここからが大事なところです。開発者(kubectlコマンド)がPodを起動する際、EKSではkube-apiserverから「Pod Identity Webhook」が呼び出されるようになっています。このWebhookはサービスアカウントの情報をPodの定義に仕込むようです。そしてkubeletがノード上でこのPodを起動するとき、サービスアカウントのOIDCトークンがPodへマウントされます。
スクリーンショット 2023-06-12 18.02.58.png

そしてようやく実アクセスです。PodがS3バケットへアクセスを試みる前に、アプリケーションからAWS SDK等でSTSへ一時認証を取得しにいきます。STSはPodのトークンが間違いなくこのEKSクラスターのIAM OIDCプロバイダーから発行されたものかチェックして、問題なければこのPodがIAMロールを時限付きでAssumeRole(権限取得)できるようにします。
スクリーンショット 2023-06-12 18.03.08.png

こうしてSTSでの一時認証が取得できたら、ようやく触りたかったAWSリソース(ここではS3バケット)へ実際にアクセスできるというわけです!

すごい雑に言うと、 「日本からアメリカに入国するために外務省からパスポートを発行されて、渡航先の入国審査場で国籍と属性をチェックされる」 ようなものですね。

※上記の流れは詳細なコンポーネントや挙動を割愛しています。また、著者の理解不足により正確でない記載を含む可能性があります。もし誤っている点に気づかれた際は、お知らせくださいますと幸いです。

実際にIRSAを使ってみよう!

AWSブログの以下記事のハンズオンを活用させていただきます。
IRSAの仕組みは少し複雑に聞こえますが、実際にやることはもっと簡単です!

環境準備

  • Macでターミナルを起動
  • aws-cli、ekstcl、kubectlをインストール

実験用EKSクラスターを作る

  • EKSクラスターを作成
Cloud9
eksctl create cluster \
  --name irsa \
  --region ap-northeast-1
  • Podを作成
Cloud9
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: pod-before
spec:
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      args: ['s3', 'ls']
  restartPolicy: Never
EOF
  • 今回PodからアクセスさせたいAWSリソース(S3バケット)への読み取りが、現時点では失敗していることをPodのログで確認
Cloud9
kubectl logs pod-before

IAMリソースとKubernetesサービスアカウントを作成

  • IAM OIDCプロバイダーを作成
Cloud9
eksctl utils associate-iam-oidc-provider --region=ap-northeast-1 --cluster=irsa --approve
  • サービスアカウントとIAMロールを作成。IAMロールには「S3読み取り許可」ポリシーをアタッチ。
Cloud9
eksctl create iamserviceaccount \
  --name my-sa \
  --namespace default \
  --cluster irsa \
  --approve \
  --attach-policy-arn $(aws iam list-policies --query 'Policies[?PolicyName==`AmazonS3ReadOnlyAccess`].Arn' --output text) 

※このコマンド一つで、サービスアカウントとIAMロールは相互に信頼する設定を含んだ状態で作成されてくれます。超便利ですね。

IRSAを適用したPodを起動してAWSリソースへのアクセスに再チャレンジ

  • 今回作ったサービスアカウントを利用してPodを新たに起動
Cloud9
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: pod-after
spec:
  serviceAccountName: my-sa 
  containers:
    - name: my-aws-cli
      image: amazon/aws-cli:latest
      args: ["s3", "ls"]
  restartPolicy: Never
EOF
  • S3バケットを読み取りできているか、Podのログを確認
Cloud9
kubectl logs pod-after

こちらのイベントで本内容を登壇予定です!

7/4に開催予定の初心者向けミートアップ「Kubernetes Novice Tokyo」でもこちらの話題についてライトニングトークを実施予定です。ご興味のある方はぜひ申し込みください!

Kubernetesの概要をおさらいしたい方は…

こちらの記事に主要コンポーネントの概要図をまとめました!

また、実際に初心者がKubernetesを触れるハンズオンも用意したのでご利用ください。

参考文献

Kubernetesの認証について

IRSAについて

46
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
8