Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ここまで出来るよ Firestore セキュリティルール

ryo
October 10, 2019
2.8k

ここまで出来るよ Firestore セキュリティルール

もくテク #3

ryo

October 10, 2019
Tweet

More Decks by ryo

Transcript

  1. 通常の Webアプリ Front end Back end DB ORM REST API

    Firestore利用 Front end Fire Store Client SDK
  2. ドキュメントの追 加 ドキュメントの取 得 firestore().collection("users").add({ name: "太郎", sales: 10000 });

    firestore().collection("users") .where("sales", ">", 5000) .orderBy("sales", "desc");
  3. Resional 99.99 % Multi-Resion 99.999 % SLO Designed to scale

    We've designed Cloud Firestore to handle the toughest database workloads from the world's biggest apps. 世界最大のアプリからの最も厳しいデータベース ワークロードを処理するように設計.
  4. Sparkプラン (無料) Flameプラン ($25/月) Blazeプラン (従量課金) 保存データ 合計 1GiB 合計

    2.5GiB $0.18 / GiB 帯域幅 10GiB / 月 20GiB / 月 Google Cloud pricing ドキュメントの 書き込み 2万 / 日 10万 / 日 $0.18 / 10万 ドキュメントの 読み取り 5万 / 日 25万 / 日 $0.06 / 10万 ドキュメントの 削除 2万 / 日 10万 / 日 $0.02 / 10万 2019/10/8 時点
  5. service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow

    read: if true; allow write: if false; } } } ex) usersコレクションを読み取り専用にするルール 対象のコレクション 条件 許可する操作
  6. function isAuthUser(auth, userId) { return auth != null && auth.uid

    == userId } match /databases/{database}/documents { match /users/{userId} { allow read: if isAuthUser(request.auth, userId); } } request.auth で認証情報を取得
  7. function isValidSchema(data) { return data.size() == 2 && 'name' in

    data && data.name is string && 'sales' in data && data.sales is number } match /databases/{database}/documents { match /users/{userId} { allow create: if isValidSchema(request.resources.data); } } request.resources.data で送信データを取得
  8. function isValidData(data) { return 'name' in data && 1 <=

    data.name.size() && data.name.size() <= 30 && 'gender' in data && data.gender.matches('male|female|genderDiverse') } match /databases/{database}/documents { match /users/{userId} { allow create: if isValidData(request.resources.data); } } 関数 で送信データを判定
  9. function isValidData(data) { return get(/databases/$(database)/documents/users/$(data.userRef)) .data.age >= 18 } match

    /databases/{database}/documents { match /messages/{message} { allow create: if isValidData(request.resources.data); } } get() で別ドキュメントのデータを参照
  10. function isAdminUser(auth) { return auth.token.admin == true; } match /databases/{database}/documents

    { match /users/{userId} { allow create: if isAdminUser(request.auth); } } custom claimsでadminを判定
  11. function isValidUpdate(oldData, newData) { return oldData.status.matches('order') && newData.status.matches('shipment') } match

    /databases/{database}/documents { match /users/{userId} { allow update: if isValidUpdate(resource.data, request.resources.data); } } resource.data で 変更前のデータを取得して判定