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

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

Avatar for ryo ryo
October 10, 2019
3k

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

もくテク #3

Avatar for ryo

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 で 変更前のデータを取得して判定