はじめに
FCM(FirebaseCloudMessaging)でWebプッシュ通知を送信する環境をTerraformで構築しました。
- 通知受取側:PWA(Nuxt3)
- 通知送信側:AWS Lambda(Python)
Pythonから送信するので、FirebaseAdminSDKも使えるようにします。
バックエンドは私の場合はLambdaですが、他の場合でもFCMの環境作成自体は同じです。
コンソールから構築する記事はたくさんあったのですが、Terraformでの実装例が全然ないのと、普段AWSを主に使っているのでGCPの理解が足りず割と苦労しました。
FirebaseとTerraformの公式ドキュメントを参考にしています。
コンソールから作る場合の参考
実行環境
- macOS Ventura
13.2.1
- Terraform
v1.5.4
- Google Cloud SDK
464.0.0
- bq
2.0.101
- core
2024.02.09
- gcloud-crc32c
1.0.0
- gsutil
5.27
Google Cloud SDK以下はgcloud-cliをインストールしたら一緒に入ってきたツール達です。
gcloud-cliの認証
Terraformからリソースを作成するにあたり、作成対象のGoogleアカウントの認証をgcloud-cliで行う必要があります。
ここで初めて知ったのですが、GCPを扱う上ではユーザの種類がユーザアカウントとサービスアカウントの2種類あるようです。
今回のようにCLIから使う場合は、サービスアカウントで認証する方がTerraform Workspaceでディレクトリごとに違う環境にデプロイする時などに良いんだろうなあと思います。
が、今回はWorkspaceを使ってないのでユーザアカウントで認証します。
作成対象のアカウントが1つしかない場合はgcloud auth login
コマンドで対話形式で設定していくのが良いと思います。
私はaws-cliのプロファイルのように実行時にプロファイルを切り替えたかったので、以下のコマンドで設定しました。
gcloud config configurations create <config名> #configの作成
gcloud config configurations activate <config名> #configの切り替え
gcloud config set core/account <Googleアカウントのアドレス> #対象のアカウントをセット
gcloud config set core/disable_usage_reporting False #とりあえずFalse
gcloud auth login # ブラウザが開くのでログインする
他にも設定値があるのでドキュメントを見てください。
コード
Terraformの公式ドキュメントとにらめっこしながら作成したコードがこちらです。
ドキュメントそのままの部分が多いですが、コンソールから作成したリソースとTerraformのリソース名がどう対応するのかわからなかったんですよね。
local
とvar
でローカル変数を参照しているところは適宜任意の名前に書き換えてください。
main.tf
terraform {
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "5.16.0"
}
}
}
# 新規でプロジェクトを作成するときはuser_project_overrideをfalseにする
provider "google-beta" {
alias = "no_user_project_override"
user_project_override = false
}
どうでもいいですがbetaがついていることに驚きです。
GCPプロジェクトとFirebaseプロジェクトの作成
resource "google_project" "project" {
provider = google-beta.no_user_project_override
name = local.project_name
project_id = local.project_id
skip_delete = true
labels = {
"firebase" = "enabled"
}
}
resource "google_firebase_project" "firebase_project" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
}
AdminSDK操作用のサービスアカウントの作成
PythonからAdminSDKを操作するためのサービスアカウントと、アクセス用のキーペアを作成します。
resource "google_service_account" "fb_admin_sdk" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
account_id = local.fb_admin_sdk_account_id
display_name = local.fb_admin_sdk_account_id
}
resource "google_project_iam_binding" "fb_admin_sdk_service_agent" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
role = "roles/firebase.sdkAdminServiceAgent"
members = [
"serviceAccount:${google_service_account.fb_admin_sdk.email}",
]
}
resource "google_project_iam_binding" "fb_admin_sdk_token_creator" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
role = "roles/iam.serviceAccountTokenCreator"
members = [
"serviceAccount:${google_service_account.fb_admin_sdk.email}",
]
}
resource "google_service_account_key" "firebase_admin_sdk_key" {
provider = google-beta.no_user_project_override
service_account_id = google_service_account.fb_admin_sdk.name
private_key_type = "TYPE_GOOGLE_CREDENTIALS_FILE"
}
locals {
decoded_private_key = jsondecode(base64decode(google_service_account_key.firebase_admin_sdk_key.private_key))
}
google_service_account_key
で作成したキーの内容を別moduleで作成しているLambdaの環境変数として渡したかったので、bese64decode
→jsondecode
でlocalsブロックで読み込んでいます。
参照するときはlocal.decoded_private_key.private_key_id
の形式でjsonのキーごとに参照できます。
コンソールから作成すると下の形式のjsonファイルでダウンロードされる内容です。
{
"type": "service_account",
"project_id": *****",
"private_key_id": "*****",
"private_key": "*****",
"client_email": "*****",
"client_id": "*****",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "*****",
"universe_domain": "googleapis.com"
}
この作成した鍵の内容の読み取り方がわからず苦労しました。
google_project_iam_binding
でサービスアカウントにロールをアタッチしています。
firebaseのプロジェクト作成時に自動でAdminSDK用のサービスアカウントが作成されるのですが、それと同じロールにしています。
WEBプッシュ用アプリの作成
今回はWEBプッシュ通知がしたいので、WEBアプリを作成します。
resource "google_firebase_web_app" "fb_web_app" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
display_name = local.fb_web_app_display_name
}
data "google_firebase_web_app_config" "fb_web_app_config" {
provider = google-beta.no_user_project_override
project = google_project.project.project_id
web_app_id = google_firebase_web_app.fb_web_app.app_id
}
通知受取側のコードでapiKey
等のfirebaseの設定情報が必要になります。
値を参照するときはdata.google_firebase_web_app_config.fb_web_app_config.api_key
のようにdataリソースから参照します。
ウェブプッシュ証明書の作成
これだけTerraformで対応してなかった(見つからなかった)ので、GUIから作成します。
作成された公開鍵は通知受け取り側(PWA)の方で使います。
以上でリソースの作成は終了です。
通知送信側、受取側の詳しいコードははじめに記載した公式ドキュメントに載っているので、そちらを参考にしてください。
最後に
IaC大好きなので、なんでもコード化したくなります。
TerraformでFCM環境を作りたい方の参考になれば幸いです。