[アップデート] EKS Pod Identity で簡単にクロスアカウントの権限付与ができるようになりました
こんにちは。クラウド事業本部の枡川です。
1 ヶ月前の話題ですが、EKS で Pod Identity を利用して権限付与を行う際、簡単にクロスアカウントアクセスを付与できるようになりました。
ここで 「エクスペリエンスが簡素化された」 と言っているのは、アプリケーション側で AssumeRole のことを意識せず、EKS 側の設定だけでクロスアカウントアクセスを扱えるということのようです。
どれだけ簡単になったのか、実際に構築して試してみようと思います。
リソース作成
今回は Terraform で下記構成を構築して、試してみます。
v6.2.0 以上の AWS Provider を利用していれば、Pod Identity を作成する際にクロスアカウントアクセスを設定できます。
role_arn
と合わせて、target_role_arn
を指定すれば良い形ですね!
target_role_arn - (Optional) The Amazon Resource Name (ARN) of the IAM role to be chained to the the IAM role specified as role_arn.
ただ、AWS EKS Terraform module を利用する条件として、aws provider が < 6.0.0
である必要があったので、今回は Pod Identity 周りのみマネジメントコンソールから設定することとします。
aws_eks_cluster などを使って、普通に定義しても良いんですけどね...
少し面倒だったのと、初めてその機能を触る際はマネジメントコンソールの方がわかりやすいって話もあるので!
ターゲットアカウント (DynamoDB が存在するアカウント) のリソース作成
まず、ターゲットアカウントに DynamoDB と IAM ロールを作成します。
もっと細かくアクセスを制限するべきかもしれませんが、ソースアカウント側で厳しく制限する前提で緩めのポリシーとしています。
resource "aws_dynamodb_table" "test-table" {
provider = aws.account-b
name = "test-dynamodb"
billing_mode = "PAY_PER_REQUEST"
hash_key = "UserId"
attribute {
name = "UserId"
type = "S"
}
}
data "aws_iam_policy_document" "pod_identity_assume_role_policy" {
statement {
effect = "Allow"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
actions = ["sts:AssumeRole", "sts:TagSession"]
}
}
resource "aws_iam_role" "dynamodb_access" {
provider = aws.account-b
name = "dynamo-db-access-role"
assume_role_policy = data.aws_iam_policy_document.pod_identity_assume_role_policy.json
}
resource "aws_iam_role_policy_attachment" "dynamodb_access" {
provider = aws.account-b
role = aws_iam_role.dynamodb_access.name
policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"
}
sts:AssumeRole
だけではなく、sts:TagSession
も付与することがポイントです。
※ 恐らく、Pod Identity 作成時にセッションタグを無効にするオプションを選択すれば不要ですが、基本権限を付与しつつ有効化で良いと思います。
DynamoDB には適当なデータを突っ込んでおきます。
ソースアカウント (EKS が存在するアカウント) のリソース作成
VPC を作成します。
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.17.0"
name = "eks-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.100.0/24", "10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
}
}
EKS (Auto Mode) と Pod Identity で指定する IAM ロールを作成します。
locals {
cluster_name = "test-cluster"
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.37.1"
cluster_name = local.cluster_name
cluster_version = "1.33"
cluster_endpoint_public_access = true
cluster_endpoint_private_access = true
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
enable_cluster_creator_admin_permissions = true
cluster_compute_config = {
enabled = true
node_pools = ["general-purpose"]
}
bootstrap_self_managed_addons = false
}
data "aws_iam_policy_document" "allow_pod_identity" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
actions = [
"sts:AssumeRole",
"sts:TagSession"
]
}
}
resource "aws_iam_role" "app" {
name = "app-sa-role"
assume_role_policy = data.aws_iam_policy_document.allow_pod_identity.json
}
resource "aws_iam_role_policy_attachment" "app" {
role = aws_iam_role.app.name
policy_arn = aws_iam_policy.assume_role_policy.arn
}
data "aws_iam_policy_document" "assume_role_policy" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole", "sts:TagSession"]
resources = [aws_iam_role.dynamodb_access.arn]
}
}
resource "aws_iam_policy" "assume_role_policy" {
name = "assume-role-policy"
policy = data.aws_iam_policy_document.assume_role_policy.json
}
Pod Identity の関連付け
関連付けの前に Kubernetes 側の権限を取得して、Service Account を作成します。
Pod Identity は Service Account と IAM ロールを関連付けて使うためです。
aws eks update-kubeconfig --name test-cluster
名前空間を作ります。
% kubectl create ns app
namespace/app created
Service Account も作成します。
% kubectl create sa app-sa -n app
serviceaccount/app-sa created
マネジメントコンソールから、Pod Identity の設定を行います。
Assume Role 可能な権限を付与した IAM ロールと、Assume Role 先の IAM ロールを指定します。
コンソールにも、クロスアカウントアクセスに関する記述がありますね!
続いて、下記のように DynamoDB アクセスを行う Python アプリケーションのコンテナを作成します。
この際、Assume Role に関する記述は一切書いておりません。
from fastapi import FastAPI
import boto3
app = FastAPI()
@app.get("/")
def read_root():
dynamodb = boto3.client("dynamodb", region_name="ap-northeast-1")
response = dynamodb.scan(
TableName="test-dynamodb",
)
return response["Items"]
Boto3 のassume_role を使えば同じことを実現できますが、アプリケーションがシンプルであることに越したことはないので嬉しいですね。
ではマニフェストファイルを用意して、アプリケーションコンテナを作成していきます。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: app
name: fast-api
spec:
selector:
matchLabels:
app.kubernetes.io/name: fast-api
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: fast-api
spec:
serviceAccountName: app-sa
containers:
- image: xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/fast-api-app:v3
imagePullPolicy: Always
name: fast-api
ports:
- containerPort: 80
resources:
requests:
cpu: "0.5"
Service を作成します。
apiVersion: v1
kind: Service
metadata:
namespace: app
name: fast-api
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app.kubernetes.io/name: fast-api
IngressClass を作成します。
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
namespace: app
labels:
app.kubernetes.io/name: LoadBalancerController
name: alb
spec:
controller: eks.amazonaws.com/alb
Ingress を作成します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: app
name: fast-api-ingress
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: fast-api
port:
number: 80
払い出された DNS 名にアクセスすると、無事クロスアカウントで DynamoDB 内のデータを取得できました!
% curl http://k8s-app-fastapii-821882c6be-1557614806.ap-northeast-1.elb.amazonaws.com
[{"UserId":{"S":"1"},"Name":{"S":"Taro"}}]
最後に
EKS 側の設定だけで、簡単に Pod に対してクロスアカウントの権限を付与することができました!
aws-for-fluent-bit の Pod Identity 対応や Auto Mode への Pod Identity Agent 組み込みなどもあり、いよいよ新規構築時は Pod Identity を選ばない理由が無くなってきた感じがあります。
皆さんも是非、便利にセキュアに便利に EKS を使っていきましょう!