Firestore 公式ドキュメントを紐解く #1
Firestore セキュリティールール を公式ドキュメントで学ぶ
Cloud Firestore セキュリティ ルールを使用すると、データベース内のドキュメントおよびコレクションへのアクセスを制御できます。
ルールの構文の柔軟性により、データベース全体へのすべての書き込みから特定のドキュメントに対するオペレーションまで、どのようなものにも一致するルールを作成できます。
開発モードの Default セキュリティールール
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.time < timestamp.date(2021, 6, 26);
}
}
}
ということで、 Dafault のセキュリティールールを適宜変更し、表題を実現できるようドキュメントを紐解いていく
Cloud Firestore セキュリティ ルールを構造化する
サービスとデータベースの宣言
Cloud Firestore セキュリティ ルールは、常に、次の宣言で始まります。
↓ できること
ルールのスコープを Cloud Firestore にできる
(Cloud Firestore セキュリティ ルールと Cloud Storage などの他のプロダクトのルールとの間の競合を防ぐ)
service cloud.firestore {
match /databases/{database}/documents {
// ...
}
}
基本的な読み書きのルール
-
match ドキュメント パスを指定
- 例1
match /cities/SF
特定のドキュメントを指す - 例2
match /cities/{city}
ワイルドカードですべてのドキュメントを指す
- 例1
-
allow データ読み書き許可の詳細を指定
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
allow read: if <condition>;
allow write: if <condition>;
}
}
}
詳細なオペレーション
-
read
ルールはget
とlist
に分割可 -
write
ルールはcreate
update
delete
に分割可
セキュリティールールを分けて安全なコードが書ける
service cloud.firestore {
match /databases/{database}/documents {
// read は get と list に分割できます。
match /cities/{city} {
// 1つのドキュメント読み取りリクエストに適用されます。
allow get: if <condition>;
// クエリやコレクションの読み込みリクエストに適用されます。
allow list: if <condition>;
}
// write は、create, update, delet に分割できます。
match /cities/{city} {
// 新規作成ドキュメントに適用されます。
allow create: if <condition>;
// 既存のドキュメントへの上書きに適用されます。
allow update: if <condition>;
// 削除操作に適用されます。
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>;
// 'landmarks'サブコレクションのルールを明示的に定義する
match /landmarks/{landmark} {
allow read, write: if <condition>;
}
}
}
}
↓ 下記ふたつのコードは同じ意味
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=** }
を使用します。ワイルドカード変数には一致するパスセグメント全体が含められます。
たとえば、下に示したルールは、/cities/SF/landmarks/coit_tower
に置かれたドキュメントと一致し、document 変数の値はSF/landmarks/coit_tower
になります。
service cloud.firestore {
match /databases/{database}/documents {
// cities コレクション内のすべてのドキュメント、およびサブコレクション内のすべてのドキュメントを含む。
match /cities/{document=**} {
allow read, write: if <condition>;
}
}
}
ただし、再帰ワイルドカードの動作は、セキュリティールールのバージョンによって異なります。
バージョン2 について
セキュリティールール(現行でのデフォルトセキュリティールールバージョン)
セキュリティ ルールの先頭に
rules_version = '2';
追記する必要があります。バージョン 2 では、ワイルドカードを
match
ステートメント内の任意の場所に配置できます。次に例を示します。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// songs コレクショングループ内の任意のドキュメントを指定できる。
match /{path=**}/songs/{song} {
allow read, write: if <condition>;
}
}
}
match ステートメントの重複
複数の allow 式がリクエストと一致する場合、いずれかの条件が true と評価されると、アクセスが許可されます。
下の例では、
cities
コレクションに対するすべての読み取りと書き込みが許可されます。これは、最初のルールが常に false になっても、2 番目のルールが常に true なるためです。
service cloud.firestore {
match /databases/{database}/documents {
// cities コレクション内のドキュメントを指定
match /cities/{city} {
allow read, write: if false;
}
// cities コレクションに含まれるサブコレクション内のドキュメントも指定
match /cities/{document=**} {
allow read, write: if true;
}
}
}
セキュリティ ルールの上限
下記に関して、初心者(私)が上限に達することはなさそう
関数の再帰的な呼び出し、または循環的な呼び出しが許可されていない、ということは頭の片隅に置いておく
リクエストあたりの
exists()
get()
getAfter()
呼び出しの最大数
- 単一ドキュメントに対するリクエストとクエリ リクエストの場合は 10。
- 複数のドキュメントに対する読み取り、トランザクション、一括書き込みの場合は 20。
- 各オペレーションには、前述の上限(10)も適用されます。
- いずれかの上限を超えると、アクセス拒否のエラーが発生します。
- キャッシュされた呼び出しは上限数に計上されません。
ネストされた
match
ステートメントの深さの最大数 10ネストされた一連の
match
ステートメント内で許可されるパスセグメント内の最大パス長 100ネストされた一連の
match
ステートメント内で許可されるパスキャプチャ変数の最大数 20関数呼び出しの深さの最大数 20
関数引数の最大数 7
関数あたりの let 変数バインディングの最大数 10
関数の再帰的な呼び出し、または循環的な呼び出しの最大数 許可されていません
リクエストあたり評価される式の最大数 1,000
ルールセットの最大サイズ 256 KB
セキュリティールールの構造化のチャプターはここまで
Discussion