Firestoreの監査ログがパワーアップした

[2021.09.30 更新]
コメントにて2021年9月2日に[再リリース](https://cloud.google.com/firestore/docs/release-notes#September_02_2021)が行われた旨ご指摘いただきました（ありがとうございます！）。
また監査ログを取得できるようになりました🙆‍♂️

[2021.07.26 更新]
パワーアップした監査ログですが再度[Futureリリース](https://cloud.google.com/firestore/docs/release-notes#July_22_2021)になり利用できなくなりました🥲

## サマリ
- 2021年7月16日、[Firestore（ネイティブモード）の監査ログ機能が拡充](https://cloud.google.com/firestore/docs/release-notes#July_16_2021)されました[^1]

```md
Added DATA_READ and DATA_WRITE Data Access audit logs.
`````

- 以前の監査ログでは、例えばインデックスの操作やドキュメントのImport/Exportといった管理者寄りの監査ログが取得できていました[^2]
- 今回の機能拡充で、上記に加え**Firestoreへのデータアクセスについてよりリッチな監査ログが残るようになりました**
    - 例：[Firebase Webコンソール](https://firebase.google.com/?hl=ja)からデータを操作したログ、エンドユーザがモバイルアプリから直接ドキュメントを操作したログ etc.
- どんなログが取れるのか、注意すべき点はあるか等について調査を行いました
- **調査しながら帰納的に獲得した結論を多分に含みます（加えてまだPreview版なので今後更改される可能性アリ）**

## 事前知識
- Firestoreには[ネイティブモードとDatastoreモード](https://cloud.google.com/firestore/docs/firestore-or-datastore?hl=ja)があり、今回はネイティブモードが対象です。ざっくり言えばアプリから直接アクセス可能なのがネイティブモードで、世間的にもFirestoreと言えばネイティブモードを指す場合が多いように思います[^3]
- Google Cloudでは取得したいデータアクセス監査ログをサービス毎に有効化する必要があります
    - Google Cloudコンソール > 監査ログ > Firestore/Datastore API > データ読み取り/データ書き込みをON[^4]
    - **以降ではデータアクセス監査ログを有効化した前提で話を進めます**

##取得できるFirestore監査ログについて

下記3つの観点から説明します。

1. 「どこ」でログを確認できるのか
2. 「誰」のログが取れるのか
3. 「どんな」ログが取れるのか

#### 「どこ」でログを確認できるのか

[Cloud Logging](https://cloud.google.com/logging/docs?hl=ja)で確認できます。
Google Cloudコンソール > Cloud Logging > クエリフィールドに下記を入力し実行します[^5]。

```
resource.type="audited_resource" resource.labels.service="firestore.googleapis.com"
```

#### 「誰」のログが取れるのか

Firestoreへのアクセス主体は大きく3つ考えられると思います。

- Googleアカウント（ユーザアカウント）
    - FirebaseのWebコンソールから直接閲覧
- サーバアプリケーション
    - サービスアカウントを付与したサーバがAdmin SDKを使ってバッチジョブを実行
- モバイル/Webアプリ
    - モバイル/WebアプリがSDK越しに直接Firestoreにアクセス

**これら全ての場合について監査ログを取得可能です。**

Cloud Logging上のFirestore監査ログには`protoPayload.authenticationInfo.principalEmail`フィールドがあります。

```example.json
{
  "protoPayload": {
    ...
    "authenticationInfo": {
      "principalEmail": "...",
    ...
    },
    ...
  }
}
```

この`principalEmail`に、

- Googleアカウントの場合
    - コンソールを操作したGoogleアカウントのメールアドレス
    - 例：<font color="HotPink">*google-account-name*</font>@<font color="HotPink">*domain-name*</font>.com
- サーバアプリケーションの場合
    - サーバが使用しているサービスアカウントのメールアドレス
    - 例：<font color="HotPink">*service-account-name*</font>@<font color="HotPink">*project-id*</font>.iam.gserviceaccount.com
- モバイル/Webアプリの場合
    - Firebaseセキュリティルールのサービスアカウントのメールアドレス[^6]
    - 例：service-<font color="HotPink">*project-number*</font>@firebase-rules.iam.gserviceaccount.com

が入ります。
モバイル/Webアプリからの直接アクセスもようやくロギングされるようになってステキですね！

### 「どんな」ログが取れるのか

これは[ドキュメント](https://cloud.google.com/firestore/docs/audit-logging?hl=ja)に詳しく記載されているので直接見た方が早いと思いますが一応転記いたします[^7]。

- データアクセスログ（DATA_READ）
    - GetDocument
    - ListDocuments
    - BatchGetDocuments
    - BeginTransaction
    - 書き込みのないCommit
    - Rollback
    - RunQuery
    - PartitionQuery
    - ListCollectionIds
    - Listen（ストリーミング）
- データアクセスログ（DATA_WRITE）
    - CreateDocument
    - UpdateDocument
    - DeleteDocument
    - Commit（書き込みあり）
    - BatchWrite
    - Write（ストリーミング）

様々に取得できますが、**FirestoreへのCRUDは基本的に全て取得できる**理解で良いと思います。
加えて、[Listen](https://firebase.google.com/docs/firestore/query-data/listen?hl=ja)等のFirestoreらしい機能に関する監査ログも取得できます。

## 補足事項
監査ログに対して除外の設定をしなかった場合、エンドユーザ（モバイル/Webアプリ）からのデータアクセスも全てCloud Loggingに吐かれます。
Cloud Loggingは良心的な値段設定ではありますが、それでも不要な課金が発生するのは避けたい場合があるかもしれません。

https://cloud.google.com/stackdriver/pricing?hl=ja#logging-pricing-summary

また、要件によっては、エンドユーザのデータアクセスログはCloud Loggingに吐きたくない場合があるかもしれません。

その場合、

**Google Cloudコンソール > 監査ログ > Firestore/Datastore API > 「除外ユーザー」**

に前述の「Firebaseセキュリティルールのサービスアカウント」を追加してあげれば、エンドユーザのログがCloud Loggingに流れなくなります。
ケースバイケースで設定するようにすれば良いと思います[^8]。


[^1]: 2021年7月20日現在まだプレビュー版
[^2]: ADMIN_READ/ADMIN_WRITE
[^3]: DatastoreモードはDatastoreがFirestoreに統合された都合で生まれたモードだと認識しています
[^4]: あらゆる監査ログがCloud Loggingに吐かれるようになるため、料金が嵩む場合があります。後述しますが、大量のユーザアクセスがある場合等は「除外ユーザー」を設定してください
[^5]: ⌘ + Enter
[^6]: 余談ですが、Firebaseセキュリティルールのサービスアカウントは、Firebaseプロジェクトによって自動生成されるサービスアカウントです。[こちら](https://firebase.google.com/support/guides/service-accounts?hl=ja)に記載されているように、普段はFirebaseセキュリティルールの管理を行うために用いられます
[^7]: 2021年7月20日現在
[^8]: 更に細かくログを流したい場合は、ログバケットへの追加に関してのみ除外し、別のシンクでGCSに流す等の手段も考えられますがそれはまた別のお話