📌

EKS Pod Identityを利用してセキュアにkubernetesリソースからAWSリソースにアクセスする

に公開

はじめに

AWS EKS (Elastic Kubernetes Service) を利用している場合、Kubernetes上のリソースだけで完結させることはほぼなく、多くの場合、kubernetesの世界にないAWSリソースにアクセスする必要があります。例えば、S3バケットへのファイルのアップロード、DynamoDBのテーブルへのデータの読み書き、SQSキューへのメッセージの送受信など、様々なユースケースが考えられます。その際に使用するのがPod Identityです。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/pod-identities.html

Pod Identityとは

Pod Identityは、Kubernetes上のPodがAWSリソースにアクセスするための認証情報を安全に取得するための仕組みです。これにより、PodはIAMロールを使用してAWSリソースにアクセスできるようになります。

Pod Identityは名前に反して、Pod単位でのアクセス制御をするわけではありません。Pod IdentityはEKSクラスタ上の Kubernetes Service Accountに対してIAMロールを関連付けます。 PodはService Accountを通じてIAMロールを取得し、そのIAMロールを使用してAWSリソースにアクセスします。

似たような仕組みとして、IRSA (IAM Roles for Service Accounts) がありますが、Pod Identityはより簡単に設定できるように設計されています。Pod Identityは、AWS EKSの公式アドオンとして提供されており、AWS CLIやAWS Management Consoleを使用して簡単にインストールできます。

IRSAに関してはこの記事では詳しく触れません。より詳細な情報はAWSの公式ドキュメントを参照してください。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/iam-roles-for-service-accounts.html

Pod Identityの仕組み

Pod Identityは、EKSクラスター上でPodがAWSリソースに安全にアクセスするための仕組みです。以下の手順で動作します。

  1. Pod Identity AgentをEKSクラスターにインストール
  2. 必要な権限を持つIAMロールを作成
  3. Service AccountとIAMロールを関連付け
  4. PodがService Accountを介してAWSリソースにアクセス

このプロセスでは、次のような認証フローが実行されます。

  • Pod Identity AgentがService Accountトークンを監視
  • PodがAWSリソースにアクセスを試みると、Agentがトークンを使用してAWS STSから一時的な認証情報を取得
  • 取得した認証情報を用いてPodがAWSリソースにアクセス

この仕組みにより、認証情報の自動ローテーションやPod単位での細かいアクセス制御が可能になり、認証情報がPod内に保存されるリスクを回避できます。

Pod Identityの設定方法

Pod Identity Agentアドオンのインストール

Pod Identity Agentは、EKSクラスターにアドオンとしてインストールします。

インストールはAWS CLI、GUI、そしてterraform eks moduleを使用してインストールすることができます。

Pod Identity Agentをインストールするとeks-pod-identity-agentというpodが作成されていることが確認できます。

❯ kubectl get -n kube-system pod | grep identity
eks-pod-identity-agent-v8x4n                                      1/1     Running   0          6m2s

IAMロールの作成

Pod IdentityでAWSリソースにアクセスするためには、以下のような信頼ポリシーを持つIAMロールを作成する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
            "Effect": "Allow",
            "Principal": {
                "Service": "pods.eks.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ]
        }
    ]
}

このとき、AssumeRoleはKubernetes Service AccountがIAMロールを引き受ける際に必要になります。
また、Pod IdentityはAWS STS へのリクエストにセッションタグを含めるために TagSession を使用します。

この信頼ポリシーをアタッチしたIAMロールに、podに付与したい権限を設定することで、PodがAWSリソースにアクセスできるようになります。

IAMロールとService Accountの関連付け

EKS上のService AccountとIAMロールを関連付けます。GUI上から設定することが可能です。

クラスター > アクセス > Pod Identity の関連付け > 作成

から、権限を与えたいpodに割り当てられているService Accountとnamespaceを選択します。

設定が完了すると、以下の画像のような状態になるはずです。

これにてPod Identityの設定は終了です。

terraform moduleの紹介

ここまでおこなってきた、必要なポリシー、権限をもったIAMロールの作成およびKubernetes Service Accountの作成をすべて担ってくれるterraform moduleが公開されています。

https://registry.terraform.io/modules/terraform-aws-modules/eks-pod-identity/aws/latest

例えば、AWS EBS CSI Driver用のPod Identityはこのモジュールを使って以下のように設定することができます。

module "aws_ebs_csi_pod_identity" {
  source  = "terraform-aws-modules/eks-pod-identity/aws"
  version = "1.11.0"

  name = "ebs-csi-controller"

  attach_aws_ebs_csi_policy = true

  # Pod Identity Associations
  associations = {
    "ebs-csi-controller" = {
      cluster_name    = "my-cluster"
      namespace       = "kube-system"
      service_account = "ebs-csi-controller-sa"
    }
  }
}

