Aller au contenu principal

Qu'est-ce que l'embedding pour les utilisateurs externes ?

Cette page décrit le fonctionnement de l'intégration pour les utilisateurs externes, comment configurer votre workspace Databricks pour un partage sécurisé des tableaux de bord intégrés, et comment utiliser des exemples d'applications pour start. L'intégration pour les utilisateurs externes utilise un Service Principal et des jetons d'accès à étendue limitée pour authentifier et autoriser l'accès aux tableaux de bord intégrés. Cette approche vous permet de partager des tableaux de bord avec des spectateurs en dehors de votre organisation, tels que les Partenaires et les clients, sans le provisionnement de comptes Databricks pour ces utilisateurs.

Pour en savoir plus sur les autres options d'intégration, y compris l'intégration de tableaux de bord pour les utilisateurs de votre organisation, voir Intégrer un tableau de bord.

Fonctionnement de l'intégration pour les utilisateurs externes

Le diagramme et les étapes numérotées ci-dessous expliquent comment les utilisateurs sont authentifiés et comment les tableaux de bord sont renseignés avec des résultats propres à l'utilisateur lorsque vous intégrez un tableau de bord pour des utilisateurs externes.

Un organigramme montrant les échanges de jetons nécessaires entre votre application et le Workspace Databricks.

  1. Authentification et requête de l'utilisateur : l'utilisateur se connecte à votre application. L'interface front-end de votre application envoie une requête authentifiée à votre serveur pour un jeton d'accès au tableau de bord.
  2. Authentification Service Principal : Votre serveur utilise le secret du service principal pour demander et recevoir un jeton OAuth du serveur Databricks. Il s’agit d’un jeton à portée étendue qui peut appeler toutes les APIs de tableau de bord auxquelles Databricks a accès au nom du Service Principal. Votre serveur appelle l’ /tokeninfo endpoint en utilisant ce jeton, en transmettant des informations utilisateur de base, telles que external_viewer_id et external_value. Voir Présenter en toute sécurité des tableaux de bord à des utilisateurs individuels.
  3. Génération de jetons spécifiques à l'utilisateur : À l'aide de la réponse du /tokeninfo endpoint et du Databricks OpenID Connect (OIDC) endpoint, votre serveur génère un nouveau jeton à portée restreinte qui encode les informations utilisateur que vous avez transmises.
  4. Rendu du tableau de bord et filtrage des données : La page de l'application instancie DatabricksDashboard de @databricks/aibi-client et transmet le jeton délimité par l'utilisateur pendant la construction. Le tableau de bord s'affiche avec le contexte de l'utilisateur. Ce jeton autorise l'accès, prend en charge l'audit avec external_viewer_id et transporte external_value pour le filtrage des données. Les query dans les dataset du tableau de bord peuvent référencer __aibi_external_value pour appliquer des filtres par utilisateur, garantissant que chaque spectateur ne voit que les données qu’il est autorisé à consulter.

Ask Genie n'est pas disponible dans l'intégration externe

Le bouton Ask Genie n'est pas pris en charge en intégration pour les utilisateurs externes. Si vous souhaitez fournir des capacités d'interrogation de données en langage naturel aux utilisateurs externes, utilisez plutôt l'API Genie Conversation. L'API Conversation vous permet d'intégrer la fonctionnalité Genie à votre application par programmation, indépendamment de l'intégration du tableau de bord.

Pour les tableaux de bord intégrés avec une intégration de base, Ask Genie est disponible. Voir Ask Genie dans les tableaux de bord intégrés.

Présentez les tableaux de bord en toute sécurité aux utilisateurs individuels.

Configurez votre serveur d'applications pour générer un jeton unique par utilisateur, basé sur son external_viewer_id. Cela vous permet de suivre les vues et l'utilisation du tableau de bord via les Logs d'audit. Le external_viewer_id est associé à un external_value, qui agit comme une variable globale pouvant être insérée dans les requêtes SQL utilisées dans les datasets des tableaux de bord. Cela vous permet de filtrer les données affichées sur le tableau de bord pour chaque utilisateur.

external_viewer_id est transmise à vos logs d'audit de tableau de bord et ne doit pas inclure d'informations personnellement identifiables. Cette valeur doit également être unique par utilisateur.

external_value est utilisé dans le traitement des query et peut inclure des informations personnelles identifiables (PII).

remarque

La taille combinée de external_viewer_id et external_value ne doit pas dépasser 1 Ko.

L'exemple suivant montre comment utiliser la valeur externe comme filtre dans les queries de dataset :

SQL
SELECT *
FROM sales
WHERE region = __aibi_external_value

Aperçu de la configuration

