この記事はFirebase#2 Advent Calendar 2018の24日目の記事です。

この1年の間にFirestoreのセキュリティールールに関してどのような変化や関心事があったのか、振り返ってみようと思います。

はじめに

  • 12月時点くらいまでで振り返っている内容になります。
  • なるべく時系列に書くつもりですが一部前後している可能性があります。
  • Firestoreの概要やルールの書き方については割愛させていただきます。
  • ※個人の見解が含まれている箇所もあります。

ルールの必要性

サービスを設計・運用していく上でセキュリティー対策を行うことがとても重要になってきます。
ただ、Firestoreのセキュリティー対策(ルールの記述)はFirestoreが登場した当初から暫くの間はそこまで参考になるものが少なく、また検証やテストがしづらいものであったため、

allow read, write: if request.auth != null;

程度しか書けていない、或いは開発モードとして if true でやりくりしていた人も居たんじゃないでしょうか。 そんな中、次の記事が(当時)話題になりました。(Firestoreに限らず、ということで記事中では「Firebase Database」として記載されています

「脆弱性」とするかは人によって解釈の仕方が異なると思いますが、
個人的には脆弱性というよりも、適切にルールを記述しないと簡単に情報が漏洩しうる状態になってしまうので、 ちゃんとルールは記述しようね 、というお気持ちです。

他にも読み解く上でこちらの記事も参考になると思います。

2018年で何が変わったか

実際にこの1年で何が変わったのか、いくつか挙げてみます。

protobufからFirestoreのセキュリティールールを生成できるようになった

https://github.com/FirebaseExtended/protobuf-rules-gen というツールが登場しました。
protobufで書いたモデルの定義からルールを生成してくれる、というものです。
僕自身これを使って書いたことがないので詳しいことは割愛します…。

リファレンスが充実した

2月~4月くらい(うろ覚えですみません…)の間に、Firestoreのセキュリティールールに関するリファレンスが充実しました。

それまではルールの記述で用いることができる関数や型の定義、プロパティ等が明確でなかったので、「Cloud Firestore セキュリティ ルールを使ってみる」あたりからサンプルを読み解いて「これはありそうだから使ってみるか…」という感じでした。
ちなみにリファレンスが充実したあたりで、Firestoreのルールのドキュメントページにも改変が加わり、「Cloud Firestore セキュリティ ルールをカスタマイズする」というページがドキュメントの一覧から外れました。(※内容は古い場合があります)

resource型の変数からidを引っ張れるようになった(?)

リファレンスが充実して、それぞれの型にどんなプロパティや関数があるのか明確になったくらいから、resource.idでドキュメントのIDが引っ張れるようになった…気がします。
というのも、この前くらいから自分もruleを探り探り書いていて、resource.idでドキュメントのIDを取得して検証に使おうとしたもののうまく動作せず、それが「resource.id が存在しなかった」のか、「単にルールが間違っていた」のか判断付かなかった、、という経緯もあります。

もしかしたら初期から正常に取得出来ていたかもですが、リファレンスが充実する前は何が備わっているのか分かりづらかったので今となっては…です。
※(この辺り知っている人が居たらTwitterとかでコッソリ教えてください)

getAfter 関数が追加された

ドキュメントが存在しているかを確認するexists関数、ドキュメントを取得するget関数が最初から備わっていたのですが、
同時書き込みやトランザクションでの更新処理時のルールを記述しようとすると、この2つの関数ではうまくチェックすることができませんでした。
いずれの関数も、現在のDBの状態に対しての実行だったので、同時書き込みの場合だと、ルールでアクセス権を検証している際はまだDBにない状態なので取得や存在確認に失敗します。

5月頃にgetAfter関数が搭載され、その問題を解決できるようになりました。

公式ドキュメントはこちらにあります。

また、実際に使ってみたときの記事を書いているので合わせてお読みください。

テストのシミュレーターが登場

2018年5月末頃に、Firebaseのwebコンソール上で、ルールを編集し、公開する前に実際にルールが正しく動作するか検証できるシミュレーターが搭載されました。

ただ、いくつか制限事項が(未だに)あります。 また、出たばっかりの頃は、Realtime Databaseのものをスッと持ってきたのか、「読み取り」「書き込み」「削除」というオペレーションになっていて動作が不安定でした。
詳しくは次の記事にまとめているのでよかったら読んでみてください。

ルールをデプロイしてから反映されるまでの時間が短縮

以前まではルールをデプロイしてから反映されるまで最長で10分ほどかかることがあったのですが、8月頃から最長1分に改善されたようです。

Twitterでのやりとり

Firestoreのローカルエミュレータが登場

Firebase Summit2018で発表がありましたが、Firestoreのローカルエミュレータが登場しました
(※現段階ではまだβです)

これは Cloud Firestore 用ローカル エミュレータのベータ版です。このプロダクトは、下位互換性のない方法で変更される可能性があり、SLA または非推奨ポリシーの対象ではありません。

今まではwebコンソール上でしか公開前にルールを検証(シミュレート)することが出来ませんでしたが、ローカル上でエミュレータを立ち上げた上で、ルールのテストができるようになりました。
これによって

  • 実際のFirebaseのプロジェクトのDBを汚すことがない
  • ルールをデプロイせずに検証できる
  • 環境に依存しないでテストが可能
  • ルールをデプロイして実際のプロジェクトに読み書きするよりも 高速

といった恩恵が得られます。個人的にはこの機能の登場が一番大きかったと思っています。

公式ドキュメントはこちらにあります。

また、実際にローカルエミュレータを使った記事がいくつかあるので紹介します。

まとめ

2017年はBetaとしてFirestoreが公開された直後は、DBの設計方法について注目が集まる中、セキュリティールールに関してはそこまで議論が出ることが少なかったのですが、脆弱性というワードと共に記事が公開されてからはセキュリティールールの重要性について注目が集まった1年になったなと(個人的には)思います。

また、ルールを生成するツールや、Firebaseのwebコンソール上で公開前に試せるシミュレーターが登場したり、Firebase Summit2018後にはローカルエミュレータが登場するなど、セキュリティールールの構築を支えるものが多くでてきました。
以前は検証も難しいし、複雑になると適切にDBを保護できず情報漏えいするくらいならFunctionsに逃がすか、、みたいな流れも若干ありましたが、今は検証しやすい環境も整ってきているのでルールを書いて公開してSDK経由で読み書きするデメリット(といって良いのか…?)が薄れた気がします。 また、Firestoreの開発が進むと共に、リファレンスやサンプル、非公式のtips的な記事が充実してきて、今年の最初の頃と比べれば親切というか調べればだいたいのことは実現できるかできないか判断できるようになってきたと思います。

来年にはどう変わっているのか、FirestoreがGA版になるのか..楽しみですね。
引き続きFirestore、特にセキュリティールール面に関してはウォッチし続けて追究していこうと思います。



よかったらTwitter等フォローお願いします🙏 @_sgr_ksmt

良いクリスマス🎄と年末🎍をお過ごしください。