次の方法で共有


API を使用して外部アプリを Lakebase に接続する

Important

Lakebase 自動スケールは、ベータ版としてeastus2westeuropewestusの各リージョンで利用できます。

Lakebase 自動スケーリングは、自動スケール コンピューティング、ゼロへのスケーリング、分岐、インスタント リストアを備えた最新バージョンの Lakebase です。 Lakebase Provisioned との機能の比較については、バージョンの選択を参照してください。

このガイドでは、REST API の直接呼び出しを使用して外部アプリケーションを Lakebase 自動スケーリングに接続する方法について説明します。 この方法は、Databricks SDK が言語 (Node.js、Ruby、PHP、Elixir、Rust など) で使用できない場合に使用します。

言語に SDK のサポート (Python、Java、Go) がある場合は、SDK を 使用して外部アプリを Lakebase に接続して 、より簡単なトークン管理を行います。

OAuth トークンローテーションを使用してデータベース資格情報を取得するには、2 つの API 呼び出しを行います。 curl と Node.jsの例を示します。

2 段階認証: この方法では、データベース資格情報ごとに 2 つの API 呼び出しが必要です。(1) ワークスペース OAuth トークンのサービス プリンシパル シークレットを交換し、(2) OAuth トークンをデータベース資格情報と交換します。 どちらのトークンも 60 分後に有効期限が切れます。 SDK は手順 1 を自動的に処理します。

[前提条件]

SDK アプローチと同じセットアップが必要です。サービス プリンシパル、Postgres ロール、接続の詳細です。

前提条件 重要な詳細 詳細情報
サービス プリンシパル 最大有効期間が 730 日の OAuth シークレット。ワークスペース アクセスを有効にします。 Postgres ロールと env vars の クライアント ID (UUID) をメモします。 サービス プリンシパルを作成する
Postgres ロール Lakebase SQL エディターで OAuth ロールを作成し、<c0 /> に CONNECT、USAGE、<c1 />/<c2 />/DELETE の権限を付与します。 手順 1 のクライアント ID を使用します。 Postgres ロールを作成する
接続の詳細 Lakebase Console Connect から: エンドポイント名 (projects/.../branches/.../endpoints/...)、 ホストデータベース (通常は databricks_postgres)。 接続の詳細を取得する

動作方法

手動 API アプローチには、次の 2 つのトークン交換が必要です。

手動 API トークン交換フロー

トークンの有効期間:

  • サービス プリンシパル シークレット: 最大 730 日 (作成時に設定)
  • ワークスペース OAuth トークン: 60 分 (手順 1)
  • データベース資格情報: 60 分 (手順 2)

トークンスコープ: データベース資格情報はワークスペースの範囲内です。 endpoint パラメーターが必要ですが、返されたトークンは、サービス プリンシパルにアクセス許可があるワークスペース内の任意のデータベースまたはプロジェクトにアクセスできます。

環境変数を設定する

アプリケーションを実行する前に、次の環境変数を設定します。

# Databricks workspace authentication
export DATABRICKS_HOST="https://your-workspace.databricks.com"
export DATABRICKS_CLIENT_ID="<service-principal-client-id>"
export DATABRICKS_CLIENT_SECRET="<your-oauth-secret>"

# Lakebase connection details (from prerequisites)
export ENDPOINT_NAME="projects/<project-id>/branches/<branch-id>/endpoints/<endpoint-id>"
export PGHOST="<endpoint-id>.database.<region>.databricks.com"
export PGDATABASE="databricks_postgres"
export PGUSER="<service-principal-client-id>"   # Same UUID as client ID
export PGPORT="5432"

接続コードを追加する

curl

この例では、生の API 呼び出しを示します。 運用アプリケーションの場合は、トークン キャッシュと更新ロジックを実装します。

