IAM Roles for Service Accounts を Terraformで手軽に体験してみる

2019年 9月 4日、EKSにIAM Roles for Service Accountsの機能が追加されました!

このアップデートにより、Kubernetesのサービスアカウントと、AWSのIAMを紐付けて運用することができるようになりました。

これまでと現在

今までは Pod に対して AWS リソースに対するアクセス権限を割り当てたい場合、 Node に IAM ロールを割り当てるしかありませんでした。 この方法を使うと、Node で動く Pod に対してすべての権限が振ってくるのでセキュリティ上問題がありました。

しかし今回のアップデートで Pod に対して IAM ロールを割り当てることが可能になりました。

IAM Role for Podsを用いることで、必要なPodに必要なだけの権限を付与することができるため、最小権限の原則を守ることができます。

手軽に体験する

この記事は、Introducing Fine-Grained IAM Roles for Service Accounts に基づいています。

元記事ではeksctlを用いてクラスタやIAMの作成を行っているのですが今回はTerraformを用いて環境を構築します。

Terraformを用いて構築することでGitHubなどにインフラの構成を残しておくことができます。

今回使用するコードはGitHubにあるため、適宜参照してください。

IAM Roles for Service Accounts をやるための準備

今回は、以下のバージョンで行いました。 - Terraform v0.12.9

以下の流れに沿って解説をします。

  1. EKSのクラスタを作成する

  2. EKS の OpenID Connect Provider URL を用いて OIDC プロバイダーを作成する

  3. OIDC プロバイダーを利用する IAM ロールをつくる

  4. Kubernetes サービスアカウントを作成する

  5. S3のbucketをつくる

EKSのクラスタを作成する

今回、terraform-aws-modules/eks/aws というmoduleを使用しています。

module "next-cluster" {
  source  = "terraform-aws-modules/eks/aws" #https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/6.0.0
  version = "6.0.0"

  cluster_name                    = "${local.cluster_name}"
  cluster_version                 = "${local.cluster_version}"
  cluster_endpoint_private_access = true
  manage_aws_auth                 = false
  subnets                         = "${module.vpc.public_subnets}"
  vpc_id                          = "${module.vpc.vpc_id}"

  worker_groups = []

  write_aws_auth_config = false
  write_kubeconfig      = false
  tags                  = "${local.tags}"
}

EKS の OpenID Connect Provider URL を用いて OIDC プロバイダーを作成する

resource "aws_iam_openid_connect_provider" "oidc_provider" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"] # CA thumbprint
  url             = "${module.next-cluster.cluster_oidc_issuer_url}"
}

先ほど作成したEKSのoidc_issuer_urlを用いて、 ODIC プロバイダーを作成します。

OIDC プロバイダーを利用する IAM ロールをつくる

1. KMS にアクセスできる IAM policy をつくる

resource "aws_iam_policy" "s3" {
  name   = "s3_read_only"
  policy = "${data.aws_iam_policy_document.s3.json}"
}

data "aws_iam_policy_document" "s3" {
  statement {
    effect    = "Allow"
    resources = ["*"]

    actions = [
      "s3:*",
    ]
  }
}

2. IAM Role for Service Accounts に利用する IAM Roleをつくる

resource "aws_iam_role" "s3_service_account" {
  assume_role_policy = "${data.aws_iam_policy_document.s3_service_account.json}"
}

data "aws_iam_policy_document" "s3_service_account" {
  statement {
    effect = "Allow"
    actions = [
      "sts:AssumeRoleWithWebIdentity"
    ]
    principals {
      type        = "Federated"
      identifiers = ["${aws_iam_openid_connect_provider.oidc_provider.arn}"]
    }
    condition {
      test     = "StringEquals"
      variable = "${replace(aws_iam_openid_connect_provider.oidc_provider.url, "https://", "")}:sub"
      values = [
        "system:serviceaccount:default:vault-unseal"
      ]
    }
  }
}

3. IAM Role と IAM Policyを紐付ける

resource "aws_iam_role_policy" "s3_service_account" {
  policy = "${data.aws_iam_policy_document.s3.json}"
  role   = "${aws_iam_role.s3_service_account.name}"
}

Kubernetes サービスアカウントをつくる

terraform applyすると、3つファイルが出てきます。

  • aws-auth

  • kubeconfig

  • s3_serviceaccount

kubeconfigを用いて、aws-auths3_serviceaccountをapplyしてください。

S3のbucketをつくる

resource "aws_s3_bucket" "bucket" {
  bucket = "terraform-bucket-test-hello-hello"
  acl    = "private"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

bucketの名前は世界でユニークなので変更しておいてください。

これで準備は完了です。

s3へファイルを保存してみる

https://github.com/mhausenblas/s3-echoer をもちいて、IAM Roles for Service Accounts ができているかテストします。

git clone https://github.com/mhausenblas/s3-echoer.git && cd s3-echoer

s3-echoer-job.yaml.template をコピーして、s3-echoer-job.yamlとし、 serviceAccountName, TARGET_BUDGET, DEFAULT_AWS_REGION, をそれぞれ変更します。

変更したあと、kubectl apply -f s3-echoer-job.yaml でS3に保存するJobが走ります。

ここで、S3を確認してファイルが保存されていることを確認しましょう。

おわりに

今回、 IAM Roles for Service Accounts をeksctlではなくTerraformを用いて実現する方法について紹介しました。 この記事は、HERPでインターンをしているときの成果です。

株式会社HERPは、先日資金調達をしたり、京都と筑波に開発拠点が増えたりと今ノリに乗っている会社だと思います。 また、プロダクトの方もTypeScript + Haskell と面白い技術スタックなので興味ある方はぜひ!

www.wantedly.com

www.wantedly.com

参考

Introducing Fine-Grained IAM Roles for Service Accounts [アップデート] EKSでIAMロールを使ったPod単位のアクセス制御が可能になりました!