Terraform で最小権限のサービスアカウントを使用する GKE クラスターを作る
先日 GKE クラスタを Terraform で作成する機会があり、不明点やハマったポイントがあったのでメモとして残しておこうと思います。
クラスタのセキュリティの強化: 権限 - 最小限の権限の Google サービス アカウントを使用する
この記事では、Terraform を使用して、GKE ノード用のサービス アカウントと、それを使用する GKE ノード プールをあわせて作成するためのコードを紹介します。 GKE クラスター自体のコードは Terraform のドキュメント等を参照してください。
IAM ロールとアクセス スコープ
この 2 つの違いで少々混乱したので簡単にまとめてみる。
- IAM ロール
- GCP リソースへのアクセス権限
- サービス アカウントに割り当てる
- アクセス スコープ
- GCE インスタンスに設定する
- インスタンス上で GCP API のクライアントがアクセス可能な API の種類を制限する
例えば、 GCR のプライベート レジストリからコンテナー イメージを pull したい場合は、サービス アカウントに "roles/storage.objectViewer"
を割り当て、 GCE インスタンスのアクセス スコープには "https://www.googleapis.com/auth/devstorage.read_only"
を設定する。
サービス アカウントの作成とロールの割り当て
GCE のデフォルトのサービス アカウントには、プロジェクトの編集者ロールが割り当てられており、 GKE クラスターの動作には過剰な権限が含まれる。 そのため、 GKE クラスター用のサービス アカウントを作成し、必要な権限のロールのみを割り当てる構成をつくる。
まずは google_service_account
リソースを使用し、 GKE ノード用のサービス アカウントを作成する。
そして google_project_iam_member
リソースで、 GKE で最低限となるロール (monitoring.viewer
, monitoring.metricWriter
, logging.logWriter
) をサービス アカウントに割り当てる。
# Service Account
resource "google_service_account" "gke_node_pool" {
account_id = "gke-node-pool"
display_name = "gke-node-pool"
description = "A service account for GKE node"
}
# IAM Role binding
resource "google_project_iam_member" "gke_node_pool_roles" {
for_each = toset([
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
"roles/monitoring.viewer"
])
role = each.value
member = "serviceAccount:${google_service_account.gke_node_pool.email}"
}
注意点としては、ロールの割り当てに google_project_iam_binding
リソースを使用しないようにする。
こちらは「あるロールに対して指定したメンバーを割り当てる」挙動となり、
2つ目以降の iam_binding
を作成したところメンバーの割り当てが上書きされ、
当該ロールを使用する既存のサービスアカウントからロールが外れてしまった。
GKE ノードプールの作成
続いて google_container_node_pool
リソースで GKE ノード プールを作成する。
node_config.service_account
には作成したサービス アカウントの email
を指定する。
oauth_scopes
には cloud-platform
(Web コンソールから SA を指定したクラスターを作った場合の既定値) を指定する。
# GKE Node Pool
resource "google_container_node_pool" "node_pool" {
name = "node-pool"
location = var.location
cluster = google_container_cluster.cluster.name
initial_node_count = 1
...
node_config {
service_account = google_service_account.gke_node_pool.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
...
}
}
まとめ
for_each
で複数ロールを割り当てられるようにするとべんり- oauth_scopes は必要に応じてさらに狭い範囲にしても良さそう
- https://www.terraform.io/docs/providers/google/r/container_cluster.html#oauth_scopes-1
- サービス アカウントにロール付与しても動作しない場合は、対応するスコープが設定されているか確認する
Previous Post
Next Post