Azure Databricks の監査ログ取得方法まとめ

みなさん、こんにちは！

誰が、いつ、どのような操作をしたか？という監査ログに関する情報はセキュリティの観点から非常に重要ですが、いざ Azure Databricks で監査ログを取得しようとした際にどのような方法を取るのが良いのかわからなかったため、調査を行い結果をまとめました。

Azure Databricks の監査ログ取得についてお悩みの方の参考になれば幸いです。

## はじめに
監査ログ（Audit log）は以下の2つのサービスで利用可能です。

* **監査ログシステムテーブル**
* **診断ログサービス**

※いずれも Databricks ワークスペースが**Premium**以上のプランである必要があります。

ただし、以下の理由から、**監査ログシステムテーブル**の利用を推奨します。

* 監査ログシステムテーブルは利用可能なすべてのイベントとサービスを記録するが、診断ログサービスではすべてのサービスがログに記録されるわけではない。
* 監査ログシステムテーブルのデータは Databricks 上で管理されているため、ストレージコストがかからず、ユーザによる改ざんも不可能。

## 監査ログシステムテーブル
システムテーブルは、Databricks がホストする運用データおよび使用データの分析ストアです。
監査ログシステムテーブルはシステムテーブルの1つで、ワークスペースで実行された操作やアクセス履歴、オブジェクトに対するアクションなどが記録されています。

設定は以下の手順で実施します。
### 1. Unity Catalog 有効化
監査ログシステムテーブルを利用するには少なくとも1つのワークスペースで Unity Catalog が有効化されている必要があるため、Unity Catalog を有効化しておきます。

具体的な方法については以下の記事をご参照ください。

[Azure Databricks における Unity Catalog 設定ガイド](https://www.reqtc.com/blog/azure-databricks-unity-catalog.html)

### 2. 監査ログシステムテーブル有効化
監査ログシステムテーブルはデフォルトで有効になっていないため、APIを利用して手動で有効化する必要があります。

以下のPythonコマンドをノートブックで実行すると、監査ログシステムテーブル（`system.access.audit`）を有効化できます。
```ruby:qiita.rb
import requests
import json

metastore_id = spark.sql("SELECT current_metastore() as metastore_id").collect()[0]["metastore_id"]
metastore_id = metastore_id.split(":")[-1]

host = "https://" + dbutils.notebook.entry_point.getDbutils().notebook().getContext().browserHostName().get()
url = f"{host}/api/2.0/unity-catalog/metastores/{metastore_id}/systemschemas/access"
api_token = dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().get()
headers = {"Authorization": f"Bearer {api_token}"}

r = requests.put(url=url, headers=headers)
print(r.text)
```

監査ログシステムテーブルが有効化されると、`system`に`access`スキーマが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/e1da4296-d580-48df-884e-36a98d677454.png)

`system.access.audit`に対しクエリを実行することで、監査ログの分析を行うことができます。

※システムテーブルは Databricks 側で管理されているテーブルを Delta Sharing によって共有して見ているものであり、システムテーブルを有効化する以前から記録されているデータが含まれています。

### ログ分析
例として、以下のSQLでユーザが実行した操作とその回数をユーザ名・IPアドレスとともに日別で集計することができます。
```ruby:qiita.rb
SELECT
  event_date,
  user_identity.email,
  action_name,
  source_ip_address,
  count(*) as total
FROM
  system.access.audit
WHERE
  service_name = 'accounts'
GROUP BY
  1,
  2,
  3,
  4
ORDER BY 1 DESC;
```

実行結果は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/deb74ee9-3330-4a6c-9c5a-1db0d605a0f3.png)

その他、監査ログを分析するSQLの例は以下の記事が詳しいです。

