【GCP × GitLab】Terraformで構築するキーレスでセキュアなCI/CDパイプライン
はじめに
個人開発で仮想通貨のデータ分析基盤を構築する際、インフラ管理とデプロイの自動化にTerraformとGitLab CI/CDを導入しました。 本記事では、「サービスアカウントキー(JSON)を発行・管理しない」 セキュアなWorkload Identity連携を用いたデプロイフローの実装について紹介します。
1. Terraformとは
Terraformは、HashiCorp社が開発した**IaC(Infrastructure as Code)**ツールです。 AWS、GCP、Azureなどのクラウドインフラのリソース定義をコード(HCL)として記述し、構築・変更・管理を自動化できます。
2. 導入のメリット
GUI(コンソール画面)でのポチポチ管理と比較して、以下のメリットがあります。
-
コードによるバージョン管理: インフラの変更履歴をGitで追跡でき、いつでも過去の状態に戻せる
-
再現性: 誰がいつ実行しても同じ構成が作られます。「本番環境と開発環境の設定が微妙に違う」といった事故を防げる
-
セキュアな認証管理: 今回の構成の要ですが、TerraformでWorkload Identity Federationを設定することで、CI/CDツールに強力な権限を持つ永続的な鍵(JSONファイル)を保存する必要がなくなる
3. 実装
今回の構成は以下の通りです。
インフラ: GCP (Artifact Registry, Cloud Run Jobs, IAM)
CI/CD: GitLab CI/CD
認証: Workload Identity Federation
3.1 Terraformによる認証基盤の構築
まず、GitLab CIがGCPのリソースを操作できるようにするための認証基盤を定義します。
ポイント:Workload Identity Poolの作成 GitLabからのOpenID Connect (OIDC) トークンを検証し、GCPのサービスアカウントになりすますための設定です。
# Workload Identity Pool の作成
resource "google_iam_workload_identity_pool" "gitlab_pool" {
project = var.gcp_project_id
workload_identity_pool_id = var.workload_identity_pool_id
display_name = "GitLab CI/CD Pool"
}
# Provider の作成(GitLabとの信頼関係設定)
resource "google_iam_workload_identity_pool_provider" "gitlab_provider" {
# ... (略) ...
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.project_path" = "assertion.project_path"
}
oidc {
issuer_uri = "https://gitlab.com"
}
# 特定のプロジェクトからのリクエストのみ許可する制限
attribute_condition = "attribute.project_path == '${var.gitlab_project_path}'"
}
ポイント:権限の付与
CI/CD用のサービスアカウントを作成し、必要なロール(Cloud Run管理者、Artifact Registry書き込み等)のみを付与します。そして、roles/iam.workloadIdentityUser を介して、GitLabからのアクセスとこのSAを紐付けます。
# GitLabがこのSAとして振る舞えるようにする
resource "google_service_account_iam_member" "workload_identity_user" {
service_account_id = google_service_account.gitlab_ci_sa.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.gitlab_pool.name}/attribute.project_path/${var.gitlab_project_path}"
}
3.2 GitLab CI/CD パイプラインの設定
Terraformで構築した認証基盤を利用して、デプロイを行うパイプラインです。永続的なクレデンシャルを持たず、ジョブ実行時に発行される一時的なトークンを使用します。
deploy:
stage: deploy
image: docker:24.0.5
# OIDCトークンの発行(TerraformのOutputで得たProvider名を指定)
id_tokens:
GCP_WIF_TOKEN:
aud: $GCP_WORKLOAD_IDENTITY_PROVIDER
before_script:
# ... (Google Cloud SDKインストール等は省略) ...
# 認証ファイルの作成:GitLab発行のトークン(GCP_WIF_TOKEN)を使って認証
- |
echo '{ "type": "external_account", "audience": "'$GCP_WORKLOAD_IDENTITY_PROVIDER'", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'$GCP_SERVICE_ACCOUNT':generateAccessToken", "credential_source": { "file": ".oidc_token" } }' > gcp-credentials.json
echo "$GCP_WIF_TOKEN" > .oidc_token
gcloud auth login --brief --cred-file=gcp-credentials.json
gcloud auth configure-docker "$GCP_REGION-docker.pkg.dev" -q
script:
# ビルド・プッシュ・デプロイ
- sh build.sh
- docker push "$IMAGE_TAG"
- gcloud run jobs deploy "$CLOUD_RUN_SERVICE_NAME" --image="$IMAGE_TAG" ...
4. まとめ
Terraformを活用することで、Workload Identity Federationのような少し複雑な認証設定もコードで管理でき、セキュアなGitLab CI/CDパイプラインを簡単に構築できました。 一度この構成を作っておけば、環境変数を切り替えるだけで他のプロジェクトにも横展開できるのがIaCの強みです。