Cloud Firestore セキュリティ ルールを構造化する

Cloud Firestore セキュリティ ルールを使用すると、データベース内のドキュメントおよびコレクションへのアクセスを制御できます。ルールの構文の柔軟性により、データベース全体へのすべての書き込みから特定のドキュメントに対するオペレーションまで、どのようなものにも一致するルールを作成できます。

このガイドでは、セキュリティ ルールの基本的な構文と構造について説明します。この構文をセキュリティ ルールの条件と組み合わせて、完全なルールセットを作成します。

サービスとデータベースの宣言

Cloud Firestore セキュリティ ルールは、常に、次の宣言で始まります。

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

service cloud.firestore という宣言では、ルールのスコープを Cloud Firestore とし、Cloud Firestore セキュリティ ルールと Cloud Storage などの他のプロダクトのルールとの間の競合を防ぎます。

match /databases/{database}/documents 宣言は、ルールがプロジェクト内の Cloud Firestore データベースと一致するように指定します。現在、各プロジェクトには (default) という名前のデータベースが 1 つだけあります。

基本的な読み書きのルール

基本的なルールは、ドキュメント パスを指定する match ステートメントと、指定されたデータの読み取りを許可するときに詳細を指定する allow 式で構成されます。

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

すべての match ステートメントは、コレクションではなくドキュメントを指す必要があります。match ステートメントでは match /cities/SF のように特定のドキュメントを指すことや、match /cities/{city} のようにワイルドカードを使用して、指定されたパスのすべてのドキュメントを指すことができます。

上の例では、match ステートメントで {city} ワイルドカード構文を使用しています。つまり、このルールは、cities コレクションの、/cities/SF/cities/NYC などのすべてのドキュメントに適用されます。match ステートメントの allow 式が評価されると、city 変数は SFNYC などの city のドキュメント名に解決されます。

詳細なオペレーション

状況によっては、readwrite をより詳細なオペレーションに分割すると便利です。たとえば、アプリで、ドキュメントの作成に対して、削除の場合とは異なる条件を適用する必要がある場合があります。または、単一のドキュメントの読み取りを許可し、大規模なクエリを拒否することが必要になる場合があります。

read ルールは getlist に分割でき、write ルールは createupdatedelete に分割できます。

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

階層データ

Cloud Firestore のデータはドキュメントのコレクションに編成され、各ドキュメントはサブコレクションによって階層を拡張できます。セキュリティ ルールと階層データのインタラクションの仕組みを理解することが重要です。

cities コレクションの各ドキュメントに landmarks サブコレクションが含まれている状況を考えてみましょう。セキュリティ ルールは一致したパスにのみ適用されるため、cities コレクションで定義されたアクセス制御は landmarks サブコレクションには適用されません。代わりに、サブコレクションへのアクセスを制御する明示的なルールを記述します。

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

match ステートメントをネストする場合、内部の match ステートメントのパスは、常に、外側の match ステートメントのパスに対する相対パスになります。したがって、次のルールセットは同等です。

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

再帰ワイルドカード

ルールが任意の深い階層に適用されるようにするには、再帰ワイルドカード構文、{name=**} を使用します。例:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

再帰ワイルドカード構文を使用する場合、ネストが深いサブコレクションにドキュメントが置かれている場合も、ワイルドカード変数には一致するパスセグメント全体が含められます。たとえば、上に示したルールは、/cities/SF/landmarks/coit_tower に置かれたドキュメントと一致し、document 変数の値は SF/landmarks/coit_tower になります。

ただし、再帰ワイルドカードの動作は、ルールのバージョンによって異なります。

バージョン 1

セキュリティ ルールは、デフォルトでバージョン 1 を使用します。バージョン 1 では、再帰ワイルドカードは、1 つ以上のパスアイテムと一致します。再帰ワイルドカードは空のパスには一致しません。したがって、match /cities/{city}/{document=**} はサブコレクションのドキュメントと一致しますが、cities コレクションのものには一致しません。一方、match /cities/{document=**}cities コレクションとサブコレクションのドキュメントの両方に一致します。

再帰ワイルドカードは、match ステートメントの最後に指定する必要があります。

バージョン 2

バージョン 2 のセキュリティ ルールでは、再帰ワイルドカードは 0 個以上のパスアイテムに一致します。match/cities/{city}/{document=**} は、任意のサブコレクション内のドキュメントと cities コレクション内のドキュメントに一致します。

セキュリティ ルールの先頭に rules_version = '2'; を追加して、バージョン 2 にオプトインする必要があります。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

match ステートメントごとに使用できる再帰ワイルドカードは 1 つだけですが、バージョン 2 では、このワイルドカードを match ステートメント内の任意の場所に配置できます。次に例を示します。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

コレクション グループ クエリを使用する場合は、バージョン 2 を使用する必要があります。コレクション グループ クエリの保護をご覧ください。

match ステートメントの重複

1 つのドキュメントが複数の match ステートメントと一致する可能性があります。複数の allow 式がリクエストと一致する場合、いずれかの条件が true と評価されると、アクセスが許可されます。

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

上の例では、cities コレクションに対するすべての読み取りと書き込みが許可されます。これは、最初のルールが常に false になっても、2 番目のルールが常に true になるためです。

セキュリティ ルールの上限

セキュリティ ルールに関する操作では、次の制限に注意してください。

制限 詳細
リクエストあたりの exists()get()getAfter() 呼び出しの最大数
  • 単一ドキュメントに対するリクエストとクエリ リクエストの場合は 10。
  • 複数のドキュメントに対する読み取り、トランザクション、一括書き込みの場合は 20。各オペレーションには、前述の上限(10)も適用されます。

    たとえば、3 つの書き込みオペレーションを含めた一括書き込みリクエストを作成するとします。セキュリティ ルールでは、ドキュメントに対する 2 件のアクセス呼び出しを使用して、それぞれの書き込みを検証します。この場合、各書き込みオペレーションがアクセス呼び出し制限数 10 のうちの 2 つを使用するため、バッチ書き込みリクエストはアクセス呼び出し制限数 20 のうちの 6 つを使用することになります。

いずれかの上限を超えると、アクセス拒否のエラーが発生します。

一部のドキュメントに対するアクセス呼び出しはキャッシュされる場合があります。キャッシュされた呼び出しは上限数に計上されません。

ネストされた match ステートメントの深さの最大数 10
ネストされた一連の match ステートメント内で許可されるパスセグメント内の最大パス長 100
ネストされた一連の match ステートメント内で許可されるパスキャプチャ変数の最大数 20
関数呼び出しの深さの最大数 20
関数引数の最大数 7
関数あたりの let 変数バインディングの最大数 10
関数の再帰的な呼び出し、または循環的な呼び出しの最大数 0(許可されていません)
リクエストあたり評価される式の最大数 1,000
ルールセットの最大サイズ ルールセットは、次の 2 つのサイズ上限に従う必要があります。
  • Firebase コンソールまたは CLI から firebase deploy を使用して公開されるルールセット テキストソースのサイズは 256 KB に制限されています。
  • Firebase がソースを処理してバックエンドでアクティブにするときに生成される、コンパイル済みルールセットのサイズは 250 KB に制限されています。

次のステップ