こんにちは、上野です。
久しぶりにGoogle Cloudの内容を書きます。大規模にGoogle Cloudを利用する場合、フォルダやプロジェクト、およびそのセキュリティ設定の管理が悩みポイントになってきます。その管理方法の1例を紹介します。
Google Cloudにおけるフォルダについて
複数のプロジェクトを管理する場合、フォルダを使用すると便利です。AWSでいうとOU(organizational units、組織単位)に近い概念です。部門や環境(開発、本番)など管理範囲別にフォルダを作成し、フォルダ内に複数のプロジェクトを配置できます。階層的なフォルダ構造も可能です。
フォルダ単位でIAMロールの付与、ログの集約、組織ポリシーの設定が一括でできるので複数プロジェクトの管理が捗ります。
フォルダも数が増えてくるとその管理が難しくなってくる場合もあります。たとえば監査ログの集約や組織ポリシーなど、フォルダごとに共通で行うべき設定があった場合、都度行うのも大変です。
Terraformによる組織設定の自動プロビジョニング
今回はフォルダの作成と、フォルダのセキュリティ設定をサンプルとして、Terraformで実装する例を紹介します。Terraformを使用する理由は私が経験があるという部分もあるのですが、Google Cloud公式のsecurity foundations guideでTerraformサンプルが紹介されていたり、Googleとして推している部分も多少はあるようです。
Terraform以外でいうと、Deployment ManagerやConfig Controllerが候補になると思います。
今回のサンプル設定例
初期状態で以下のように組織内に1個プロジェクト「audit」を作成しておきます。
図の構成には入れていませんが、Terraformのstateを配置するCloud Storageバケットも用意しておきます。
その後、Terraformで以下の紫枠の部分を作成します。
具体的なリソースは以下のとおりです。
- 新規フォルダ作成
- 監査ログのデータアクセスログON(Cloud Storage)
- 監査ログのログシンク(エクスポート)先Big Queryデータセット
- 監査ログのログシンク設定
監査ログはフォルダ単位で設定し、エクスポート先はあらかじめ用意していたauditプロジェクト内にBig Queryデータセットを作成し、そこにシンクします。
できるだけ構成をシンプルにお伝えするため、監査ログに絞ってサンプルを紹介しています。
Terraformコード内容
それでは実際のコード構成の中身に入っていきます。 ファイル構造は以下のとおりです。
同じフォルダ構成を複数再現するため、Terraformのmodule機能を使用します。
. ├── folder_module │ ├── resource.tf │ └── variables.tf ├── backend.tf ├── main.tf ├── povider.tf └── terraform.tfvars
povider.tf
- provider設定。デフォルトのプロジェクトやzoneも記載できますが、今回はリソースごとに記載するため空の状態で書いておきます。
provider "google" {}
backend.tf
- backendにはstateファイルを格納するCloud Storageバケットを指定しておきます。
- 値はサンプルです。
terraform { backend "gcs" { # Stateファイル保存先GCSバケット bucket = "tf-state-hoge" prefix = "terraform/state" } }
terraform.tfvars
- 変数格納用のterraform.tfvars。組織IDとログ保存先データセットを作成するプロジェクトIDを記載しておきます。
- 組織やプロジェクトが変わる場合は、ここを書き換えればOKです。
- 値はサンプルです。
# 組織ID org_id = "000000000000" # 監査ログ保存データセット作成先プロジェクト log_project_id = "audit-hoge"
main.tf
- module呼び出し用のmain.tf。作成したいフォルダが増えたら、このブロックを追加していくことになります。
variable "org_id" {} variable "log_project_id" {} module "folder01" { source = "./folder_module" org_id = var.org_id log_project_id = var.log_project_id folder_name = "folder01" }
folder_module/variable.tf
- moduleへ渡す変数の定義です。
variable "org_id" {} variable "folder_name" {} variable "log_project_id" {}
folder_module/resource.tf
- moduleとして作成するリソースの定義です。
- 今回のメインとなるファイルです。
- フォルダ作成、GCS監査ログのオン、ログルーターの作成を定義しています。
# フォルダ resource "google_folder" "organization_folder" { display_name = var.folder_name parent = "organizations/${var.org_id}" } # 監査ログ格納用データセット resource "google_bigquery_dataset" "auditlog" { project = var.log_project_id dataset_id = "${var.folder_name}_auditlog" } resource "google_bigquery_dataset_access" "auditlog_access" { project = var.log_project_id dataset_id = google_bigquery_dataset.auditlog.dataset_id role = "roles/bigquery.dataEditor" iam_member = google_logging_folder_sink.auditlog.writer_identity } # 監査ログ追加設定(GCS有効) resource "google_folder_iam_audit_config" "audit_config" { folder = google_folder.organization_folder.name service = "storage.googleapis.com" audit_log_config { log_type = "DATA_READ" } audit_log_config { log_type = "DATA_WRITE" } audit_log_config { log_type = "ADMIN_READ" } } # ログ集約ルーター resource "google_logging_folder_sink" "auditlog" { name = "${var.folder_name}-auditlog-sink" folder = google_folder.organization_folder.name include_children = true destination = "bigquery.googleapis.com/${google_bigquery_dataset.auditlog.id}" # Auditlog filter = "logName:cloudaudit.googleapis.com" }
Terraform実行
ファイルの準備ができたので実行していきます。
事前の準備として、gcloudとterraformをインストールしておきます。
$ gcloud --version Google Cloud SDK 393.0.0 alpha 2022.07.08 beta 2022.07.08 bq 2.0.75 bundled-python3-unix 3.9.12 core 2022.07.08 gsutil 5.10 $ terraform --version Terraform v1.2.5 on linux_amd64
Terraformの認証は、今回PC上から実行するためApplication Default Credentials ("ADCs")を使用します。
Terraformのドキュメントにも認証方法のパターンが記載されています。
$ gcloud auth application-default login Your browser has been opened to visit: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=・・・ tcgetpgrp failed: Not a tty
gcloud auth application-default login
を実行すると上記のように表示され、ブラウザでログインが促されるので、アクセスを許可します。
すると以下のように表示され、~/.config/gcloud/application_default_credentials.json
に認証情報が格納されます。
Credentials saved to file: [/home/username/.config/gcloud/application_default_credentials.json] These credentials will be used by any library that requests Application Default Credentials (ADC).
認証が完了したので、Terraformを実行していきます。
※認証したユーザーには対象組織やプロジェクトにIAMロールの付与が必要です。今回は細かくなるので詳細な権限について割愛します。
以下のとおり、terraform init
→ terraform plan
→ terraform apply
の順に実行していくだけです。出力結果は長くなるので一部省略しています。
- init
$ terraform init Initializing modules... - folder01 in folder_module Initializing the backend... Successfully configured the backend "gcs"! Terraform will automatically use this backend unless the backend configuration changes. 省略 Terraform has been successfully initialized!
- plan
$ terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # module.folder01.google_bigquery_dataset.auditlog will be created + resource "google_bigquery_dataset" "auditlog" { 省略 } # module.folder01.google_bigquery_dataset_access.auditlog_access will be created + resource "google_bigquery_dataset_access" "auditlog_access" { 省略 } # module.folder01.google_folder.organization_folder will be created + resource "google_folder" "organization_folder" { 省略 } # module.folder01.google_folder_iam_audit_config.audit_config will be created + resource "google_folder_iam_audit_config" "audit_config" { 省略 } # module.folder01.google_logging_folder_sink.auditlog will be created + resource "google_logging_folder_sink" "auditlog" { 省略 } Plan: 5 to add, 0 to change, 0 to destroy. ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
- apply
$ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # module.folder01.google_bigquery_dataset.auditlog will be created + resource "google_bigquery_dataset" "auditlog" { 省略 } # module.folder01.google_bigquery_dataset_access.auditlog_access will be created + resource "google_bigquery_dataset_access" "auditlog_access" { 省略 } # module.folder01.google_folder.organization_folder will be created + resource "google_folder" "organization_folder" { 省略 } # module.folder01.google_folder_iam_audit_config.audit_config will be created + resource "google_folder_iam_audit_config" "audit_config" { 省略 } # module.folder01.google_logging_folder_sink.auditlog will be created + resource "google_logging_folder_sink" "auditlog" { 省略 } Plan: 5 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.folder01.google_folder.organization_folder: Creating... module.folder01.google_bigquery_dataset.auditlog: Creating... 省略 Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
実行結果を見てみる
以下のように組織配下にフォルダが作成されています。
フォルダ単位のログシンクもOKです。
せっかくなので、監査ログをONにした、GCSについて、バケットを作成して監査ログがシンクされるか確認してみます。作成したfolder01は、プロジェクトが無い状態なので、手動で作成します。
バケットを作成し、
1ファイルアップロードしました。
この状態で、集約した監査ログのBigQueryデータセットにクエリ実行してみます。
すると以下のように、バケット作成のログがクエリできていることがわかります。
フォルダ作成、GCS監査ログON、BigQueryへの集約がTerraformで実行できました。
試した構成は以下のとおりです。
フォルダを増やす場合
同じ設定を増やす場合は、main.tfに以下のようにmoduleの呼び出し部分をそのまま追加し、terraform init
→ terraform apply
を実行すれば同じ構成のフォルダがもう一つ作成されます。
variable "org_id" {} variable "log_project_id" {} module "folder01" { source = "./folder_module" org_id = var.org_id log_project_id = var.log_project_id folder_name = "folder01" } # 追加 module "folder02" { source = "./folder_module" org_id = var.org_id log_project_id = var.log_project_id folder_name = "folder02" }
以下のようにfolder02が増える形です。
実行ログは1つ目とほぼ同じになるので、省略します。
まとめ
Google Cloudの複数プロジェクト管理について、フォルダおよびセキュリティリソースの作成手法の一つとしてTerraformを紹介しました。作成されたリソースの変更、削除については、IAMで変更できないよう制御するなど、別途検討が必要となります。
1つの管理方法サンプルとして、参考になれば幸いです。他の方の管理方法も聞いてみたいです。