Databricks Security Analysis Tool (SAT)を触ってみた

本記事はDatabricks アドベントカレンダー2024 22日目の記事です。

https://qiita.com/advent-calendar/2024/databricks


こんにちは、てぃーおみです。
好きなDatabricksのサービスはDatabricks Assistantです（最高だよね）

この記事ではDatabricksのSecurity Analysis Tool (以降SAT）について紹介したいと思います。SATについては日本語での解説記事があまり見当たらなかったので、ツールの概要から丁寧に解説していきたいと思います。


# はじめに
SATはDatabricksアカウントおよびワークスペースのセキュリティ構成を分析し、セキュリティのベストプラクティスに対する遵守状況をチェックしてくれるツールで、Databricks社が公開している[セキュリティ＆トラストセンター](https://www.databricks.com/jp/trust/security-features)でも紹介されています。

REST APIを介して収集される様々な情報は、最終的に以下のような単一のDatabridcks AI/BIダッシュボードで表現され、セキュリティベストプラクティスに対しての逸脱状況を重大度別（高・中・低）に報告してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/88523ff0-a1a3-13aa-052a-ad857d77c30d.png)
出典：https://github.com/databricks-industry-solutions/security-analysis-tool

AWSのSecurity Hubや、AzureのSecurity Centerを利用されたことがある方なら、まさにこれらのDatabridcks版、といったイメージを持っていただければと思います。

本ツールはこちらのGitHubリポジトリで公開されています。

https://github.com/databricks-industry-solutions/security-analysis-tool

ということでこちらのGitHubを見ながら早速触っていきます。

# セットアップ
SATはDatabricksがホスト可能な全てのクラウドプロバイダー（AWS,Azure,GCP）で利用可能です。今回は筆者の実行環境がDatabricks on AWSなので、[AWSのセットアップガイド](https://github.com/databricks-industry-solutions/security-analysis-tool/blob/main/docs/setup/aws.md)をもとに設定を進めていきます。

※なお今回は標準セットアップガイドをもとに進めていきますが、[Terraformベースのセットアップ](https://github.com/databricks-industry-solutions/security-analysis-tool/blob/main/terraform/aws/TERRAFORM_AWS.md)も選択可能です。Terraformに慣れている方はこちらの方がよろしいかと。

:::note warn
セットアップ前に、お手元の実行環境で次の条件が満たされていることを確認してください。
- Python3.9以上がインストール済みであること
- Databricks CLIがインストール済みであること
※未インストールの方は[こちらを参考に](https://docs.databricks.com/ja/dev-tools/cli/install.html)インストールを完了させてください。
- 対象のワークスペースからPyPiへアクセス可能なこと（閉域環境下は注意）
:::

#### 1. サービスプリンシパルの用意
まずはサービスプリンシパルを作成していきます。
1-1.各管理者ロールの付与 
アカウントコンソールからサービスプリンシパルを作成し、サービスプリンシパルに対してアカウント管理者ロールを付与します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/40c89b96-21a1-107d-2a57-a7778cb00bbb.png)


次にメタストア管理者ロールを付与します。ちなみにメタストア管理者はグループ単位で指定するのが望ましいです。今回はmetastore_adminというメタストア管理者グループに加入させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/8c2c7afc-911b-d01d-58e8-5c838978622b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/31beed44-6583-3626-5f44-d7197ed6dfcb.png)
最後にワークスペース管理者ロールも付与します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/8bf8224f-9325-d7b7-93a3-b1b9440e1adc.png)


1-2. OAuthシークレットの作成
OAUthシークレットを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/e0df61b7-d0b4-84db-f58c-c29ce39f398b.png)
画面に表示されたクライアントIDとシークレットを保存します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/40b103b5-7fac-b5ef-448f-1f33db454f3b.png)

#### 2. DatabricksCLI経由でのSATインストール

2-1. Databridcks CLIのプロファイル設定
Databricks CLIで使用するプロファイル（ファイル名：`.databrickscfg`）を作成します。
[こちらのドキュメント](https://docs.databricks.com/en/dev-tools/cli/authentication.html#oauth-machine-to-machine-m2m-authentication)を参考に、以下のように記述します。

    [<任意のプロファイル名>]
    host          = <Databricks ワークスペースのURL>
    client_id     = <Databricks サービス プリンシパル クライアントID>
    client_secret = <Databricks サービス プリンシパル シークレット>

サービスプリンシパルのIDとシークレットは先ほど取得したものを指定してください。

2-2. SATインストール
一通り事前準備が終わりましたので、ついにSATをインストールします。まずはリポジトリをローカルにクローンします。

      git clone https://github.com/databricks-industry-solutions/security-analysis-tool.git
      
  ターミナル上で`install.sh`を実行します。

```
$ cd security-analysis-tool
$ ./install.sh 
```

必要情報を入力していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/5ba62adb-4d32-73e9-503f-c7dadff08f82.png)

