Connectez une application externe à Lakebase à l'aide de l'API
Ce guide montre comment connecter des applications externes à Lakebase Autoscaling à l'aide d'appels d'API REST directs. Utilisez cette approche lorsqu'un SDK Databricks n'est pas disponible pour votre langue (Node.js, Ruby, PHP, Elixir, Rust, etc.).
Si votre langage prend en charge le SDK (Python, Java ou Go), utilisez plutôt Connecter une application externe à Lakebase à l'aide du SDK pour une gestion simplifiée des tokens.
Vous effectuez deux appels d'API pour obtenir des informations d'identification de base de données avec la rotation des jetons OAuth. Des exemples sont fournis pour curl et Node.js.
Authentification en deux étapes : Cette approche nécessite deux appels d'API pour chaque identifiant de base de données : (1) échanger le secret du Service Principal contre un jeton OAuth de workspace, (2) échanger le jeton OAuth contre un identifiant de base de données. Les deux jetons expirent après 60 minutes. Le SDK gère automatiquement l'étape 1.
Prérequis
Vous avez besoin de la même configuration que l'approche SDK : Service Principal, rôle Postgres et détails de connexion.
Prérequis | Détail clé | Plus d'informations |
|---|---|---|
Service Principal | Secret OAuth avec une durée de vie maximale de 730 jours ; activez l' accès au Workspace . Notez l' ID client (UUID) pour le rôle Postgres et les variables d'environnement. | |
Rôle Postgres | Créez un rôle OAuth dans l'éditeur SQL Lakebase : | |
Détails de la connexion | Depuis la console Lakebase **Connecter** : **nom d'Endpoint** |
Comment cela fonctionne
L'approche API manuelle nécessite deux échanges de jetons :

Durées de vie des jetons :
- Secret de Service Principal : Jusqu'à 730 jours (défini lors de la création)
- Jeton OAuth Workspace : 60 minutes (étape 1)
- Identifiant de base de données : 60 minutes (étape 2)
Définition du périmètre des jetons : Les informations d'identification de la base de données sont limitées au Workspace. Bien que le parameter endpoint soit requis, le jeton renvoyé peut accéder à n'importe quelle base de données ou projet dans le Workspace pour lequel le Service Principal dispose des autorisations.
Définir les variables d'environnement
Définissez ces variables d'environnement avant d'exécuter votre application :
# 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>.cloud.databricks.com"
export PGDATABASE="databricks_postgres"
export PGUSER="<service-principal-client-id>" # Same UUID as client ID
export PGPORT="5432"
Ajouter un code de connexion
- curl
- Node.js
Cet exemple montre les appels d'API bruts. Pour les applications de production, implémentez la mise en cache de jetons et la logique de refresh.
# 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()"
Cet exemple utilise node-postgres avec une fonction de mot de passe asynchrone qui gère la récupération et la mise en cache des jetons.
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);
Dépendances : pg (node-postgres)
**Remarque :** Node-postgres ()pg accepte une fonction asynchrone comme mot de passe. La fonction est appelée chaque fois qu'une nouvelle connexion est créée, garantissant des jetons à jour.
Exécuter et vérifier la connexion
- curl
- Node.js
Exécutez le script bash avec les variables d'environnement chargées :
export $(cat .env | xargs)
bash connect.sh
Sortie attendue :
Got workspace OAuth token (60-min lifetime)
Got database credential (60-min lifetime)
current_user | current_database
-----------------------+------------------
c00f575e-d706-4f6b... | databricks_postgres
Si current_user correspond à l’ID client de votre Service Principal, OAuth fonctionne correctement.
Installer les dépendances :
npm install pg
Exécuter :
node app.js
Sortie attendue :
Connected as: c00f575e-d706-4f6b-b62c-e7a14850571b
Note: La première connexion après inactivité peut prendre plus de temps, car le dimensionnement automatique de Lakebase start le compute à partir de zéro.
Dépannage
Erreur | Corriger |
|---|---|
« invalid_client » ou « Missing client authentication » | Vérifiez que |
« L'API est désactivée pour les utilisateurs sans droit d'accès au workspace » | Activez l'accès au « Workspace » pour le Service Principal (conditions préalables). |
« INVALID_PARAMETER_VALUE » / « Le champ 'endpoint' est requis » | Assurez-vous que le parameter |
« Le rôle n'existe pas » ou l'authentification échoue | Créez un rôle OAuth via SQL (prérequis). |
« Connexion refusée » ou délai d'attente | La première connexion après une mise à l'échelle à zéro peut prendre plus de temps. Mettez en œuvre la logique de nouvelle tentative. |
Jeton expiré / "authentification par mot de passe échouée" | Les jetons Workspace et de base de données expirent tous deux après 60 minutes. Mettez en œuvre la mise en cache avec des contrôles d'expiration. |