[監査ログ システム テーブル リファレンス - Azure Databricks](https://learn.microsoft.com/ja-jp/azure/databricks/admin/system-tables/audit-logs)

### ログの保持期間
監査ログの保持期間はデフォルトで1年間となっています。
保持期間を変更する場合、Azure Databricks アカウントチームに連絡する必要があります。

[システム テーブルを使用してアカウント アクティビティを監視する](https://learn.microsoft.com/ja-jp/azure/databricks/admin/system-tables/)

## 診断ログサービス
診断ログサービスは、Azure Databricks の診断設定を利用したログサービスです。
ワークスペースレベルに限定されますが、監査ログシステムテーブルと同様のログデータを取得可能です。

設定は以下の手順で実施します。
### 1. Log Analytics ワークスペース作成
Azure ポータルから「Log Analytics ワークスペース」を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/b12f1899-c7ac-445f-ae3a-26bae17a6402.png)

「作成」をクリックし、各項目を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/19ebf799-0822-419f-86f1-6993cb00880f.png)

確認画面で作成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/f8871982-2dd1-4ab8-b993-d79aacd4e6b7.png)

これでワークスペースの作成は完了です。

### 2. Databricks 診断ログ設定
Azure Databricks ワークスペースの「監視」→「診断設定」を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/39cbe79d-7850-40f1-ba35-5ece2d51f3f0.png)

「診断設定を追加する」をクリックし、設定画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/c726029b-a71d-451e-b82b-5b3d5293e235.png)

以下の項目を設定します。

* 診断設定の名前：診断設定の名前。任意のものを指定。
* ログ：取得対象のログ。カテゴリから必要なものを選択する（簡単のため今回は allLogs を選択）。
* 宛先の詳細：ログの送信先。「1. Log Analytics ワークスペース作成」で作成したものを選択する。

設定が完了したら、「保存」をクリックして設定を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/cbff0ac7-9667-4f29-ab61-8b0f2b611719.png)

以上で設定は完了です。

### ログ分析
診断ログサービスの場合、指定した Log Analytics ワークスペースにログが送信されるため、そこで Kusto (KQL) という独自のクエリ言語を用いて分析を行います。

「Log Analytics ワークスペース」で対象のワークスペースを指定し、「ログ」からクエリ画面を開いてKQLを実行します。

以下は監査ログシステムテーブルと同じ結果を取得するためのKQLです。
```ruby:qiita.rb
DatabricksAccounts
| extend eventDate = format_datetime(TimeGenerated, 'yyyy-MM-dd')
| distinct eventDate, Identity, ActionName, SourceIPAddress
| summarize total = count() by eventDate, Identity, ActionName, SourceIPAddress
| order by eventDate
```

実行結果は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/2bbded22-5aea-4d3e-ae19-77844e0ee5d2.png)

### ログの保持期間
診断ログサービスの場合、ログ保存先の Log Analytics ワークスペースの設定に依存します。
デフォルトは30日で、最大730日まで延長することが可能です。

[Azure Monitor の各種データの保持期間について](https://jpazmon-integ.github.io/blog/AzureMonitorEssential/MonitorRetentionPeriod/)

## 補足
### 詳細監査ログ
詳細監査ログはワークスペースでクエリまたはコマンドが実行されるたびに記録される追加の監査ログです。各コマンドまたはクエリのテキストが記録されます。

デフォルトでは有効になっていないため、有効化する場合はワークスペースの「設定」→「Advanced」→「Verbose Audit Logs」をオンにする必要があります。

[詳細監査ログを有効にする - Azure Databricks](https://learn.microsoft.com/ja-jp/azure/databricks/admin/account-settings/verbose-logs)

## まとめ
Azure Databricks の監査ログ取得方法についてご紹介しました。

診断ログサービスは Unity Catalog を有効化していなくても利用できるというメリットはありますが、監査ログシステムテーブルに比べて取得できる情報が少なく、分析や可視化もしにくいというデメリットがあります。

特別な事情がない限り、監査ログシステムテーブルを使用されることをおすすめします。

## 参考
* [診断ログ リファレンス - Azure Databricks](https://learn.microsoft.com/ja-jp/azure/databricks/admin/account-settings/audit-logs)
* [Databricks System Table を有効化して監査ログや課金データを取得しよう！ #audit - Qiita](https://qiita.com/maroon-db/items/b89d47009948206ac064)
* [【Azure Databricks】Databricksの診断ログを保存してみる | Azure導入支援デスク](https://cloud.sojitz-ti.com/blog/azure-databricks-audit-logs-01/)
* [andyweaves/databricks-audit-logs | GitHub](https://github.com/andyweaves/databricks-audit-logs/tree/main)