Databricks Apps では、Azure Databricks でのセキュリティで保護されたアプリケーション開発がサポートされています。 アプリがワークスペース内のデータとサービスにアクセスするときは、データ アクセス制御を適用し、ユーザーのアクセス許可を尊重する認証と承認のメカニズムを使用する必要があります。 Databricks Apps 承認モデルは OAuth 2.0 に基づいており、アプリに割り当てられたアクセス許可と、それにアクセスするユーザーのアクセス許可を組み合わせます。
このフレームワークをサポートするために、Databricks Apps は 2 つの補完的な ID モデルを使用します。
アプリの承認
各 Azure Databricks アプリには、Azure Databricks リソースにアクセスするときに ID として機能する専用の サービス プリンシパル があります。 このサービス プリンシパルはアプリ インスタンスに固有であり、アプリ間で再利用することはできません。 アプリに割り当てられているサービス プリンシパルを変更したり、アプリの作成時に既存のサービス プリンシパルを指定したりすることはできません。 Azure Databricks では、この ID を使用して、ユーザーとは別にアプリのアクセス許可を評価します。これにより、ユーザー操作のコンテキスト外であっても、アプリは明示的に付与されたリソースにのみアクセスできます。
この分離は、セキュリティ境界を適用するのに役立ちます。これにより、アプリ アクティビティの監査が可能になり、バックグラウンド処理や自動タスクなどのシナリオがサポートされます。
サービス プリンシパルは、一意の ID で表されます。 アプリの [承認 ] タブからコピーします。
アプリを作成すると、Azure Databricks によってアプリの専用サービス プリンシパルが自動的にプロビジョニングされます。 サービス プリンシパルは、アプリのすべてのデプロイで同じままです。 アプリを削除すると、Azure Databricks によってサービス プリンシパルが削除されます。
個々のユーザーのコンテキストを必要とせずに、アプリが単独で実行するアクションにはサービス プリンシパルを使用します。 一般的な使用用途は次のとおりです。
- バックグラウンド タスクの実行
- 共有構成またはメタデータの読み取りまたは書き込み
- アクティビティまたは使用状況メトリックのログ記録
- セキュリティで保護されたエンドポイントを介した外部サービスの呼び出し
アプリによって開始されるすべてのアクションは、サービス プリンシパルのアクセス許可を使用します。 標準のアクセス許可の割り当てを使用して、サービス プリンシパルに特定のリソースへのアクセス権を付与します。 ただし、ユーザー レベルのアクセス制御はサポートされていません。 アプリを操作するすべてのユーザーは、サービス プリンシパルに対して定義されているのと同じアクセス許可を共有します。これにより、アプリは個々のユーザー ID に基づいてきめ細かいポリシーを適用できなくなります。
次の例は、アプリがサービス プリンシパルを使用して Unity カタログ内のデータを照会する方法を示しています。
この場合、サービス プリンシパルは、SQL ウェアハウスとクエリする Unity カタログ テーブルの両方に明示的にアクセスする必要があります。
このモデルは、アプリのすべてのユーザーに同じデータを表示させる場合、またはアプリがユーザー固有のアクセス制御に関連付けられていない共有操作を実行する場合に適切に機能します。
アプリの承認資格情報を取得する
アプリの承認のために、Azure Databricks はサービス プリンシパルの資格情報をアプリの環境に自動的に挿入します。 次の環境変数は、必要な OAuth クライアント値を保持します。
| Variable | Description |
|---|---|
DATABRICKS_CLIENT_ID |
サービス プリンシパルの OAuth クライアント ID |
DATABRICKS_CLIENT_SECRET |
サービス プリンシパルの OAuth クライアント シークレット |
Azure Databricks は、アプリ ランタイムで環境変数を自動的に設定します。 アプリは、それ自体として認証するときにこれらの変数を使用します。
Python
import os
client_id = os.getenv('DATABRICKS_CLIENT_ID')
client_secret = os.getenv('DATABRICKS_CLIENT_SECRET')
JavaScript
const clientId = process.env.DATABRICKS_CLIENT_ID;
const clientSecret = process.env.DATABRICKS_CLIENT_SECRET;
Note
Azure Databricks SDK を使用している場合、通常、これらの環境変数に手動でアクセスする必要はありません。 SDK は 統合認証に 従い、環境内の資格情報を自動的に検出します。
例: アプリの承認を使用してクエリを実行する
Python
この例では、環境変数からサービス プリンシパルの資格情報をプルし、OAuth 承認を実行する SDK Config オブジェクトを使用します。
from databricks import sql
from databricks.sdk.core import Config
cfg = Config()
conn = sql.connect(
server_hostname=cfg.host,
http_path="<your-warehouse-http-path>",
credentials_provider=lambda: cfg.authenticate,
)
query = "SELECT * FROM main.sandbox.sales_customers LIMIT 1000"
with conn.cursor() as cursor:
cursor.execute(query)
df = cursor.fetchall_arrow().to_pandas()
print(df.head())
conn.close()
JavaScript
この例では、環境変数を使用して OAuth を使用してサービス プリンシパルで認証し、 Databricks SQL Driver for Node.jsでクエリを実行します。
import { DBSQLClient } from '@databricks/sql';
const client = new DBSQLClient();
const connection = await client.connect({
authType: 'databricks-oauth',
host: process.env.DATABRICKS_SERVER_HOSTNAME,
path: process.env.DATABRICKS_HTTP_PATH,
oauthClientId: process.env.DATABRICKS_CLIENT_ID,
oauthClientSecret: process.env.DATABRICKS_CLIENT_SECRET,
});
const query = 'SELECT * FROM main.sandbox.sales_customers LIMIT 1000';
const cursor = await connection.cursor(query);
const rows = [];
for await (const row of cursor) {
rows.push(row);
}
console.log(rows.slice(0, 5)); // Like df.head()
await connection.close();
ユーザーの承認
Important
ユーザー承認は パブリック プレビュー段階です。
ユーザー承認は、ユーザーの 代理承認とも呼ばれ、Databricks Apps アプリがアプリ ユーザーの ID で動作することを許可します。 Azure Databricks は、ユーザーのアクセス トークンをアプリに転送します。このトークンを使用して、ユーザーの代わりにリソースにアクセスします。 Azure Databricks では、ユーザーの既存の Unity カタログ ポリシーに基づいてすべてのアクセス許可が適用されます。
Azure Databricks では、ユーザーの代わりに動作するアプリのセキュリティ リスクを管理するために、スコープを使用して、ユーザーの承認によってアプリが実行できるアクションを制限します。
アプリが個々のユーザーのアクセス許可を尊重する必要がある場合は、ユーザー承認を適用します。 一般的なユース ケースは次のとおりです。
- テーブルまたはボリュームのクエリ
- SQL ウェアハウスまたはコンピューティングへのアクセス
- ユーザー アクションに関連付けられたジョブまたはワークフローの実行
すべてのアクションでは、ユーザーの既存の Unity カタログアクセス許可が使用されます。
ユーザー承認では、行レベルのフィルターや列マスクなどの Unity カタログ機能をアプリ アクティビティに適用することで、きめ細かいアクセス制御が可能になります。 このアプローチでは、アクセス制御とワークスペース ガバナンスの一貫性が保たれ、アクセス許可ロジックがアプリにハードコーディングされるのを回避できます。
ユーザー承認によるきめ細かなアクセス許可
アプリにユーザー承認を追加すると、次のようなユーザーの既存の Unity カタログアクセス許可が適用されます。
- 表示される行を制限する行レベルのフィルター
- 列マスクを使用して機密データを編集または変換する
Azure Databricks はユーザーの ID を使用してユーザー承認要求を評価するため、アプリがデータにアクセスすると、これらのポリシーが自動的に適用されます。 たとえば、テーブルにリージョン別の可視性を制限する行フィルターが含まれている場合、アプリはユーザーがクエリを実行できる行のみを返します。 アプリで追加のフィルター処理ロジックは必要ありません。
この方法では、アプリケーション コードでアクセス制御ロジックを複製することを回避し、ワークスペース レベルのガバナンスとの一貫性を確保します。 管理者が Unity カタログ ポリシーを更新すると、アプリはこれらの変更を自動的に考慮します。
スコープベースのセキュリティと特権のエスカレーション
ユーザー承認を使用するアプリでは、ユーザーに代わってアプリが実行できる操作を制限するために、特定の承認スコープを宣言する必要があります。 スコープは、次のような特定の API またはリソースの種類へのアクセスを制限します。
-
sqlSQL ウェアハウスに対してクエリを実行する場合 -
dashboards.genieあなたの Genie スペースを管理するための -
files.filesファイルとディレクトリを管理するための
スコープを選択しない場合、Azure Databricks は、アプリが基本的なユーザー ID 情報を取得できるようにする既定のセットを割り当てます。
iam.access-control:readiam.current-user:read
これらの既定値は、ユーザー承認機能をサポートするために必要ですが、データやコンピューティング リソースへのアクセスは許可されません。 アプリを作成または編集するときに、スコープを追加します。
スコープでは、最小権限ポリシーに従います。 必要なスコープのみを要求するようにアプリを構成してください。 Azure Databricks は、ユーザーがアクセス許可を持っている場合でも、承認されたスコープ外のすべての機能へのアクセスをブロックします。 たとえば、アプリが sql スコープのみを要求した場合、ユーザーがアプリの外部にアクセスできる場合でも、エンドポイントを提供するモデルにアクセスすることはできません。
ユーザーが最初にアプリにアクセスすると、Azure Databricks は、要求されたスコープ内で動作するようにアプリを明示的に承認するように求めます。 管理者は、必要に応じて、組織のポリシーに合わせてアクセスを調整するために、ユーザーに代わって同意を付与できます。
アプリにスコープを追加する
Important
ユーザー承認は パブリック プレビュー段階です。 アプリにスコープを追加するには、ワークスペース管理者が有効にする必要があります。
ユーザー承認を有効にした後、スコープを追加する前に、既存のアプリを再起動する必要があります。 ユーザーの承認を無効にする場合は、リソースにアクセスするために現在のユーザーのアクセス トークンの使用を停止するために、既存のアプリを再起動する必要があります。
Azure Databricks UI でアプリを作成または編集するときに、ユーザー承認を構成します。
構成手順で、[+スコープの追加] をクリックし、アプリがユーザーの代わりにアクセスできる Azure Databricks API またはリソースを定義するスコープを選択します。 Azure Databricks では、実行時にこれらのスコープが適用され、アクセスを許可する前にユーザーまたは管理者の同意が必要です。
完全な例については、 GitHub の Databricks Apps 承認デモを参照してください。 アプリの例では、アプリとユーザー承認モデルの両方を使用する方法を示し、セットアップ手順とユーザー承認を使用したクエリの例が含まれています。
ユーザー承認資格情報を取得する
ユーザー承認のために、Azure Databricks はユーザーの ID とアクセス トークンを HTTP ヘッダーでアプリに転送します。 アプリは、ユーザーの代わりに動作するために、これらのヘッダーを抽出する必要があります。
これらのヘッダーを取得する方法は、使用するフレームワークによって異なります。
Streamlit
import streamlit as st
user_access_token = st.context.headers.get('x-forwarded-access-token')
Gradio
import gradio as gr
def query_fn(message, history, request: gr.Request):
access_token = request.headers.get("x-forwarded-access-token")
...
パラメーターとして宣言すると、Gradio によって要求オブジェクトがアプリの関数に自動的に挿入されます。 要求を手動で構築または取得する必要はありません。
ダッシュとフラスク
from flask import request
headers = request.headers
user_token = headers.get('x-forwarded-access-token')
Shiny
user_token = session.http_conn.headers.get('x-forwarded-access-token')
簡易
import express from 'express';
const userAccessToken = req.header('x-forwarded-access-token');
例: ユーザー承認を使用してクエリを実行する
この場合、アプリはユーザーのアクセス トークンをコネクタに直接渡し、Azure Databricks はユーザーのアクセス許可をクエリに適用します。
Python
from databricks import sql
from databricks.sdk.core import Config
from flask import request
cfg = Config()
user_token = request.headers.get("x-forwarded-access-token")
conn = sql.connect(
server_hostname=cfg.host,
http_path="<your-warehouse-http-path>",
access_token=user_token
)
query = "SELECT * FROM main.sandbox.sales_customers LIMIT 1000"
with conn.cursor() as cursor:
cursor.execute(query)
df = cursor.fetchall_arrow().to_pandas()
print(df.head())
conn.close()
JavaScript
import { DBSQLClient } from '@databricks/sql';
import express from 'express';
const app = express();
app.get('/', async (req, res) => {
const userToken = req.header('x-forwarded-access-token');
const client = new DBSQLClient();
const connection = await client.connect({
authType: 'access-token',
host: process.env.DATABRICKS_SERVER_HOSTNAME,
path: process.env.DATABRICKS_HTTP_PATH,
token: userToken,
});
const query = 'SELECT * FROM main.sandbox.sales_customers LIMIT 1000';
const cursor = await connection.cursor(query);
const rows = [];
for await (const row of cursor) {
rows.push(row);
}
console.log(rows.slice(0, 5));
await connection.close();
res.send('Query complete');
});
app.listen(3000);
ユーザー承認のベスト プラクティス
ユーザーに代わってアクションを実行するアプリを構築する場合は、次のベスト プラクティスに従って、セキュリティで保護された監査可能なアクセスを確保します。
- アプリの所有者または少数の信頼されたユーザーのみがアクセスできるフォルダーにアプリ コードを格納します。
- アプリのメンテナンスとレビューを担当する信頼できる上級開発者にのみ、
CAN MANAGEアクセス許可を付与します。 アプリの実行が承認された特定のユーザーまたはグループにのみ、CAN USEアクセス許可を付与します。 - トークンが印刷、ログ記録、またはファイルに書き込まれていないことを確認します。 これは、すべてのログ 記録ステートメント、デバッグ ツール、およびエラー ハンドラーに適用されます。 たとえば、
print(f"User token: {token}")の代わりにheaders = {"Authorization": f"Bearer {token}"}を使用します。 - 機能に必要な最低限必要な承認スコープのみを要求するように各アプリを構成します。
- コード レビュー中に、スコープとアクセス許可の設定がセキュリティ要件と一致し、不要なアクセス権を付与していないことを確認します。
- 運用環境にデプロイする前に、すべてのアプリ コードに対してピア レビューを適用します。
- ユーザー ID、アクションの種類、ターゲット リソース、状態など、ユーザーに代わって実行されたすべてのアクションについて、構造化された監査ログがアプリ コードに記録されていることを確認します。
認証方法
Databricks Apps のトークンを取得するために、ユーザーとサービス プリンシパルの両方が標準の OAuth 2.0 フローを使用して認証されます。 メソッドは、呼び出し元がユーザーであるか、自動化されたワークロードであるかによって異なります。
ワークスペース ログインの場合 (ユーザーのみ):
- シングル サインオン (SSO): シングル サインオン (SSO) が構成されている場合、ユーザーは ID プロバイダーを介して認証を行います。
- ワンタイム パスワード (OTP): SSO が構成されていない場合、ユーザーは一時的なパスワードを受け取ります。
OAuth フロー (アプリとワークロード) の場合:
- ユーザーからマシンへの (U2M) OAuth: ユーザーが認証され、結果のトークンによってユーザー承認が有効になり、アプリがユーザーの代わりに動作できるようになります。
- マシン間 (M2M) OAuth: サービス プリンシパルは、クライアント資格情報またはフェデレーションを使用して認証します。 これらのトークンは、アプリがユーザーではなくそれ自体として機能するアプリの承認を支えます。
トークン認証を使用して Databricks アプリを呼び出す手順については、「トークン認証を 使用して API Databricks アプリに接続する」を参照してください。
モデルの比較と結合
Databricks Apps では、アプリとユーザーの承認を個別に、またはまとめて使用できます。 これらのモデルはさまざまな目的に対応し、並列で動作するように設計されています。
| 承認モデル | いつ使用するか | 利用事例の例 |
|---|---|---|
| アプリの承認 | アプリがユーザーの ID に依存しない操作を実行する場合 | ログの書き込み、共有構成へのアクセス、外部サービスの呼び出し |
| ユーザーの承認 | アプリが現在のユーザーのコンテキストでリソースにアクセスする必要がある場合 | Unity カタログ データのクエリ、コンピューティングの起動、行レベルのアクセス許可の適用 |
| 両方 | アプリが共有操作とユーザー固有操作の両方を実行する場合 | アプリ ID を使用したメトリックのログ記録、ユーザー ID を使用したフィルター処理されたデータのクエリ |