セキュリティ ルールの構造化
Firestore セキュリティ ルールを使用すると、データベース内のドキュメントおよびコレクションへのアクセスを制御できます。ルールの構文の柔軟性により、データベース全体へのすべての書き込みから特定のドキュメントに対するオペレーションまで、どのようなものにも一致するルールを作成できます。
このガイドでは、セキュリティ ルールの基本的な構文と構造について説明します。この構文をセキュリティ ルールの条件と組み合わせて、完全なルールセットを作成します。
サービスとデータベースの宣言
Firestore セキュリティ ルールは、常に、次の宣言で始まります。
service cloud.firestore {
match /databases/{database}/documents {
// ...
}
}
service cloud.firestore
という宣言では、ルールのスコープを Firestore とし、Firestore セキュリティ ルールと Cloud Storage などの他のプロダクトのルールとの間の競合を防ぎます。
match /databases/{database}/documents
宣言は、ルールがプロジェクト内の 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
変数は SF
や NYC
などの city のドキュメント名に解決されます。
詳細なオペレーション
状況によっては、read
と write
をより詳細なオペレーションに分割すると便利です。たとえば、アプリで、ドキュメントの作成に対して、削除の場合とは異なる条件を適用する必要がある場合があります。または、単一のドキュメントの読み取りを許可し、大規模なクエリを拒否することが必要になる場合があります。
read
ルールは get
と list
に分割でき、write
ルールは create
、update
、delete
に分割できます。
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>;
}
}
}
階層データ
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() 呼び出しの最大数 |
いずれかの上限を超えると、アクセス拒否のエラーが発生します。 一部のドキュメントに対するアクセス呼び出しはキャッシュされる場合があります。キャッシュされた呼び出しは上限数に計上されません。 |
ネストされた match ステートメントの深さの最大数 |
10 |
ネストされた一連の match ステートメント内で許可されるパスセグメント内の最大パス長 |
100 |
ネストされた一連の match ステートメント内で許可されるパスキャプチャ変数の最大数 |
20 |
関数呼び出しの深さの最大数 | 20 |
関数引数の最大数 | 7 |
関数あたりの let 変数バインディングの最大数 |
10 |
関数の再帰的な呼び出し、または循環的な呼び出しの最大数 | 0(許可されていません) |
リクエストあたり評価される式の最大数 | 1,000 |
ルールセットの最大サイズ | ルールセットは、次の 2 つのサイズ制限に従う必要があります。
|
次のステップ
- カスタム セキュリティ ルールの条件を記述する。
- セキュリティ ルールのリファレンスを参照する。