Cette section comprend une vue d'ensemble conceptuelle de haut niveau des étapes que vous devez effectuer pour configurer l'intégration d'un tableau de bord dans un emplacement externe.

Pour intégrer un tableau de bord dans une application externe, vous créez d'abord un Service Principal dans Databricks et générez un secret. Le Service Principal doit bénéficier d'un accès en lecture au tableau de bord et à ses données sous-jacentes. Votre serveur utilise le secret de Service Principal pour récupérer un jeton qui peut accéder aux APIs du tableau de bord au nom du Service Principal. Avec ce jeton, le serveur appelle l'Endpoint d'API /tokeninfo, un Endpoint OpenID Connect (OIDC) qui renvoie les informations de profil utilisateur de base, y compris les valeurs external_value et external_viewer_id. Ces valeurs vous permettent d'associer des requêtes à des utilisateurs individuels.

À l'aide du jeton obtenu du Service Principal, votre serveur génère un nouveau jeton limité à l'utilisateur spécifique qui accède au tableau de bord. Ce jeton, limité à l'utilisateur, est transmis à la page de l'application, où l'application instancie l'objet DatabricksDashboard à partir de la bibliothèque @databricks/aibi-client. Le jeton contient des informations spécifiques à l'utilisateur qui prennent en charge l'audit et appliquent un filtrage afin que chaque utilisateur ne voie que les données auxquelles il est autorisé à accéder. Du point de vue de l'utilisateur, la connexion à l'application fournit automatiquement l'accès au tableau de bord intégré avec la visibilité des données correcte.

Limites de débit et considérations sur les performances

L’intégration externe a une limite de débit de 20 chargements de tableau de bord par seconde. Vous pouvez ouvrir plus de 20 tableaux de bord à la fois, mais pas plus de 20 ne peuvent start à se charger simultanément.

Prérequis

Pour implémenter l'intégration externe, assurez-vous de satisfaire aux prérequis suivants :

Étape 1 : Créer un Service Principal

Créez un Service Principal pour qu'il agisse en tant qu'identité de votre application externe au sein de Databricks. Ce Service Principal authentifie les requêtes au nom de votre application.

Pour créer un Service Principal :

  1. En tant qu’administrateur de workspace, connectez-vous au workspace Databricks.
  2. Cliquez sur votre nom d'utilisateur dans la barre supérieure du workspace Databricks et sélectionnez **Paramètres**.
  3. Cliquez sur Identité et accès dans le volet de gauche.
  4. À côté de **Service principals**, cliquez sur **Gérer**.
  5. Cliquez sur Ajouter un Service Principal .
  6. Cliquez sur Ajouter nouveau .
  7. Saisissez un nom descriptif pour le Service Principal.
  8. Cliquez sur **Ajouter**.
  9. Ouvrez le Service Principal que vous venez de créer à partir de la page de liste Service principals . Utilisez le champ de saisie de texte Filtre pour le rechercher par nom, si nécessaire.
  10. Sur la page Détails du Service Principal , enregistrez l' ID d'application . Vérifiez que les cases à cocher Databricks SQL access et Workspace access sont sélectionnées.

Étape 2 : Créer un secret OAuth

Générez un secret pour le Service Principal et collectez les valeurs de configuration suivantes : vous en aurez besoin pour votre application externe.

  • ID client de Service Principal
  • Secret du client

Le Service Principal utilise un secret OAuth pour vérifier son identité lors de la demande d'un jeton d'accès à votre application externe.

Pour générer un secret :

  1. Cliquez sur Secrets sur la page Détails du Service Principal .
  2. Cliquez sur Générer le secret .
  3. Saisissez une valeur vie client pour le nouveau secret en jours (par exemple, entre 1 et 730 jours).
  4. Copiez immédiatement le secret. Vous ne pouvez pas afficher ce secret à nouveau après avoir quitté cet écran.

Étape 3 : attribuez des autorisations à votre Service Principal

Le Service Principal que vous avez créé agit comme l'identité qui fournit l'accès au tableau de bord via votre application. Ses autorisations s'appliquent uniquement si le tableau de bord n'est pas publié avec des autorisations de partage de données. Si les autorisations de partage de données sont utilisées, les informations d’identification de l’éditeur accèdent aux données. Pour plus de détails et de recommandations, consultez l’intégration des approches d’authentification.

  1. Cliquez sur Tableaux de bord dans la barre latérale du workspace pour ouvrir la page de liste des tableaux de bord.
  2. Cliquez sur le nom du tableau de bord que vous souhaitez intégrer. Le tableau de bord publié s'ouvre.
  3. Cliquez sur « Partager » .
  4. Utilisez le champ de saisie de texte de la boîte de dialogue Partage pour trouver votre Service Principal, puis cliquez dessus. Définissez le niveau d'autorisation sur CAN RUN . Ensuite, cliquez sur Ajouter .
  5. Notez l' ID du tableau de bord . Vous pouvez trouver l'ID du tableau de bord dans l'URL du tableau de bord (par exemple, https://<your-workspace-url>/dashboards/<dashboard-id>). Consultez les détails du Databricks workspace.
