安全でないルールを修正する

このガイドでは、Cloud Firestore セキュリティ ルール構成における一般的な脆弱性、独自のルールを確認してセキュリティを強化する方法、デプロイする前に変更内容をテストする手順について説明します。

Cloud Firestore データベースが適切に保護されていないという警告を受け取った場合は、Cloud Firestore セキュリティ ルールを変更してテストすることで脆弱性を解決できます。

既存のセキュリティ ルールを表示するには、Firebase コンソールの [ルール] タブに移動します。

Cloud Firestore セキュリティ ルールについて

Cloud Firestore セキュリティ ルールは、悪意のあるユーザーからデータを保護します。Firebase コンソールで作成された Cloud Firestore インスタンスのデフォルトのルールでは、すべてのユーザーのアクセスが拒否されます。アプリを開発してデータベースにアクセスするには、これらのルールを変更して、開発環境内のすべてのユーザーに包括的なアクセス権を付与することを検討する必要があります。ただし、アプリを本番環境にデプロイする前に、十分な時間をかけてルールを正しく構成し、データを保護してください。

アプリの開発過程において、さまざまな構成でルールをテストする際は、Cloud Firestore エミュレータを使用してローカルの開発環境でアプリを起動します。

安全でないルールに関する一般的なシナリオ

デフォルトで設定した Cloud Firestore セキュリティ ルール、または Cloud Firestore で最初にアプリを開発する際に使用した Cloud Firestore セキュリティ ルールは、アプリをデプロイする前に確認して更新する必要があります。以下に説明する陥りがちな落とし穴を避けて、ユーザーのデータを適切に保護してください。

オープン アクセス

Cloud Firestore を設定する際に、開発中にオープン アクセスを許可するようにルールを設定している場合があります。アプリのユーザーは自分だけだと思いがちですが、アプリをデプロイすると、そのアプリはインターネット上で利用可能な状態になります。ユーザー認証を行っていない場合や、セキュリティ ルールを構成していない場合は、誰でもプロジェクト ID を推測してデータにアクセスし、データを窃取、変更、削除できてしまいます。

非推奨事項: すべてのユーザーに対する読み取りと書き込みのアクセス権。
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}
解決策: 読み取りと書き込みのアクセス権を制限するルール。

データ階層に合ったルールを構築します。この非安全性に対する一般的な解決策の一つは、Firebase Authentication によるユーザーベースのセキュリティです。詳しくは、ルールを使用したユーザーの認証をご覧ください。

コンテンツ所有者のみ

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{document} {
      allow read, write: if request.auth != null && request.auth.uid == request.resource.data.author_uid
    }
  }
}
  

公開アクセスと限定公開アクセスの混合

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      allow read: if true
      allow write: if request.auth != null && request.auth.uid == request.resource.data.author_uid
    }
  }
}
  

認証されたユーザーのアクセス

Cloud Firestore セキュリティ ルールによって、ユーザーがログインしていることが確認されますが、その認証に基づいてアクセスがそれ以上制限されないことがあります。いずれかのルールに auth != null が含まれている場合は、ログインしているすべてのユーザーがそのデータにアクセスできても問題ないことを確認します。

非推奨事項: ログインしているすべてのユーザーが、データベース全体に対して読み取りと書き込みのアクセス権を持っている。
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth != null;
    }
  }
}
解決策: セキュリティ条件を使用してアクセスを制限する。

認証を確認するときは、いずれかの認証プロパティを使用して、特定のユーザーによる特定のデータセットへのアクセスをさらに制限することもできます。詳しくは、セキュリティ ルールの条件を追加する方法ロールベースのアクセス権をご覧ください。

ロールベースのアクセス権

service cloud.firestore {
  match /databases/{database}/documents {
    // Assign roles to all users and refine access based on user roles
    match /some_collection/{document} {
     allow read: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"

     // Note: Checking for roles in your database using `get` (as in the code
     // above) or `exists` carry standard charges for read operations.
    }
  }
}

属性ベースのアクセス権

// Give each user in your database a particular attribute
// and set it to true/false
// Then, use that attribute to grant access to subsets of data
// For example, an "admin" attribute set
// to "true" grants write access to data

service cloud.firestore {
  match /databases/{database}/documents {
    match /collection/{document} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
      allow read: true;
    }
  }
}
  

公開アクセスと限定公開アクセスの混合

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      allow read: if true
      allow write: if request.auth.uid == request.resource.data.author_uid
    }
  }
}
  

クローズド アクセス

アプリの開発中における一般的なアプローチとしては、データを遮断するという方法もあります。通常、これは以下のように、すべてのユーザーに対して読み取りと書き取りのアクセス権を拒否することを意味します。

// Deny read/write access to all users under any conditions
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Firebase Admin SDK と Cloud Functions は、引き続きデータベースにアクセスできます。Firebase Admin SDK と組み合わせ、サーバーのみのバックエンドとして Cloud Firestore を使用する場合は、これらのルールを使用します。これによってセキュリティは確保されますが、アプリのクライアントによって適切にデータが取得されることをテストする必要が生じます。

Cloud Firestore セキュリティ ルールとその仕組みについて詳しくは、Cloud Firestore セキュリティ ルールを使ってみるをご覧ください。

Cloud Firestore セキュリティ ルールをテストする

アプリの動作確認と Cloud Firestore セキュリティ ルール構成の検証を行うには、Cloud Firestore エミュレータ使用します。変更をデプロイする前に、Cloud Firestore エミュレータを使用して、ローカル環境で単体テストの実施と自動化を行います。

更新した Cloud Firestore セキュリティ ルールを Firebase コンソールですばやくテストするには、ルール プレイグラウンド ツールを使用します。

  1. ルール プレイグラウンドを開くには、[ルール] タブの [ルール プレイグラウンド] をクリックします。
  2. ルール プレイグラウンドの設定で、次のようなテストのオプションを選択します。
    • 読み取りまたは書き込みのテスト
    • データベース内の特定の場所(パスとして)
    • 認証タイプ - 未認証、認証された匿名ユーザー、または特定のユーザー ID
    • ルールで参照するドキュメントの固有のデータ(例: ルールで書き込みを許可する前に、特定のフィールドが存在している必要がある場合)
  3. [実行] をクリックして、ルール ウィンドウの上のバナーで結果を確認します。