Firestoreセキュリティルールを読み解く

# 0. 始めに
↓のメールが届いて、何かしないとな～って思ったら、何から始めるかをまとめた記事です[^3]。
自分の備忘録兼学習の証跡みたいな感じになるので、N番煎じ感は否めないですが、それについてはご了承願います。

![firestore_intro0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314204/784a655d-fc90-7ff3-dc69-bcdb04004153.jpeg)


# 1. Firestoreセキュリティルールって何？
　そもそも論ですね、一言で言えば、セキュリティのルールだってことは分かります(合ってるけどそうじゃない)。
[公式ドキュメント](https://firebase.google.com/docs/firestore/security/get-started?hl=ja#use_the_firebase_console)によれば、Firestoreセキュリティルールを使えば、

> インフラストラクチャを管理したり、サーバー側の認証コードや承認コードを作成したりする必要がなくなるため、デベロッパーは優れたユーザー エクスペリエンスを構築することだけに集中できます。
> セキュリティ ルールは、シンプルでありながら高度な処理にも対応できる形式で、アクセス制御とデータ検証を提供します。

との事。ルールさえこちらで設定してあげれば、それに沿ってFirestore側がイイ感じにしてくれそう！

# 2. どこにどうやって設定するの？
　例によって公式ドキュメントを覗いてみますと、「Firebase コンソール」と「Firebase CLI 」の2通りのやり方があるらしい。要するに、ブラウザから直接ルールを編集するか、自前のPCで設定してルールをデプロイするかって事ですね！

#### ①Firebase コンソール
プロジェクトを開いたら、Database > ルール で編集できます
![firestore_intro.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314204/e9c9bcce-b337-6bc1-a667-0b66589fc64c.jpeg)

#### ②Firebase CLI
`firebase init`でFireBaseプロジェクトのディレクトリを作成した時に、↓でFirestoreを選ぶとfirestore.rulesってファイルが出来るのでそれを編集。

```shell
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection)
>( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 ( ) Functions: Configure and deploy Cloud Functions
 ( ) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules
```

もし選択してなかった場合は、

```shell
> firebase init firestore
```
で再設定すれば、ファイルができるはず。そうして編集したルールのみをデプロイする場合は

```shell
> firebase deploy --only firestore:rules
```
でOK！　まだプロジェクトを作ってない場合は手前味噌ですが、[こちら](https://qiita.com/hiroki-harada/items/ca22ac177db68e3c3796)を参考に。



# 3. デフォルトのルールを(ちらっと)確認する
今回は簡単そうな①でやってみます[^20]、まずは、初期状態のルール確認から。
Firebaseプロジェクトを作成した直後はきっと下記のようなルールが設定されているはず！

```shell
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone on the internet to view, edit, and delete
    // all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // your app will lose access to your Firestore database
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2020, 8, 27);
    }
  }
}
```
。。。なるほど分からん :innocent:
大部分はコメントで、読み込みと書き込みが特定の日付まで許可されていそうってことは伝わるけど、他の部分がまるでさっぱり。。。

# 4. セキュリティルールを解読する
　そうは言っても、読み解かない事には先に進めないので、上から順に解読していきます。
以降の節は、

#### 4.1 バージョンとサービスの宣言
まずは最初の2行

```shell
rules_version = '2';
service cloud.firestore {
```
1行目はルール言語のバージョンを表しているらしいです。最新バージョンは`2`との事。
現状の理解として、おまじない的なものとしてつけておけば良さそう。

2行目は`firestore`に対してセキュリティルールを設定している事を示している。ちなみに`firebase storage`の場合は`firebase.storage`となるみたい。
　
#### 4.2 データベースの宣言
　お次は、ルールをどのデータベースに適用するかを指定する行。2020/09/01現在、1つのプロジェクトにつきデータベースは1つで、`(default)`って名前が付いているらしいですよ[^40]。
つまり、↓はプロジェクト内の全てのデータベースを対象対にしたルールってことになりますね！ここも初期設定から変更しなくて良さげ！！

```shell
match /databases/{database}/documents {
  ...
{

// ↓でも、↑と同じ意味？
match /databases/default/documents {
  ...
{
```

#### 4.3 基本的な読み書きのルール
最後に`match`ステートメントと呼ばれる箇所。

```shell
match /{document=**} {
  allow read, write: if request.time < timestamp.date(2020, 8, 27);
}
```
`/{document=**}`は任意のコレクションに対して適用するって意味。[^45]。まぁ要するに、プロジェクト内の全てのコレクションに対してルールが適用されるって事になりますね！

　で、その肝心のルールですが 、
`allow hogehoge`で`hogehoge` 出来ますよーってことなので、↑は読み書き(`read, write`)を許可してますよーってことですね！その条件(`if`より右)が、コレクションに対してアクセスした日付が`2020/08/27`より過去であることってなります。

### 4.4 ルールまとめ
。。。以上、分解して読み解いていきました。
全部繋げると、
　**・プロジェクトの`default`データベースにある**
　**・全てのコレクションは**
　**・`2020/08/27`より過去なら読み書き可能**

って意味ですね！いや～スッキリした！！

# 5. 今後の展望
次は自分でルールを設定してみまーす！

あ、そうそう。。。
デフォルトで設定されたルールですが、単にアクセス期間を伸ばしたいだけなら、

```shell
match /{document=**} {
  allow read, write: if request.time < timestamp.date(2030, 8, 27);
}
```
ってすればOK！。。。なんだけど、例えテストモードで利用していてもその回避策はオススメ出来ないので、やっぱりしっかりとルール設定しないとね！(ブーメラン:crescent_moon:)

# 参考
1. [[公式ドキュメント]Cloud Firestore セキュリティ ルールを使ってみる](https://firebase.google.com/docs/firestore/security/get-started?hl=ja)

2. [[公式ドキュメント]Cloud Firestore セキュリティ ルールを構造化する](https://firebase.google.com/docs/firestore/security/rules-structure?hl=ja)

[注釈]: 　
[^3]: 0日後で通知来ても流石に手遅れですが。。。(笑)
[^20]: 本来的には、CLIでルールを設定して、.rulesファイルをgit管理するのが良さそうではあります:thinking:
[^40]: 参考2から、そう解釈しました。ということは、今後複数のDBを扱えるようになるかもしれないって事？？
[^45]: ディレクトリ風な表記で考えたら、`/*`って感じのルート配下を指す事になるのだろうか？