Skip to content

The workspace-identity handshake

The deepest integration between the two emulators, reproducing Fabric’s workspace identity feature (fabric-docs/docs/security/workspace-identity.md): a workspace gets its own Entra service principal, auto-managed, whose credential no customer ever holds.

Method + pathNotes
POST /v1/workspaces/{id}/provisionIdentityAdmin-only, 202 LRO
POST /v1/workspaces/{id}/deprovisionIdentityAdmin-only, 202 LRO

Once provisioned, the workspace shape carries workspaceIdentity: { applicationId, servicePrincipalId }.

  • entra-emulator owns the identity: the app registration + service principal, its state machine (Active/Provisioning/Failed/Deprovisioning, only Active mints), the internal token mint (GET /fabric/workspaceidentities/{id}/token), and the Retrieved Fabric Identity Token for Workspace audit event.
  • fabric-emulator owns the orchestration: it drives entra’s admin API over plain HTTP (internal/entra client; origin derived from the configured issuer, honoring FABRIC_ENTRA_TLS_INSECURE) and keeps the lifecycle glued to the workspace:
    • rename follows — renaming the workspace renames the identity;
    • delete cascades — deleting the workspace deprovisions the identity;
    • RBAC grant-back — the provisioned SP is granted Admin on its own workspace, so tokens entra mints for it are honored right back here; deprovisioning revokes the grant.

No shared code or process — the same HTTP calls would work against any implementation of those endpoints.

Reaching a protected resource: Azure Key Vault

Section titled “Reaching a protected resource: Azure Key Vault”

This is what the handshake is for. Its canonical case — a Fabric item needs to reach a protected resource as the workspace, not as a user — is now realised against the family’s third member, azure-keyvault-emulator. Key Vault is a relying party that trusts the same entra issuer: it validates every bearer against entra’s JWKS with the vault audience (https://vault.azure.net), exactly as the control plane and the OneLake data plane do. Key Vault didn’t change the identity model — it’s the clearest instance of it.

A vault-backed credential (keyReference and its siblings) resolves its secret with the workspace identity of the AzureKeyVault connection it points at — no user, no stored credential:

It is the same mint as the loop above (GET …/workspaceidentities/{id}/token), only with the vault audience. Two consumers ride this trust edge:

  • fabric-emulator — resolving a KeyVaultSecretReference with the workspace-identity token (internal/akv; the referenced AzureKeyVault connection must carry a provisioned identity).
  • notebook codenotebookutils.credentials.getSecret(vault, name) in the Python shim, using the notebook’s own vault-audience token.

Both WorkspaceIdentity-type connection credentials and Azure Key Vault references — once planned on top of this — are now shipped.

The pattern under test in real life is: a Fabric item needs to reach a protected resource as the workspace, not as a user. With the family running you can exercise the full credential-less loop offline — provision, mint, reach Key Vault (or Fabric RBAC), deprovision, watch access die — deterministically and in CI (the e2e does exactly this; see the e2e matrix).