• トップ
  • ブログ一覧
  • Firestore セキュリティルール ~入門編~
  • Firestore セキュリティルール ~入門編~

    広告メディア事業部広告メディア事業部
    2020.03.23

    IT技術

    Firestore セキュリティルール

    なにかと便利な「Firestore(ファイアストア)

    ですが、セキュリティルールの設定を怠ると「データが改ざんされる」「削除される」、といった事態に発展する可能性があります。

    本記事では、サンプルを交えつつ、セキュリティルールの基本的な構成や設定の方法について解説していきたいと思います!

    簡単な流れ

    本記事では、以下のような流れで解説を進めていきます!

    1. セキュリティルールの簡単なサンプルとともに、基本的な構成を解説
    2. セキュリティルールの主要な要素である matchステートメントと allow式について解説
    3. セキュリティルールの気になるところを Q & A方式で解説

    セキュリティルールの基本的な構成

    まずは、セキュリティルールの簡単なサンプルとともに、基本的な構成について解説したいと思います。

    セキュリティルールの基本的な構成

    セキュリティルールの基本的な構成は、以下のような形式となります。

    1// セキュリティルールのバージョンを指定
    2rules_version = '2';
    3
    4// 対象サービスを指定
    5service cloud.firestore {
    6  // プロジェクト内のFirestoreデータベースを指定
    7  match /databases/{database}/documents {
    8    // ドキュメントパスを指定
    9    match /users/{user} {
    10      // 読み込みを許可
    11      allow read: if true;
    12      
    13      // 書き込みを拒否
    14      allow write: if false;
    15    }
    16  }
    17}

    rules_version

    セキュリティルールのバージョンを指定する部分です。

    2019年5月以降から、セキュリティルールの「バージョン2」が使用可能になりました。

    コレクション グループ クエリを使う場合は「バージョン2」を指定して、コレクション グループ クエリ用のセキュリティルールを設定する必要があります。

    特にバージョンの指定がない場合は「バージョン1」となります。

    service cloud.firestore

    対象サービスを指定する部分です。

    他プロダクト(Cloud Storageなど)との、ルールの競合を防ぐための設定です。

    match /databases/{database}/documents

    プロジェクト内の、Firestore データベースを指定する部分です。

    現在、各プロジェクトには (default) というデータベースが1つだけあるので、database変数には (default) が代入されます。

    match ステートメント

    ドキュメントのパスを指定する部分です。

    指定先はドキュメントのみで、コレクションを指定する事はできません。

    上記の例の場合、match /users/{user} の部分で、usersコレクションのドキュメントを指定しています。

    {user} の部分は、ワイルドカード表記を使用してます。(※ワイルドカードについては後述いたします)

    allow 式

    読み書きの許可条件を指定する部分です。

    上記の例の場合、allow read: if true; の部分で読み込みを許可。

    allow write: if false; の部分で、書き込みを拒否しています。

    matchステートメント 入門

    複数のサブコレクションのセキュリティルールを記述する際、全てのサブコレクションに対して、ドキュメントパスの全体を記述するのは面倒だと思います。

    matchステートメントはネスト記述が使える!

    そのような場合は、以下のようにネスト記述」を使うと便利です。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    match /users/{user} {
    5        // favoritesサブコレクションを指定
    6        match /favorites/{favorite} {
    7          allow read, write: if true;
    8        }
    9
    10        // propertiesサブコレクションを指定
    11        match /properties/{property} {
    12          allow read, write: if true;
    13        }
    14    }
    15  }
    16}

    ここで、「favoritesサブコレクション」と、「propertiesサブコレクション」に対する「matchステートメント」は、外側の matchステートメント(ここではusersコレクション)のパスからの、相対パスとなります。

    よって、上記のセキュリティルールと、以下のセキュリティルールは同等のものとなります。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    match /users/{user}/favorites/{favorite} {
    5      allow read, write: if true;
    6    }
    7
    8    match /users/{user}/properties/{property} {
    9      allow read, write: if true;
    10    }
    11  }
    12}

    サブコレクションが2つくらいであれば、それほど面倒ではありません。

    ですが、3つ4つとルールが増えてくると、「ネスト記述」を使う方が楽になってきます。

    また、共通部分を「ネスト記述」を使って括りだしておくと、ルール全体の見通しがよくなり、ルールの設定漏れ防止にもつながります。

    matchステートメントはワイルドカードが使える!

    以下のように、matchステートメントではワイルドカードが利用できます

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    // ① 特定のドキュメントを指定
    5    match /vegetables/carrot {
    6      allow read, write: if true;
    7    }
    8
    9    // ② ワイルドカードでfruitsコレクションの任意のドキュメントを指定
    10    match /fruits/{fruit} {
    11      allow read, write: if true;
    12    }
    13  }
    14}

    ① 特定のドキュメントを指定

    ①のルールでは、ワイルドカードを使用せずに、「vegetablesコレクション」の carrotドキュメントのみの読み書きを許可しています。

    「vegetablesコレクション」の、carrotドキュメント以外の読み書きは拒否されます。

    ② ワイルドカードでfruitsコレクションの任意のドキュメントを指定

    ②のルールでは、ワイルドカード {fruit} を使って、「fruitsコレクション」の任意のドキュメントの読み書きを許可しています。

    「fruitsコレクション」の、任意のドキュメントの読み書きが可能です。

    matchステートメントは再帰ワイルドカードが使える!

    深い階層のサブコレクションのルールを記述する場合、各階層のサブコレクション全てについてルールを記述するのは面倒だと思います。

    そのような場合、以下のように「再帰ワイルドカード構文 {document=**} 」を使うと便利です。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    // usersコレクション以下の全てのドキュメントに対するルール
    5    match /users/{document=**} {
    6      allow read, write: if true;
    7    }
    8  }
    9}

    上記のルールは、「usersコレクション」内のドキュメントに加え、「usersコレクション」以下のサブコレクションのドキュメントにも適用されます。

    たとえば、/users/{user}/favorites/users/{user}/favorites/{favorite}/memos などのサブコレクションにも、上記のルールが適用されます。

    document変数は、ルールが適用されたドキュメントに対応する値となります。

    たとえば、ドキュメント /users/yamada/favorites/apple についての判定では、document変数の値は yamada/favorites/apple となります。

    再帰ワイルドカードの補足 ~ バージョン1とバージョン2の違い ~

    「バージョン1」と「バージョン2」で、再帰ワイルドカードの動作が異なります。

    match /users/{user}/{document=**} のような matchステートメントがあった場合

    たとえば、match /users/{user}/{document=**} のような matchステートメントがあった場合、「バージョン2」では usersコレクションと、usersコレクションのサブコレクションに対してルールが適用されます。

    対して「バージョン1」では、usersコレクションにはルールが適用されません。

    「バージョン1」で usersコレクションにルールを適用する場合は、match /users/{document=**} のように matchステートメントを記述する必要があります。

    再帰ワイルドカードを配置

    「バージョン2」では、match /{path=**}/favorites/{favorite} のように任意の場所に再帰ワイルドカードを配置できます。

    一方「バージョン1」では、matchステートメントの最後にだけ配置することができます。

    コレクション グループ クエリを使用する場合は、「バージョン2」を使用する必要があります。

    今から Firestore を使い始める場合は、セキュリティルールは「バージョン2」を使う事をオススメします!

    allow式 入門

    「allow式」は、以下のようなフォーマットで記述します。

    1allow [アクセスタイプ]: if [条件];

    [アクセスタイプ] の部分で、「read」や「write」のようなアクセスタイプを指定します。

    [条件] の部分で、アクセスの許可条件を指定します。

    [条件] 部分で指定した条件が、true の場合は指定のアクセスが許可されます。

    allow式で指定できるアクセスタイプ

    allow式では、read、write ルールに加えて、readルールを分割した「get」「list」や、writeルールを分割した「create」「update」「 delete」を指定することができます。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    match /vegetables/{vegetable} {
    5      // ドキュメントの取得を許可
    6      allow read: if true;
    7
    8      // ドキュメントの追加・更新・削除を許可
    9      allow write: if true;
    10    }
    11
    12    // readルールはget, listルールに分ける事ができます
    13    match /fruits/{fruit} {
    14      // 単一ドキュメントの取得を許可
    15      allow get: if true;
    16      
    17      // 複数ドキュメント(クエリやコレクション)の取得を許可
    18      allow list: if true;
    19    }
    20
    21    // writeルールはcreate, update, deleteルールに分ける事ができます
    22    match /fruits/{fruit} {
    23      // 新規ドキュメントの追加を許可
    24      allow create: if true;
    25
    26      // 既存ドキュメントの更新を許可
    27      allow update: if true;
    28
    29      // ドキュメントの削除を許可
    30      allow delete: if true;
    31    }
    32  }
    33}

    セキュリティルールのここが気になる!? ~Q & A コーナー~

    セキュリティルールについて、気になるところを Q&A でまとめてみました!

    セキュリティルールで指定していないアクセスは許可?拒否?

    セキュリティルールで指定されていないアクセスは拒否されます。

    以下のようなルールの場合、usersコレクションの readアクセスのみが許可されます。

    そして、usersコレクションの writeアクセスと users以外のコレクションへのアクセスは拒否されます。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    // usersコレクションの読み込みを許可
    5    match /users/{user} {
    6      allow read: if true;
    7    }
    8  }
    9}

    1つのドキュメントが、複数のmatchステートメントと一致するとどうなる!?

    いずれかの「allow式」の条件が true と評価されると、アクセスが許可されます。

    たとえば、以下のようなルールの場合、usersコレクションの読み書きが許可されます。

    1rules_version = '2';
    2service cloud.firestore {
    3  match /databases/{database}/documents {
    4    // usersコレクションの読み書きを拒否
    5    match /users/{user} {
    6      allow read, write: if false;
    7    }
    8
    9    // usersコレクションとサブコレクションの読み書きを許可
    10    match /users/{users}/{document=**} {
    11      allow read, write: if true;
    12    }
    13  }
    14}

    上記のルールでは、1つ目のルールで usersコレクションの読み書きを拒否しています。

    2つ目のルールで、usersコレクションのサブコレクションと、usersコレクションの読み書きを許可しています。

    usersコレクションに対するルールが競合していますが、この場合は許可設定が優先されて、usersコレクションへの読み書きが許可されます。

    プロジェクトディレクトリのセキュリティルールをデプロイすると、Firebaseコンソールで設定したルールはどうなる?

    デプロイしたプロジェクトディレクトリのセキュリティルールで上書きされます。

    Firebase CLI を使ってルールをデプロイする場合は、ルールの定義・更新をプロジェクトディレクトリのルールに統一することをオススメします!

    もし Firebaseコンソールでルールを編集する場合は、その都度、プロジェクトディレクトリのルールも更新してください。

    まとめ

    以上、セキュリティルールの基本的な構成やmatchステートメント、allow式の記述の仕方についてサンプルルールを交えて解説しました。

    最後に、簡単に今回の内容をまとめてみたいと思います!

    1. セキュリティルールは大事
    2. 基本はmatchとallowだけ
    3. matchステートメントはワイルドカードやネスト記述、再帰ワイルドカードが使える
    4. readアクセスはgetとlistに分割できる
    5. writeアクセスはcreate, update, deleteに分割できる
    6. 今からはじめるならバージョンは2がおすすめ

    今回ご紹介した内容をもとに、セキュリティルールの設定を行っていただければと思います!

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    featureImg2020.08.04エンジニアの働き方 特集社員としての働き方社員としてのエンジニアの働き方とは?ライトコードのエンジニアはどんな働き方をしてるのか、まとめたいと...

    featureImg2020.07.27IT・コンピューターの歴史特集IT・コンピューターの歴史をまとめていきたいと思います!弊社ブログにある記事のみで構成しているため、まだ「未完成状態」...

    広告メディア事業部

    広告メディア事業部

    おすすめ記事