LoginSignup
14
8

More than 3 years have passed since last update.

eksctlを使わずterraformを使ってIAM Roles for Service Accounts

Posted at

https://aws.amazon.com/jp/blogs/news/introducing-fine-grained-iam-roles-service-accounts/
最近EKSにServiceAccountに紐付いたrole arnでIAM権限を付与する仕組みが実装されました
非の打ち所のないような公式ドキュメントで、eksctlを使う場合は上のドキュメントを読んでいただければ完璧に理解できると思います、この記事ではeksctlではなくterraformを使って IAM Roles for Service Accounts を使用する手順を記載します
* 東京リージョンで作成することを想定しています

source code: https://github.com/keiSunagawa/qiita/tree/master/eks-sa-2-iam

そもそも何ができるようになったの?

従来のEKSではWorkerNodeのIAM roleがPod内に引き継がれる仕様でした
つまり、Pod内のアプリケーションからAWSリソースへアクセスするための権限を、対象のPodがデプロイされる可能性のある全てのWorkerNode自身につける必要がありました
これを回避するためにPod自身に(正確にはServiceAccountに)IAM roleを付与する方法が今回追加されました
* ちなみに以前から kiam などを使えば同様のことができたそうですが、僕はよく知らないので説明しません

OpenID Connect

今回追加された IAM Roles for Service Accounts を構成する要素の一つ
OAuth2.0の仕様を拡張し、IDトークン と呼ばれる情報を取得できるようにした認可/認証のための仕様
IAM Roles for Service Accounts ではこれに則って認可/認証を実装しているため
OpenID Connect という用語がドキュメントやコンソールにちらほら出てきます
ただし、今回の機能を使う上でほとんどEKSとIAM(及びSTS)の間で完結している話なのでユーザはあまり気にしなくても良かったりします

環境構築

冒頭で貼った source code に沿って説明します

  • VPC ~ EKS ~ EC2 この辺は通常通りなので特に説明をしません
  • IAM
    worker & master用のロールとServiceAccount用のロールを付与します
    • worker & master用のロール
      通常通り、EKSに必要なポリシー以外は付与しません
    • ServiceAccount用のロール assume_role_policy がworkerの付与するロールと違っているので注意 あとで付与するPodのためにCloudWatchLogsのFullAccessを付与します
sa-iam.tf
resource "aws_iam_role" "eks_log_role" {
  name = "${local.prefix}_eks_log_role"

  assume_role_policy = <<EOS
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
          "Federated": "${aws_iam_openid_connect_provider.for_eks.arn}"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "${aws_iam_openid_connect_provider.for_eks.url}:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}
EOS

resource "aws_iam_role_policy_attachment" "eks_log_role_policy" {
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccess"
  role       = "${aws_iam_role.eks_log_role.name}"
}
  • IAM OpenID Connect Provider
    EKSをidP(OpenID Connectで言う認証を行うためのサーバ)とするための設定を作成します thumbprintはidPのドメインの証明書から生成しますが、リージョンが ap-northeast-1 の場合はソースそのままで問題ありません(もちろん証明書が差し替わった場合は変更になります)
    自分で作成したい場合は以下の手順が参照できます
    https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
oidcp.tf
resource "aws_iam_openid_connect_provider" "for_eks" {
  url = "${aws_eks_cluster.main_eks.identity.0.oidc.0.issuer}"

  client_id_list = [
    "sts.amazonaws.com"
  ]
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
}

マニフェストファイル

  • ServiceAccount
    annotations に環境構築で作ったarnを記載します、このアノテーションをみてEKSは認証方式を判断します(厳密に言うとSTS認証方式向けの環境変数と値のファイルを作成します)
service-account.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: <your role arn>
  name: fluentd
  namespace: kube-system
  • DaemonSet
    特に特筆することはない、通常のDaemonSetです、上記で作ったServiceAccountを紐付けます
    今回はCloudWatchにfluentdでログを転送するアプリケーションをデプロイすることにします

Let's Deploy

$ cd play-ground/eks-sa-2-iam/terraform

$ terraform init && terraform apply

$ vim ~/.kube/config # 接続先情報の編集

$ terraform output eks_configmap | kubectl apply -f -

$ cd ../k8s

$ vim service-account.yml # metadata.annotations.eks.amazonaws.com/role-arnを作成したServiceAccount用roleのarnで書き換え

$ kubectl apply -f .

fluentdよりCloudWatchにログが流れていれば成功です

確認

$ kube get pods fluentd-k8sd5 -n kube-system -o yaml

podの情報を取得すると、マニフェストファイルに記載しておらず、EKSによって自動で付与された環境変数 AWS_ROLE_ARN AWS_WEB_IDENTITY_TOKEN_FILE やvolumeの aws-iam-token などを確認することができます
aws client(およびsdk)はこれらの情報を使い、STS経由で認証/認可を行うことができます

14
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
14
8