remarque

Si vous publiez un tableau de bord avec des autorisations de données individuelles, vous devez accorder à votre Service Principal l'accès aux données utilisées dans le tableau de bord. L'accès au compute utilise toujours les informations d'identification de l'éditeur, vous n'avez donc pas besoin d'accorder des autorisations de compute au Service Principal.

Pour lire et afficher les données, le Service Principal doit disposer d'au moins SELECT privilèges sur les tables et vues référencées dans le tableau de bord. Consultez Qui peut gérer les privilèges ?.

Étape 4 : Utilisez l'application exemple pour vous authentifier et générer des jetons.

Utilisez une application d'exemple pour vous entraîner à l'intégration externe de votre tableau de bord. Les applications comprennent des instructions et du code qui initient l’échange de jetons nécessaire pour générer des jetons de portée. Les blocs de code suivants n'ont aucune dépendance. Copiez et enregistrez une des applications suivantes.

Copiez et enregistrez ceci dans un fichier nommé example.py.

Python
#!/usr/bin/env python3

import os
import sys
import json
import base64
import urllib.request
import urllib.parse
from http.server import HTTPServer, BaseHTTPRequestHandler

# -----------------------------------------------------------------------------
# Config
# -----------------------------------------------------------------------------
CONFIG = {
"instance_url": os.environ.get("INSTANCE_URL"),
"dashboard_id": os.environ.get("DASHBOARD_ID"),
"service_principal_id": os.environ.get("SERVICE_PRINCIPAL_ID"),
"service_principal_secret": os.environ.get("SERVICE_PRINCIPAL_SECRET"),
"external_viewer_id": os.environ.get("EXTERNAL_VIEWER_ID"),
"external_value": os.environ.get("EXTERNAL_VALUE"),
"workspace_id": os.environ.get("WORKSPACE_ID"),
"port": int(os.environ.get("PORT", 3000)),
}

basic_auth = base64.b64encode(
f"{CONFIG['service_principal_id']}:{CONFIG['service_principal_secret']}".encode()
).decode()

# -----------------------------------------------------------------------------
# HTTP Request Helper
# -----------------------------------------------------------------------------
def http_request(url, method="GET", headers=None, body=None):
headers = headers or {}
if body is not None and not isinstance(body, (bytes, str)):
raise ValueError("Body must be bytes or str")

req = urllib.request.Request(url, method=method, headers=headers)
if body is not None:
if isinstance(body, str):
body = body.encode()
req.data = body

try:
with urllib.request.urlopen(req) as resp:
data = resp.read().decode()
try:
return {"data": json.loads(data)}
except json.JSONDecodeError:
return {"data": data}
except urllib.error.HTTPError as e:
raise RuntimeError(f"HTTP {e.code}: {e.read().decode()}") from None

# -----------------------------------------------------------------------------
# Token logic
# -----------------------------------------------------------------------------
def get_scoped_token():
# 1. Get all-api token
oidc_res = http_request(
f"{CONFIG['instance_url']}/oidc/v1/token",
method="POST",
headers={
&quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;,
&quot;Authorization&quot;: f&quot;Basic {basic_auth}&quot;,
},
body=urllib.parse.urlencode({
"grant_type": "client_credentials",
"scope": "all-apis"
})
)
oidc_token = oidc_res["data"]["access_token"]

# 2. Get token info
token_info_url = (
f"{CONFIG['instance_url']}/api/2.0/lakeview/dashboards/"
f"{CONFIG['dashboard_id']}/published/tokeninfo"
f"?external_viewer_id={urllib.parse.quote(CONFIG['external_viewer_id'])}"
f"&external_value={urllib.parse.quote(CONFIG['external_value'])}"
)
token_info = http_request(
token_info_url,
headers={&quot;Authorization&quot;: f&quot;Bearer {oidc_token}&quot;}
)["data"]

# 3. Generate scoped token
params = token_info.copy()
authorization_details = params.pop("authorization_details", None)
params.update({
"grant_type": "client_credentials",
"authorization_details": json.dumps(authorization_details)
})

scoped_res = http_request(
f"{CONFIG['instance_url']}/oidc/v1/token",
method="POST",
headers={
&quot;Content-Type&quot;: &quot;application/x-www-form-urlencoded&quot;,
&quot;Authorization&quot;: f&quot;Basic {basic_auth}&quot;,
},
body=urllib.parse.urlencode(params)
)
return scoped_res["data"]["access_token"]

