🔥

【Google Cloud】 App Engine x Firestore にて PermissionDenied desc 発生時の対処法

に公開

個人開発をしている最中に、けっこう詰まってしまったので、備忘録を兼ねてココに書き留めておきます。

問題

Google Cloud にて。
App Engine 上のプログラム(Go 言語)から、Firestore にアクセスする際に {"error":"rpc error: code = PermissionDenied desc = Missing or insufficient permissions."} のエラーが発生してしまう。

該当のソースコード(抜粋)

詳細はだいぶ省略してますが、おおよそ次のようなソースコードでした。

package main

import (
    "context"

    // https://pkg.go.dev/cloud.google.com/go/firestore を利用しています。
    // バージョンは v1.18.0 です。
    "cloud.google.com/go/firestore"
)

func CreateClient(ctx context.Context) (*firestore.Client, error) {
    client, err := firestore.NewClientWithDatabase(ctx, "GOOGLE_CLOUD_PROJECT_ID", "FIRESTORE_DATABASE_NAME")
    if err != nil {
        return nil, err
    }

    return client, nil
}

func GetData() {
    ctx := context.Background()
    client, err := CreateClient(ctx)
    if err != nil {
        fmt.Println(err.Error())
        panic(err.Error())
    }
    defer client.Close()

    doc := client.Doc("コレクション名/ドキュメントID")
    docsnap, err := doc.Get(ctx)
    if err != nil {
        // ココで {"error":"rpc error: code = PermissionDenied desc = Missing or insufficient permissions."} が発生する。
        fmt.Println(err.Error())
        panic(err.Error())
    }

    data := docsnap.Data()
    fmt.Println(data)
}

解消方法

App Engine サービスアカウントの IAM を更新する

試しに App Engine サービスアカウントに「Cloud Datastore ユーザー」を付与してみました。
結果的に、この対応のみで問題を解消できました。

Cloud Datastore ユーザー

Firestore のロールではなく、Cloud Datastore のロールを指定すること

Firestore にアクセスできないことが問題なので、はじめは App Engine サービスアカウントに Firestore 関連のロールを割り当てたりしましたが、問題は解消せずでした。

Firestore のルールは関係ない

IAM 更新の他に思い当たったこととして、Firestore のルールがありました。
そこで次のように、ルールを read を許可(引き続き write は不許可)に更新してみました。
…が、問題は解消できずでした。

本問題と Firestore のルールは関係ありませんでした。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      // allow read, write: if false; ← 削除する。もしくは、コメントアウトする。
      allow read: if true; // ← 追記する。
      allow write: if false; // ← 追記する。
    }
  }
}

Firestore はネイティブモードであっても、Cloud Datastore のロールが必要になる???

(ここら辺の理解がまだ浅いです。。)

Firestore には、Native モードと Datastore モードがあり、データベース作成時にいずれかを選べます。

Firestore Native モードと Datastore モード

私は、上記のキャプチャ通りに「Firestore ネイティブ」を選択していました。
…が、本問題の解消の肝は、先述の「サービスアカウントに、Firestore のロールではなく、Cloud Datastore のロールを指定すること」でした。

まとめ

なかなか本問題に関する情報が見つからず、解決にかなりの時間を要してしまいました。
しかも、最後は勘頼みとなりました。。

対処療法だけをまとめた技術記事とは呼べない些末な記事ですが、誰かのお役に立てれば、幸いです〜。

Discussion