Amazon Web Services ブログ

Kubernetes サービスアカウントのクロスアカウント IAM ロール



サービスアカウントへの IAM ロール (IRSA) の導入により、Kubernetes でのワークロード要件に固有な IAM ロールを作成できるようになりました。このため、ノードレベルではなくポッドレベルでの詳細に設定されたロールを作成でき、最低限の特権のセキュリティ プリンシパルも有効になります。このブログ投稿では、ポッドのクロスアカウントロールを引き受ける必要があるユースケースを見ていきます。

ユースケース

デベロッパーアカウントと shared_content AWS アカウントがある、次のシナリオを考えてみましょう。Amazon Elastic Kubernetes Service (Amazon EKS) クラスターのポッドとしてデベロッパーアカウントで実行する開発ワークフローでは、shared_content アカウントの pics S3 バケットに保存されているいくつかの画像にアクセスする必要があります。

IRSA 以前の手順

IRSA 導入前に shared_content アカウントの pics バケットにアクセスするには、次の手順を実行します。

  1. shared_content アカウントに S3_Pics ロールを作成し、shared_content アカウントとデベロッパーアカウントの間に信頼関係を作成します。
  2. S3_Pics ロールにポリシーを添付して、ReadOnlyAccess が pics バケットへのアクセスのみを許可するようにします。
  3. Amazon EC2 信頼関係ポリシーをデベロッパーアカウントの Amazon EKS (EKS) ワーカーノードロールに添付します。.
  4. EKS ワーカーノードのロールにポリシーを添付し、EKS ワーカーノードが sts:AssumeRole 操作を実行できるようにします。

このアプローチには大きな欠点があり、その 1 つに EKS ワーカーノードで実行しているすべてのポッドが shared_content アカウントの pics バケットにアクセスできることがあります。加えて、Kubernetes スケジューラは任意のワーカーノードにポッドをスケジューリングする可能性があるため(追加のポッド配置設定を使用している場合を除く)、すべての EKS ワーカーノードにポリシーを添付する必要があることも欠点として挙げられます。

IRSA の手順

1.デベロッパーアカウントで、EKS クラスターの IAM OpenID Connect プロバイダーを関連付けます。

eksctl utils associate-iam-oidc-provider —name development-cluster --approve

2.shared_content アカウントに IAM OIDC プロバイダーを作成します。IAM コンソールは OIDC IdP の ROOT_CA_THUMBPRINT を自動的にフェッチするため、これを使用します。ただし、ROOT_CA_THUMBPRINT は手動でフェッチして確認することをお勧めします。

プロバイダー URL はデベロッパーアカウントの EKS クラスターからの OpenID Connect プロバイダー URL に対応し、対象ユーザーを sts.amazonaws.com に設定します。

次のステートメントを使用して、プロバイダー URL を取得できます。

aws eks describe-cluster —name development-cluster --query "cluster.identity.oidc.issuer" --output text

3.pics バケット内のすべてのオブジェクトに ReadOnlyAccess を提供する shared_content アカウントで、ロールを作成します。OIDC プロバイダーによってフェデレーションされたユーザーは、このロールを引き受けることができます。

 "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::shared_content_account_id:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/oidc-id"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.us-east-1.amazonaws.com/id/oidc-id:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}

以下は、ポリシードキュメントの例です。

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "s3-bucket",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::pics/*"
}
]
}

4.development-cluster にサービスアカウントを作成し、ステップ 3 で作成したロールの ARN で注釈を付けます。

$ kubectl create sa s3-shared-content

$ kubectl annotate sa s3-p shared-content eks.amazonaws.com/role-arn=arn:aws:iam:: shared-content-account-id:role/s3-read-object
serviceaccount/s3- shared-content annotated
 $

5.次に、ポッド仕様でサービスアカウントを指定します。以下は、私のポッド仕様のスニペットです。

spec:
      serviceAccountName: s3- shared-content
      containers:
      - image: nginx
        name: nginx

処理が機能することを確認する

このポッドに bash シェルを添付して、sts:AssumeRoleWithWebIdentity コールを使ってロールを引き受けましょう。前提条件はこちらにあります。

$ kubectl exec -it nginx-8578f9978-7dhdx bash
root@nginx-8578f9978-7dhdx:/#

ポッド内の一時的な認証情報にアクセスします。

root@nginx-8578f9978-7dhdx:/# aws sts assume-role-with-web-identity --role-arn $AWS_ROLE_ARN --role-session-name x-account --web-identity-token file://$AWS_WEB_IDENTITY_TOKEN_FILE --duration 1500 > /tmp/temp_creds.txt
root@nginx-8578f9978-7dhdx:/# export AWS_ACCESS_KEY_ID="$(cat /tmp/temp_creds.txt | jq -r ".Credentials.AccessKeyId")"
root@nginx-8578f9978-7dhdx:/# export AWS_SECRET_ACCESS_KEY="$(cat /tmp/temp_creds.txt | jq -r ".Credentials.SecretAccessKey")"
root@nginx-8578f9978-7dhdx:/# export AWS_SESSION_TOKEN="$(cat /tmp^Cemp_creds.txt | jq -r ".Credentials.SessionToken")"

GetObject 操作を実行します。

root@nginx-8578f9978-7dhdx:/# aws s3api get-object —bucket pics --key indoor-cat.jpg mypic.jpg
{
 "AcceptRanges": "bytes",
 "ContentType": "image/jpeg",
 "LastModified": "Sat, 04 Jan 2020 22:18:56 GMT",
 "ContentLength": 5556,
 "ETag": "\"f9af61fc922ae24a3ad143e316a67d2d\"",
 "Metadata": {}
}

これで、IRSA を使用してポッド内のクロスアカウントリソースに正常にアクセスできました。

注: EKS クラスターの Blue/Green の更新を実行している場合(たとえば、異なるバージョンで新しい EKS クラスターをプロビジョニングしたり、アプリケーションを新しいクラスターに移行したりする場合)、新しいクラスターは別の OIDC プロバイダー URL に関連付けられているため、この作業によってロールでの変更が引き起こされる可能性があります。これを回避するには、ポッドが shared_content アカウントでロールを引き受けることを許可するポリシーをデベロッパーカウントで作成します。これで、アプリケーション内で標準の sts:AssumeRole 操作を実行できます。

まとめ

簡単に IRSA を拡張することで、ポッドが安全にクロスアカウントリソースにアクセスできるようにすることができます。OIDC IdP プロバイダーは、Amazon EKS クラスターで暗黙的に作成されます。EKS クラスターで実行しているポッドは IdP を使って認証されるため、OIDC プロバイダーによってフェデレーションされたエンティティを許可するロールはクロスアカウントアクセスを許可します。これにより、Kubernetes ワーカーノードレベルでロールを割り当てる必要がなくなるため、全体的なセキュリティ体制が大幅に改善します。