# -----------------------------------------------------------------------------
# HTML generator
# -----------------------------------------------------------------------------
def generate_html(token):
return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard Demo</title>
<style>
body {{ font-family: system-ui; margin: 0; padding: 20px; background: #f5f5f5; }}
.container {{ max-width: 1200px; margin: 0 auto; height:calc(100vh - 40px) }}
</style>
</head>
<body>
<div id="dashboard-content" class="container"></div>
<script type="module">
import {{ DatabricksDashboard }} from "https://cdn.jsdelivr.net/npm/@databricks/aibi-client@0.0.0-alpha.7/+esm";
const dashboard = new DatabricksDashboard({{
instanceUrl: "{CONFIG['instance_url']}",
workspaceId: "{CONFIG['workspace_id']}",
dashboardId: "{CONFIG['dashboard_id']}",
token: "{token}",
container: document.getElementById("dashboard-content")
}});
dashboard.initialize();
</script>
</body>
</html>"""

# -----------------------------------------------------------------------------
# HTTP server
# -----------------------------------------------------------------------------
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/":
self.send_response(404)
self.send_header("Content-Type", "text/plain")
self.end_headers()
self.wfile.write(b"Not Found")
return

try:
token = get_scoped_token()
html = generate_html(token)
status = 200
except Exception as e:
html = f"<h1>Error</h1><p>{e}</p>"
status = 500

self.send_response(status)
self.send_header("Content-Type", "text/html")
self.end_headers()
self.wfile.write(html.encode())

def start_server():
missing = [k for k, v in CONFIG.items() if not v]
if missing:
print(f"Missing: {', '.join(missing)}", file=sys.stderr)
sys.exit(1)

server = HTTPServer(("localhost", CONFIG["port"]), RequestHandler)
print(f":rocket: Server running on http://localhost:{CONFIG['port']}")
try:
server.serve_forever()
except KeyboardInterrupt:
sys.exit(0)

if __name__ == "__main__":
start_server()

Étape 5 : exécutez l’exemple d’application

Remplacez les valeurs suivantes, puis exécutez le bloc de code depuis votre terminal. Vos valeurs ne doivent pas être entourées de chevrons (< >) :

  • Utilisez l' URL du Workspace pour rechercher et remplacer les valeurs suivantes :

    • <your-instance>
    • <workspace_id>
    • <dashboard_id>
  • Remplacez les valeurs suivantes par celles que vous avez créées lors de la création du service principal (étape 2) :

    • <service_principal_id>
    • <service_principal_secret> (secret client)
  • Remplacez les valeurs suivantes par des identifiants associés aux utilisateurs de l'application externe :

    • <some-external-viewer>
    • <some-external-value>
  • Remplacez </path/to/example> par le chemin d'accès au fichier .py ou .js que vous avez créé à l'étape précédente. Incluez l'extension de fichier.

remarque

Ne pas inclure d'informations personnelles identifiables (PII) dans la valeur EXTERNAL_VIEWER_ID.

Bash

INSTANCE_URL='https://<your-instance>.databricks.com' \
WORKSPACE_ID='<workspace_id>' \
DASHBOARD_ID='<dashboard_id>' \
SERVICE_PRINCIPAL_ID='<service-principal-id>' \
SERVICE_PRINCIPAL_SECRET='<service-principal_secret>' \
EXTERNAL_VIEWER_ID='<some-external-viewer>' \
EXTERNAL_VALUE='<some-external-value>' \
~</path/to/example>

# Terminal will output: :rocket: Server running on http://localhost:3000

Options de configuration

Lorsque vous initialisez DatabricksDashboard, vous pouvez transmettre un objet config pour personnaliser l'apparence et le comportement du tableau de bord intégré. L'objet config requiert un champ version défini sur 1.

Masquer le logo Databricks

Par default, les tableaux de bord intégrés affichent un logo **Propulsé par Databricks** dans le pied de page. Pour masquer le logo, définissez hideDatabricksLogo: true dans l'objet config.

JavaScript
const dashboard = new DatabricksDashboard({
instanceUrl: '<your-instance>.databricks.com',
workspaceId: '<workspace_id>',
dashboardId: '<dashboard_id>',
token: '<scoped-token>',
container: document.getElementById('dashboard-content'),
config: {
version: 1,
hideDatabricksLogo: true,
},
});
dashboard.initialize();

Data download in external embedding

Par default, les visualiseurs de tableaux de bord intégrés peuvent download des données au format CSV, TSV ou Excel, et download des visualisations au format PNG. Pour désactiver le download de données sur votre Workspace, un administrateur de Workspace peut désactiver le paramètre de download dans la console d'administration du Workspace.