Un notebook Fabric qui appelle une API a besoin de deux choses : un secret (stocké dans Azure Key Vault) et un jeton d’accès. Les deux passent par notebookutils.credentials. Ce billet teste ses fonctions une par une.
Vérifié en lab en septembre 2026, dans un notebook PySpark, avec un compte qui a le rôle Key Vault Secrets Officer sur le coffre.
1. Ce que la bibliothèque annonce
Premier réflexe : demander à Fabric ce qui existe.
notebookutils.credentials.help()
Trois fonctions annoncées :
| Fonction | Rôle |
|---|---|
getToken(audience) | Obtenir un jeton d’accès pour un service |
getSecret(akvVaultUri, secret) | Lire un secret Key Vault, avec l’identité de l’utilisateur |
getSecretWithConnection(connectionId, secret) | Lire un secret via une connexion Fabric |
2. getSecret : l’URL, pas le nom
kv_uri = "https://kv-techniir-lab-weu-001.vault.azure.net/"
kv_name = "kv-techniir-lab-weu-001"
user = notebookutils.credentials.getSecret(kv_uri, "sqldb-adventureworks-admin-user") # fonctionne
user2 = notebookutils.credentials.getSecret(kv_name, "sqldb-adventureworks-admin-user") # échoue
- Avec l’URL complète, le secret est lu.
printaffiche[REDACTED]: Fabric masque la valeur dans la sortie. - Avec le nom seul du coffre :
AkvHttpClientException: Invalid vault uri.
Attention au [REDACTED] : c’est un filet de sécurité, pas une protection. La variable contient bien la valeur en clair. Ne jamais afficher un secret.
3. putSecret : absent de l’aide, mais présent, et refusé
help() ne liste pas putSecret. La fonction existe pourtant : l’appel ne renvoie pas fonction inconnue, il part vers le service et revient en erreur.
notebookutils.credentials.putSecret(kv_uri, "test-value-putsecret", "valeur-de-test")
Résultat : 403, renvoyé par le Token Service, alors que le compte a le rôle Secrets Officer, qui autorise l’écriture. D’après le message, le refus ne vient donc pas des droits Key Vault.
À retenir : un notebook lit les secrets, il ne les écrit pas. L’écriture se fait côté Azure : portail, CLI, ou infrastructure as code.
4. getToken : appeler une API avec son propre jeton
import requests
token = notebookutils.credentials.getToken("pbi")
print("Longueur du jeton :", len(token))
resp = requests.get(
"https://api.powerbi.com/v1.0/myorg/groups",
headers={"Authorization": f"Bearer {token}"}
)
print("Code HTTP :", resp.status_code)
for ws in resp.json().get("value", [])[:5]:
print(ws["name"])
Une ligne suffit pour obtenir un jeton, et l’API répond 200 avec la liste des workspaces. Deux bonnes pratiques au passage : on affiche la longueur du jeton, jamais le jeton lui-même ; et ce jeton est celui de l’utilisateur : l’API renvoie tous les workspaces auxquels il a accès.
5. Service principal : secrets dans Key Vault, jeton d’application
Pour un traitement automatisé, on ne veut pas dépendre du compte d’une personne. On utilise un service principal, dont les identifiants sont rangés dans Key Vault :
import requests
kv_uri = "https://kv-techniir-lab-bicep.vault.azure.net/"
tenant_id = notebookutils.credentials.getSecret(kv_uri, "entra-tenant-id")
client_id = notebookutils.credentials.getSecret(kv_uri, "sp-fabric-app-id")
resp = requests.post(
f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token",
data={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": notebookutils.credentials.getSecret(kv_uri, "sp-fabric-app-secret"),
"scope": "https://analysis.windows.net/powerbi/api/.default",
},
)
app_token = resp.json().get("access_token", "")
print("Jeton d'application obtenu :", len(app_token) > 0)
groups = requests.get(
"https://api.powerbi.com/v1.0/myorg/groups",
headers={"Authorization": f"Bearer {app_token}"}
)
print(groups.status_code, [g["name"] for g in groups.json().get("value", [])])
Même API, résultat différent : le service principal ne voit que deux workspaces (ws_dp700_sandbox et ws_dp700_sandbox_test), là où l’utilisateur en voyait davantage. Le jeton d’application ne donne accès qu’aux workspaces où le service principal a été ajouté. C’est exactement ce qu’on veut : le traitement n’a que les droits dont il a besoin.
Le secret du service principal n’est jamais stocké dans une variable affichée : il est lu dans Key Vault et passé directement à la requête.
À retenir
getSecretattend l’URL complète du coffre, pas son nom.[REDACTED]n’est pas une protection : ne jamais afficher un secret ni un jeton.putSecretn’est pas dans l’aide et échoue en403: un notebook lit les secrets, il ne les écrit pas.getTokendonne un jeton utilisateur : il voit tout ce que l’utilisateur voit.- Un service principal dont les identifiants sont dans Key Vault ne voit que les workspaces où il a été ajouté.
À lire aussi : Key Vault en mode RBAC : le piège du premier secret pour créer le coffre et attribuer les rôles.