簡単に説明していきたいと思います。
1. 一番初めはプロファイル名を選択します（`.databrickscfg`内に複数のプロファイルが記述されている場合は、適切なプロファイル名を選択してください）

2. DatabricksのアカウントIDを入力します。アカウントコンソールの右上のアイコンからアカウントIDを取得可能です

3. SATはUnity Catalog内のカタログにスキーマを作成するので、その際に使用するカタログを決定します
3. 上で選択したカタログ内に作成されるスキーマ名の選択になります
3. ユーザーのワークスペース内のSQLウェアハウスを利用しますのでその確認です
3. クライアントIDとクライアントシークレットは上述のサービスプリンシパルの情報を入力してください
3. プロキシを使用している場合は「ｙ」を選択してプロキシサーバーを指定することが出来ます


こんな画面が出ましたら、セットアップ完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/2f322546-7e27-c0b3-7674-e66609ee666e.png)


#### 3. ジョブの実行
ワークスペースにアクセスし、ワークフロー画面で`SAT Initializer Notebook (one-time)`と`SAT Driver Notebook`の2つのジョブが作成されていることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/fad7e54b-51da-dc84-7758-f1cda20cf104.png)
その名の通り、`SAT Initializer Notebook (one-time)`は初回のみ実行するジョブで、`SAT Driver Notebook`はスケジュール設定がされているジョブになります。

ワークスペース内の情報を収集してダッシュボードを作成するには、まず`SAT Initializer Notebook (one-time)`を実行し、そのあと続けて`SAT Driver Notebook`を実行してください
（`SAT Initializer Notebook (one-time)`を実行しただけだと、ダッシュボード自体は作成されますが、データ収集がされていない状態で真っ白なダッシュボードになるかと思います、2つとも実行するようにしてください）

# ダッシュボードの確認

ジョブを実行した後、サイドバーからダッシュボードを選択し、`SAT - Security Analysis Tool (Lakeview - Experimental)`という名前でこんな感じのダッシュボードが作成されているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/38bab417-23bd-77aa-d83d-0e9a357823e9.png)

色々と情報提供してくれていますね。
具体的には、SATは以下の5つのカテゴリごとにセキュリティベストプラクティスに対しての逸脱状況を整理してくれています。

- Network Security
- Identity & Access
- Data Protection
- Governance
- Informational

例えばGovernanceを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/c1e42347-e80e-e593-685c-88cad12fad13.png)

なんか色々と怒られていますが、特に重要度の高い（High）項目が3つあるみたいですね。
そのうちの１つを確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/86a8e581-9ca7-bb2d-4cc1-a8b2064fb521.png)

チェック項目には「Monitor audit logs with system tables」と記載されていますので、システムテーブルを有効化してちゃんと監査ログテーブルをモニタリング出来るようにしなさい、と怒られているようです。
ちなみに各チェック項目のRecommendation列には、チェック項目に関連する公式ドキュメントのURLがマッピングされているので、具体的に何をしたら良いのか？と迷った時もこちらを見れば対策出来そうですね。


ということでRecommendation列に記載の以下のURLを参考に、監査ログシステムテーブルを有効化します。

https://docs.databricks.com/ja/admin/system-tables/index.html

`system.access.audit`テーブルを有効化したところで、もう一度`SAT Driver Notebook`ジョブを実行してダッシュボードを更新してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/b4acccb5-03ae-8817-a143-a4a9f046fdf6.png)

無事にStatusが更新されました！
こんな感じで他の項目についても対応していけば、セキュリティベスプラに準拠したDatabricks環境が出来上がっていくという訳ですね。

# カスタマイズしてみる
一通り触ってみましたが、折角なのでちょっとだけいじってみます。
### ダッシュボードの日本語化

デフォルトのダッシュボードでも十分分かりやすいですが、チェック項目等が英語になっているので、これを日本語にしてみたいと思います。
ダッシュボードの裏側で使用されている各テーブルは、セットアップ時に指定したカタログ配下の`security_analysis`というスキーマ内に格納されています。これらの中でチェック項目やRecommendation列については、以下の`security_best_practices`で管理されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/8122756c-7d7a-b57a-5428-631de9773d0c.png)