EBS CSI Driverについては公式ドキュメントを見てください。ドキュメントでは煩雑になりがちな設定を、このモジュールを使うことで非常に簡潔に、宣言的に書くことができます。

EBS CSI Driverは、通常kube-system namespaceにデプロイされ、ebs-csi-controller-saというService Accountを使用します。このモジュールを使うことで、IAMロールとService Accountの関連付けが簡単に行えます。

必要となる権限セットもモジュール側で用意がされており、IAMロールのことをほぼ考えずに、直にKubernetes Service Accoutnに権限を付与しているような感覚で使うことができます。

モジュールには、現在以下の権限セットが用意されており、フラグで簡単に権限を付与できます。

input description
attach_amazon_managed_service_prometheus_policy Amazon Managed Service for Prometheus用のポリシーをアタッチします。
attach_aws_appmesh_controller_policy AWS App Mesh用のポリシーをアタッチします。
attach_aws_appmesh_envoy_proxy_policy AWS App Mesh Envoy Proxy用のポリシーをアタッチします。
attach_aws_cloudwatch_observability_policy AWS CloudWatch Observability用のポリシーをアタッチします。
attach_aws_ebs_csi_policy AWS EBS CSI Driver用のポリシーをアタッチします。
attach_aws_efs_csi_policy AWS EFS CSI Driver用のポリシーをアタッチします。
attach_aws_fsx_lustre_csi_policy AWS FSx for Lustre CSI Driver用のポリシーをアタッチします。
attach_aws_gateway_controller_policy AWS Gateway Load Balancer用のポリシーをアタッチします。
attach_aws_lb_controller_policy AWS Load Balancer Controller用のポリシーをアタッチします。
attach_aws_lb_controller_targetgroup_binding_only_policy AWS Load Balancer Controller TargetGroup Binding用のポリシーをアタッチします。
attach_aws_node_termination_handler_policy AWS Node Termination Handler用のポリシーをアタッチします。
attach_aws_privateca_issuer_policy AWS Private CA Issuer用のポリシーをアタッチします。
attach_aws_vpc_cni_policy AWS VPC CNI用のポリシーをアタッチします。
attach_cert_manager_policy AWS Certificate Manager用のポリシーをアタッチします。
attach_cluster_autoscaler_policy AWS Cluster Autoscaler用のポリシーをアタッチします。
attach_custom_policy カスタムポリシーをアタッチします。
attach_external_dns_policy AWS External DNS用のポリシーをアタッチします。
attach_external_secrets_policy AWS External Secrets(Secret Managerm )用のポリシーをアタッチします。
attach_mountpoint_s3_csi_policy AWS S3 Mountpoint CSI Driver用のポリシーをアタッチします。
attach_velero_policy AWS Velero用のポリシーをアタッチします。

このように、用意されている権限セットは豊富ですが、必要に応じてカスタムポリシーを作成することも可能です。以下は、カスタムポリシーを作成してPod Identityを設定する例です。

module "custom_pod_identity" {
  source  = "terraform-aws-modules/eks-pod-identity/aws"
  version = "1.11.0"

  name = "custom-pod-identity"

  attach_custom_policy = true

  policy_statements = [
    {
      sid = "AllowReadingMetricsFromCloudWatch"
      actions = [
        "cloudwatch:DescribeAlarmsForMetric",
        "cloudwatch:DescribeAlarmHistory",
        "cloudwatch:DescribeAlarms",
        "cloudwatch:ListMetrics",
        "cloudwatch:GetMetricData",
        "cloudwatch:GetInsightRuleReport"
      ]
      resources = ["*"]
    },
  ]


  # Pod Identity Associations
  associations = {
    "grafana-eks" = {
      cluster_name    = "my-cluster"
      namespace       = "my-namespace"
      service_account = "my-service-account"
    }
  }
}

このように、それぞれのリソースで定義すると散らばりがちなIAMロールの設定を、モジュールを使うことで一元管理することができます。これにより、IAMロールの設定ミスや権限の過剰付与を防ぐことができ、セキュリティを向上させることができます。

まとめ

Pod Identityを使用することで、Kubernetes上のPodから安全にAWSリソースにアクセスすることができます。主なメリットは以下の通りです:

  • セキュアな認証情報の管理
  • きめ細かいアクセス制御
  • 簡単な設定と管理

適切に設定を行い、定期的に動作確認とセキュリティ監査を行うことで、安全なアプリケーション運用が可能になります。セキュリティのベストプラクティスに従うことで、より堅牢なシステムを構築することができます。

また、terraform moduleを使用することで、Pod Identityの設定を簡素化することが可能になります。

Discussion