# Step 1: Get workspace OAuth token
OAUTH_TOKEN=$(curl -s -X POST "${DATABRICKS_HOST}/oidc/v1/token" \
  -u "${DATABRICKS_CLIENT_ID}:${DATABRICKS_CLIENT_SECRET}" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&scope=all-apis" \
  | jq -r '.access_token')

echo "Got workspace OAuth token (60-min lifetime)"

# Step 2: Get database credential
PG_TOKEN=$(curl -s -X POST "${DATABRICKS_HOST}/api/2.0/postgres/credentials" \
  -H "Authorization: Bearer ${OAUTH_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"endpoint\": \"${ENDPOINT_NAME}\"}" \
  | jq -r '.token')

echo "Got database credential (60-min lifetime)"

# Step 3: Connect to Postgres
PGPASSWORD="${PG_TOKEN}" psql \
  -h "${PGHOST}" \
  -p "${PGPORT}" \
  -U "${PGUSER}" \
  -d "${PGDATABASE}" \
  -c "SELECT current_user, current_database()"

Node.js

この例では、トークンのフェッチとキャッシュを処理する非同期パスワード関数で node-postgres を使用します。

import pg from 'pg';

// Step 1: Fetch workspace OAuth token
async function getWorkspaceToken(host, clientId, clientSecret) {
  const auth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
  const response = await fetch(`${host}/oidc/v1/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: `Basic ${auth}`,
    },
    body: 'grant_type=client_credentials&scope=all-apis',
  });

  if (!response.ok) {
    throw new Error(`OAuth failed: ${response.status}`);
  }

  const data = await response.json();
  return {
    token: data.access_token,
    expires: Date.now() + data.expires_in * 1000,
  };
}

// Step 2: Fetch database credential
async function getPostgresCredential(host, workspaceToken, endpoint) {
  const response = await fetch(`${host}/api/2.0/postgres/credentials`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${workspaceToken}`,
    },
    body: JSON.stringify({ endpoint }),
  });

  if (!response.ok) {
    throw new Error(`Database credential failed: ${response.status}`);
  }

  const data = await response.json();
  return {
    token: data.token,
    expires: new Date(data.expire_time).getTime(),
  };
}

// Simple caching wrapper (production: use more sophisticated caching)
function cached(fetchFn) {
  let cache = null;
  return async (...args) => {
    const now = Date.now();
    if (!cache || now >= cache.expires - 5 * 60 * 1000) {
      // Refresh 5 min early
      const result = await fetchFn(...args);
      cache = result;
    }
    return cache.token;
  };
}

// Create connection pool with async password function
function createPool() {
  const host = process.env.DATABRICKS_HOST;
  const clientId = process.env.DATABRICKS_CLIENT_ID;
  const clientSecret = process.env.DATABRICKS_CLIENT_SECRET;
  const endpoint = process.env.ENDPOINT_NAME;

  const cachedWorkspaceToken = cached(() => getWorkspaceToken(host, clientId, clientSecret));
  const cachedPostgresToken = cached(async () => {
    const workspaceToken = await cachedWorkspaceToken();
    return getPostgresCredential(host, workspaceToken, endpoint);
  });

  return new pg.Pool({
    host: process.env.PGHOST,
    port: process.env.PGPORT,
    database: process.env.PGDATABASE,
    user: process.env.PGUSER,
    password: cachedPostgresToken, // Async function: () => Promise<string>
    ssl: { rejectUnauthorized: true },
    min: 1,
    max: 10,
    idleTimeoutMillis: 900000, // Example: 15 minutes
    connectionTimeoutMillis: 60000, // Example: 60 seconds
  });
}

// Use the pool
const pool = createPool();
const result = await pool.query('SELECT current_user, current_database()');
console.log('Connected as:', result.rows[0].current_user);

依存関係:pg (node-postgres)

メモ: Node-postgres (pg) は、非同期関数をパスワードとして受け入れます。 この関数は、新しい接続が作成されるたびに呼び出され、新しいトークンが確保されます。

接続を実行して確認する

curl

環境変数が読み込まれた bash スクリプトを実行します。

export $(cat .env | xargs)
bash connect.sh

想定される出力:

Got workspace OAuth token (60-min lifetime)
Got database credential (60-min lifetime)
     current_user      | current_database
-----------------------+------------------
 c00f575e-d706-4f6b... | databricks_postgres

current_userがサービス プリンシパル クライアント ID と一致する場合、OAuth は正常に動作しています。

Node.js

依存関係をインストールします。

npm install pg

実行:

node app.js

想定される出力:

Connected as: c00f575e-d706-4f6b-b62c-e7a14850571b

メモ: Lakebase Autoscaling が 0 からコンピューティングを開始すると、アイドル後の最初の接続に時間がかかる場合があります。

トラブルシューティング

エラー 修正
"invalid_client" または "クライアント認証がありません" DATABRICKS_CLIENT_IDDATABRICKS_CLIENT_SECRETが正しいことを確認します。 基本認証 (base64 エンコード) を使用します。
"ワークスペース アクセス権を持たないユーザーに対して API が無効になっています" サービス プリンシパルの "ワークスペース アクセス" を有効にします (前提条件)。
"パラメーター値が無効です" / "「endpoint」フィールドが必要です" ステップ2のPOST本文にendpoint形式のパラメーターがprojects/<id>/branches/<id>/endpoints/<id>必ず含まれていることを確認してください。
"ロールが存在しない" か、認証が失敗する SQL を使用して OAuth ロールを作成する (前提条件)。
"接続が拒否されました" またはタイムアウト 0 へのスケール後の最初の接続には、より長い時間がかかる場合があります。 再試行ロジックを実装します。
トークンの有効期限が切れた/ "パスワード認証に失敗しました" ワークスペース トークンとデータベース トークンの両方が 60 分後に期限切れになります。 有効期限チェックを使用してキャッシュを実装します。