Featured image of post Azure DatabricksワークスペースAPIをAPI Management経由で利用する

Azure DatabricksワークスペースAPIをAPI Management経由で利用する

Databricksきつい 触りたくない

まとめ

どうしてもDatabricksのワークスペースAPIをAPI Management経由で叩きたかったのだが、
設定が結構大変な上になぞりやすい公式のドキュメントが見つからなかったので
自分が設定できたときの手順を残しておく。

  • DatabricksワークスペースAPIをAPI Managementのバックエンドとして利用する際はカスタムURLが使える
  • API Managementに持たせる資格情報はDatabricksワークスペースのPATも利用可能だが、
    よりセキュアにやるならAPI Managementのauthentication-managed-identityポリシーでresource="2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"を指定する

前提条件

Databricks, API Managementは以下の設定で作成済みとする。

手順

バックエンドAPIを作成

まずはAPI ManagementからDatabricksへ接続するためのバックエンドAPI情報を設定する。

API Managementの管理画面から「APIs」→「Backends」→「+追加」と進み、
バックエンド(例: dbw-01)を作成する。
ランタイムURLにDatabricksワークスペースURLをぺたっと貼るだけでOK。
(資格情報は後ほど設定する)

次にAPI定義を作成する。
API Managementの管理画面から「APIs」→「API」→「+Add API」と進み、
API定義(例: dbw-01)を作成する。
名前とAPI URL suffix(例: dbw-01)を設定するだけでよい。
(Web service URLは設定せず、後ほどポリシー式で先ほど作成したバックエンドを指定する)

API定義が作成できたら、「Design」→「All operations」→「Design」から全操作(メソッド)共通のポリシー編集画面を開き、
先ほど作成したバックエンドを指定するset-backend-serviceポリシーを追加する。

また、リクエストを受信しバックエンドに流せるようにoperationを追加する。
Azure Databricks REST API reference等を参考に必要なAPI操作を定義するのがよさげ。
(OpenAPIで定義されたものがあればインポートできるんだけど、自分が探した限りだと見つけられなかった)

今回は簡単に確認したいだけなので、全てのGETリクエストをそのままのパスで流すワイルドカードを設定する。
(ドキュメントの注意事項にもあるように、本来は必要な操作だけをホワイトリスト的に定義した方が安全)

これでAPIを利用する準備ができたように見えるが(実際ほぼ終わり)、
資格情報を設定していないので試しにAPI Management越しにリクエストを送っても失敗する。

# 変数の設定
$ apimUrl="<API Managementの管理画面「概要」→「基本」→「ゲートウェイのURL」>" # 例: https://apim-name.azure-api.net
$ subscriptionKey="<API Managementの管理画面「APIs」→「サブスクリプション」から取得した主キー>"

# API Management越しにクラスター一覧APIを呼び出す(Databricks用のキーは付与せず、API Management用のキーのみ設定)
$ curl -H "Ocp-Apim-Subscription-Key: ${subscriptionKey}" ${apimUrl}/dbw-01/api/2.1/clusters/list

{"error_code":"401","message":"Unauthorized"}

API ManagementのマネージドIDに権限を付与

次はこの資格情報を設定していく。

参考: https://learn.microsoft.com/ja-jp/azure/databricks/dev-tools/azure-mi-auth

Databricks側でPAT発行してそれをAPI ManagementバックエンドのAuthorizationヘッダーに設定、でもいいんだけど、
PATってあんまり推奨されるものでもない(個人の権限ですべての操作が行われてしまう)のでできればマネージドIDでやりたい。

このため、まずはAPI Managementのシステム割り当てマネージドIDをDatabricksにサービスプリンシパルとして登録(ワークスペースへのアクセス権限を付与)する。
(ドキュメントだとユーザー割り当てマネージドIDが推奨されてるけど、やってみたらシステム割り当てでもできちゃった)

Databricksワークスペースで「設定」→「IDとアクセス」→「サービスプリンシパル」→「Service Principalを追加」からシステム割り当てマネージドIDを新規追加する。
記載するIDはMicrosoft Entra IDの管理画面から「管理」→「すべてのアプリケーション」から対象のマネージドIDの情報を開き、「アプリケーションID」の値を利用する。
(マネージドIDが見つけづらい場合はAPI Management管理画面(portal)の「セキュリティ」→「マネージドID」→「オブジェクト(プリンシパル)ID」の値を取得し、アプリケーション一覧画面で検索する。)

必要であれば特定の権限を持つグループに対象のサービスプリンシパルを追加しておくこと。
(今回は雑にadminに追加してしまっているが、本番運用の際はちゃんと専用のグループと権限を設定した方が良い)

これでAPI ManagementのマネージドIDでDatabricksワークスペースを操作する権限が設定できた。

API Managementのポリシー設定

マネージドIDに権限を付与できたので、
次はAPI Managementがアクセストークンを取得するためのauthentication-managed-identityポリシーを定義する。

resourceに何を指定すればよいのか迷うところだが、
curlでアクセストークンを取得する例を見る感じ2ff814a6-3304-4ab8-85cb-cd0e6f879c1d(DatabricksのプログラムID)でよさそう。
(正直ここに気付けなくて1日くらい溶かした)

ここまでできたら接続設定は完了。
バックエンドAPIの作成後に試した手順で再度リクエストを送ると、
今度は権限が付与されているので成功するようになっている。

$ curl -H "Ocp-Apim-Subscription-Key: ${subscriptionKey}" ${apimUrl}/dbw-01/api/2.1/clusters/list

{"next_page_token":"","prev_page_token":""} 
# クラスターを作成していないのでほぼ空っぽだが、APIリファレンス通りのレスポンスが返っているので動作確認は成功
# https://docs.databricks.com/api/azure/workspace/clusters/list

やったぜ。
これでAPI Managementにさえ疎通できればDatabricksワークスペースAPIが使えるようになった。

後は必要に応じてネットワークを閉域化したり、お好みで…

bicep

今回ブラウザでポチポチした操作をコード(bicep)化するとこんな感じ。↓↓↓

ネットワークまわりの設定で追加したところがあり、
API Managementは外部モードでデプロイして、
Databricksにはプライベートエンドポイント経由で接続するようにした。

また、Databricksワークスペースの細かい設定(IPアクセスリストだったりサービスプリンシパル)はbicepでは書けないっぽいので(Terraformだといけるかも?)、
手動で実施する必要がある。

おわり

Azure Databricksが難しすぎて日々泣いている。😭
ファーストパーティサービスと言いつつRBACはAzureロールと別物だし、サービスエンドポイントはないし…
同じように泣いている人の助けになれば幸い。

おまけ

顔がいいねこ