2021-04-13 追記
後日 GCS のバケットを新しく作成しようとしたらできませんでした。(削除はできた気がしたんですが、幻覚を見ていたのかも...)
また pulumi refresh
を実行しようとすると、サービスアカウントの借用をしないと Firebase 関係のリソースが見れず、借用をするとそれ以外のリソースが見れないという事態に陥りました。
そのため auth/impersonate_service_account
を unset して GOOGLE_OAUTH_ACCESS_TOKEN
環境変数を消し、 pulumi state delete
で Firebase のリソースを Pulumi の管理から外しました。
現時点では「Firebase を IaC ツールで管理しない方が良い」と思っています。
概要
IaC ツールである Pulumi を使って Firebase のアプリを作ろうとしたら googleapi から 403 エラーが返ってきたので、それを解消する方法を調査しました。
インフラ初心者が場当たり的に調べた結果なので、もし内容がおかしかったらコメントで教えてください。
前提
- pulumi CLI のバージョンは 2.24.1
- 使用言語は TypeScript
- @pulumi/gcp のバージョンは 4.0.0
- @pulumi/pulumi のバージョンは 2.0.0
- gcloud へのアクセスには僕個人の Google アカウントを使用
- GCP プロジェクトへのオーナー権限を所有
- Firebase プロジェクトはコンソールから作成済み
- GCP プロジェクトに紐付けてある
発端
Pulumi で以下のようなコードを実行しようとしたところ、
import * as gcp from "@pulumi/gcp";
new gcp.firebase.WebApp("my-firebase-webapp", {
displayName: "my-app",
});
以下のエラーが発生しました。
gcp:firebase:WebApp (my-firebase-webapp):
error: 1 error occurred:
* Error creating WebApp: googleapi: Error 403: Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the firebase.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.
Details:
[
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"domain": "googleapis.com",
"metadata": {
"consumer": "projects/999999999999",
"service": "firebase.googleapis.com"
},
"reason": "SERVICE_DISABLED"
}
]
どうやら the auth/impersonate_service_account setting
、即ちサービスアカウントの権限を借用しないといけないようです。
( the billing/quota_project setting
の方は良くわかりませんでした。)
解決方法
1. firebase-adminsdk サービスアカウントの権限を借用する
Firebase のドキュメントには、
Firebase では、ユーザー認証情報を共有せずに、サービス アカウントを使用してサービスの操作と管理を行えます。Firebase プロジェクトを作成すると、プロジェクトで複数のサービス アカウントが用意されます。
とあります。
また Firebase のコンソールの「プロジェクトの設定」 > 「サービス アカウント」には、
Firebase サービス アカウントを使用し、Database、Storage、Auth などの複数の Firebase 機能を、統合 Admin SDK を介してプログラムにより認証できます。
Firebase サービス アカウント
firebase-adminsdk-xxxxx@my-gcp-project.iam.gserviceaccount.com
とあります。
GCP のサービスアカウント一覧を見てみると、確かに firebase-adminsdk なるサービスアカウントが作られているようです。
というわけでこのサービスアカウントの権限を借用します。
借用の方法は以下の通り。
「gsutil -i」、「gsutil config」を実行して boto 構成ファイルを編集するか、「gcloud config set auth/impersonate_service_account」を実行して、なりすましに使用するサービス アカウントを指定できます。
なりすましを行うには、元の認証情報で、ターゲット サービス アカウントに roles/iam.serviceAccountTokenCreator を付与する必要があります。 詳細については、次をご覧ください。
まず auth/impersonate_service_account
をセットします。
$ gcloud config set auth/impersonate_service_account firebase-adminsdk-xxxxx@my-gcp-project.iam.gserviceaccount.com
次に借用する側のアカウント(今回は僕の個人 Google アカウント)に roles/iam.serviceAccountTokenCreator
(サービス アカウント トークン作成者)を付与します。
自分は GCP のコンソールからやりました。
2. 環境変数を設定する
上記だけだとうまく行かず、色々調べた結果↓の記事にたどり着きました。
As for Terraform, set the GOOGLE_OAUTH_ACCESS_TOKEN variable to pass an OAuth2 token:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
自分は direnv を使っているので、.envrc に以下を追記しました。
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
この状態で pulumi up
を実行したところ、無事 Firebase アプリが作成されました。
ちなみに GCS バケットの削除など Firebase と関係ないリソースの操作もできました。
操作のログは↓のような感じになります。
authenticationInfo: {
principalEmail: "firebase-adminsdk-xxxxx@my-gcp-project.iam.gserviceaccount.com"
serviceAccountDelegationInfo: [
0: {
firstPartyPrincipal: {
principalEmail: "<僕個人の Google アカウントのメールアドレス>"
}
}
]
}
以上です。