このテーブルの英語の文章を、Databricks上でホストされている`databricks-meta-llama-3-3-70b-instruct`で日本語に変換してみたいと思います。コーディングはちょっとだけDatabricks Assistant君に協力してもらいました。

```py
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.serving import ChatMessage, ChatMessageRole
from pyspark.sql.functions import pandas_udf
from pyspark.sql.types import StringType
import pandas as pd

w = WorkspaceClient()

def translate_to_japanese(text: pd.Series) -> pd.Series:
    responses = []
    for t in text:
        response = w.serving_endpoints.query(
            name="databricks-meta-llama-3-3-70b-instruct",
            messages=[
                ChatMessage(
                    role=ChatMessageRole.SYSTEM, content="あなたは優秀な翻訳家です。与えられた英語を適切な日本語に翻訳してください。"
                ),
                ChatMessage(
                    role=ChatMessageRole.USER, content=t
                ),
            ],
            max_tokens=500,
        )
        responses.append(response.choices[0].message.content)
    return pd.Series(responses)

# Register the Pandas UDF
translate_to_japanese_udf = pandas_udf(translate_to_japanese, StringType())

# Read the data
data = spark.sql("SELECT * FROM <カタログ名>.security_analysis.security_best_practices")

# Collect the data to the driver
data_pd = data.toPandas()

# Overwrite 'check' column with translations
data_pd['check'] = translate_to_japanese(data_pd['check'])

# Overwrite 'recommendation' column with translations
data_pd['recommendation'] = translate_to_japanese(data_pd['recommendation'])

# Convert back to Spark DataFrame
data_translated = spark.createDataFrame(data_pd)

# Write the translated data back in Delta format
data_translated.write.mode("overwrite").saveAsTable("<カタログ名>.security_analysis.security_best_practices")
```
こんな感じで日本語に出来ました。これで再度ダッシュボードを更新してみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/02754a0d-eec5-5a4c-15d6-21a8b08e7007.png)

ダッシュボードの情報を日本語で確認出来るようになりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/454bae3f-d513-15e4-2c45-385b3ff722cd.png)


### ジョブのスケジュール設定を変更する
今回の標準セットアップではシェルスクリプトを実行しただけでしたが、実は裏側では[Databricks Asset Bundles](https://docs.databricks.com/ja/dev-tools/bundles/index.html)が使用されています。
ジョブの設定画面を見ると以下のようなポップアップが確認出来ると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/730c3e53-dcae-7dc5-2083-c4cb2b7bdb28.png)

`SAT Driver Notebook`のジョブ設定を変更するために、YAMLファイルを確認してみます。dabs/dabs_template/template/tmp/resources/sat_driver_job.yml.tmplを覗いてみてください。

```yml
resources:
  jobs:
    sat_driver:
      name: "SAT Driver Notebook"
      schedule:
        quartz_cron_expression: "0 0 8 ? * Mon,Wed,Fri"
        timezone_id: "America/New_York"
      tasks:
        - task_key: "sat_initializer"
          job_cluster_key: job_cluster
          libraries:
            - pypi:
                package: dbl-sat-sdk
          notebook_task:
            notebook_path: "../notebooks/security_analysis_driver.py"

      job_clusters:
        - job_cluster_key: job_cluster
          new_cluster:
            data_security_mode: SINGLE_USER
            num_workers: 5
            spark_version: {{.latest_lts}}
            runtime_engine: "PHOTON"
            node_type_id: {{.node_type}}
            {{- if eq .cloud "gcp" }}
            gcp_attributes:
              google_service_account: {{.google_service_account}}
            {{- end }}

```

スケジュール設定を見ると、毎週月曜日、水曜日、金曜日の朝8時に実行されるよう設定されていますが、タイムゾーンが"America/New_York"になっているのがちょっと気になります。ということで以下のように変更してみます。

```yml
      schedule:
        quartz_cron_expression: "0 0 8 ? * Mon"
        timezone_id: "Asia/Tokyo"
```
こちらの内容で`databricks bundle deploy`コマンドを実行してみると。。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1564507/db6ef8c3-3487-d866-36f8-e3bca96e5ae2.png)
変更できました！

# おわりに
SATの基本的な機能について触ってみましたが、紹介出来なかった部分がまだまだありますので（特にAsset Bundlesの部分はかなり端折ってしまいました）、気になった方は是非実際に触っていただければと思います。