# Workspace Identity Demo — Crawl, Walk, Run

**Audience:** Fabric admin or platform engineer running a hands-on demo in a throwaway tenant or sandbox capacity.
**Goal:** Show how a **Workspace Identity (WI)** replaces user-bound credentials for machine-to-machine access in Fabric, and how it composes with the Entra group model from the [Security Briefing](./Fabric_Security_Briefing.md).
**Time:** ~90 minutes end-to-end. Each phase stands alone — stop after Crawl if that is all you need to show.

---

## Where Workspace Identity Fits in the Briefing

The briefing defines **two security tracks**:

| Track | Who/What | Mechanism |
|---|---|---|
| **Human access** | Users | Entra security groups → built-in workspace roles (Viewer/Contributor/Member/Admin) + RLS |
| **Machine access** | Pipelines, refreshes, notebooks, cross-workspace reads, Azure resource calls | **Workspace Identity** — a Fabric-managed service principal owned by the workspace |

A WI is essentially a **scoped, credential-free service principal**. It is created *inside* a workspace, lives and dies with that workspace, can be granted roles on **other** Fabric workspaces and on **Azure** resources (Key Vault, ADLS Gen2, etc.), and authenticates connections without anyone managing a secret. It is the right answer to UC-1, UC-5, UC-7 in the briefing.

**Two facts to keep front-of-mind during the demo:**
1. **Since 27 July 2025** a new WI does **not** automatically get Contributor on its own workspace — you must grant it explicitly. This trips people up.
2. WI is **not** a user. It cannot be added to Entra groups intended for people. Treat the WI list as its own inventory.

---

## Prerequisites

- A Fabric capacity (Trial F-SKU is fine) and **Capacity Admin** rights on it. WI requires a paid SKU or trial — not free Power BI.
- Tenant setting **"Service principals can use Fabric APIs"** enabled, scoped to a security group that includes WIs (or all). Admin Portal → Tenant settings → Developer settings.
- Two empty workspaces you can throw away — name suggestions: `Demo-WI-Source` and `Demo-WI-Target`.
- One Azure subscription with rights to create a Key Vault and a Storage account (only needed for **Run**).
- An Entra security group you control, e.g. `Demo-Fabric-Contributor` (only needed for **Walk**).

---

## CRAWL — Create a WI and prove it works inside Fabric (≈20 min)

**Objective:** Stand up a Workspace Identity, hit the July 2025 gotcha live, and use it to read across workspaces.

### Step C1 — Create the source workspace and a sample lakehouse

1. Create workspace `Demo-WI-Source`, assign to your demo capacity.
2. Add a Lakehouse `lh_demo`. Load any sample table (the built-in **Sample data → Public Holidays** works).

### Step C2 — Create the Workspace Identity

1. In `Demo-WI-Source` → **Workspace settings → Workspace identity → +**.
2. Wait ~30 seconds for provisioning. Fabric creates a hidden Entra service principal named after the workspace.

> **Talking point:** No password, no secret, no expiry. The WI's lifecycle is bound to the workspace — delete the workspace, the identity is gone.

### Step C3 — Hit the gotcha (deliberately)

1. Create the target workspace `Demo-WI-Target`. Add an empty semantic model or a blank report.
2. In `Demo-WI-Target` → **Manage access**, search for the WI by the source workspace's name. It will appear as a service principal.
3. **Do not add it yet.** First try to build a cross-workspace connection from `Demo-WI-Target` back to `lh_demo` using **Workspace Identity** auth. It will fail with an authorization error.
4. Now go back to `Demo-WI-Target` → Manage access and grant the source WI **Viewer**. Retry — it works.

> **Talking point:** This is exactly UC-1 from the briefing. The fix is one Manage-Access add, not a new credential.

### Step C4 — Show the audit trail

1. Trigger a manual refresh of the semantic model in `Demo-WI-Target` (which now reads via the WI).
2. Admin Portal → **Audit logs** (or M365 Compliance) → filter by workspace.
3. Show that the action initiator is the **WI's service principal object ID**, distinct from any human user.

> **Talking point:** This is why the briefing keeps WI and human-group tracks separate — they show up differently in audit and need different governance.

**Stop here** if the audience just needs to understand the primitive.

---

## WALK — Compose WI with Entra groups (≈30 min)

**Objective:** Demonstrate the briefing's two-layer model: humans via groups, machines via WI, side by side on the same workspace.

### Step W1 — Add the Entra group for human access

1. In Entra: confirm `Demo-Fabric-Contributor` exists and contains one test user (not yourself).
2. In `Demo-WI-Target` → Manage access → add the **group** as Contributor. Do **not** add the user directly.
3. Sign in as the test user in a private browser window → confirm they can open and edit the report.

### Step W2 — Show that audit still resolves to the individual

1. Have the test user save a trivial change to the report.
2. Back in your admin session, refresh the audit log filter.
3. Point out: the entry shows the **named user**, not the group. This is the briefing's auditability concern, mitigated.

### Step W3 — Layer WI access on the same workspace

1. The source WI is already a Viewer on `Demo-WI-Target` from Crawl.
2. Show the Manage Access pane: humans-via-group **and** the WI coexist with different roles.
3. Make the point that removing the human user from the group instantly revokes their access — no per-workspace cleanup — while the WI is untouched.

### Step W4 — Demonstrate the briefing's Prod-Admin restriction pattern

1. Create a second group `Demo-Fabric-Prod-Admin` containing only you.
2. In `Demo-WI-Target`, treat it as "Prod": remove all Admin assignments except this group.
3. Try to change workspace settings as the test user — denied. As the Prod-Admin user — allowed.
4. Tie back to UC-4: same Viewer/Contributor everywhere, **Admin tightly scoped in Prod**.

> **Talking point:** Onboarding a new analyst is now one group membership change in Entra, propagated by Fabric within minutes. Offboarding is the same single action.

---

## RUN — WI reaches into Azure, governed by Entra groups (≈45 min)

**Objective:** Show the full UC-5 pattern *the right way*: the WI never gets a direct role assignment on an Azure resource. Instead, **Entra security groups** hold the Azure RBAC, and the WI inherits access by group membership. This is the same group-driven model the briefing applies to humans, applied to machines.

> **Why this matters:** Direct principal-to-resource grants are how IAM clutter starts. When the workspace is later deleted, every direct assignment becomes an orphaned SID in Azure. With group-based grants, removing the WI from the group is one action and the resource ACLs stay clean.

### Step R1 — Stand up the Azure side

1. Create a resource group `rg-fabric-wi-demo`.
2. Inside it: a Key Vault `kv-fabricwidemo-<initials>` and a Storage account `stfabricwidemo<initials>` with a container `bronze` and hierarchical namespace enabled (ADLS Gen2).
3. Drop one small CSV into the `bronze` container.
4. Add one secret to the Key Vault, e.g. `demo-api-key` = `hello-from-kv`.

### Step R2 — Create the Entra groups that *own the access*

Create two **security groups** in Entra (not M365 groups — Azure RBAC and Fabric pipeline admin both reject M365 groups):

| Group | Purpose | Will hold |
|---|---|---|
| `Fabric-WI-KV-Readers` | Anyone (human or WI) allowed to read demo Key Vault secrets | The Key Vault role |
| `Fabric-WI-Lake-Readers` | Anyone allowed to read the `bronze` container | The Storage role |

> **Talking point:** Notice the groups are named after **what they grant**, not after a workspace. One group can serve many WIs across many workspaces — that is the point.

### Step R3 — Grant Azure RBAC to the *groups*, not the WI

1. Key Vault → **Access control (IAM)** → add role assignment **Key Vault Secrets User** → assign to **group** `Fabric-WI-KV-Readers`.
2. Storage account → **Access control (IAM)** → add role assignment **Storage Blob Data Reader** → assign to **group** `Fabric-WI-Lake-Readers`.

The WI is not mentioned anywhere in Azure yet.

### Step R4 — Add the Workspace Identity to the groups

1. In Entra, open `Fabric-WI-KV-Readers` → Members → Add.
2. Search for the WI by the source workspace's name. It appears as a service principal. Add it.
3. Repeat for `Fabric-WI-Lake-Readers`.

> **Talking point:** This is the only step that ties this specific WI to these permissions. To revoke later, you remove it from the group — no Azure portal trip required.

### Step R5 — Prove it works from a notebook

1. In `Demo-WI-Source`, create a notebook.
2. Create a connection of type **Azure Data Lake Storage Gen2**, auth = **Workspace Identity**, point at the `bronze` container.
3. Read the CSV with Spark. It works — the WI authenticated, Azure resolved the group, the group held the role.
4. In the same notebook, retrieve `demo-api-key` from Key Vault via the WI. It works for the same reason.

### Step R6 — Demonstrate group-based revocation

1. In Entra, remove the WI from `Fabric-WI-Lake-Readers`.
2. Wait ~5 minutes for token cache to expire (or restart the Spark session).
3. Rerun the lakehouse read — denied. The Key Vault read still works because the WI is still in the other group.
4. Re-add the WI to the group. Access returns.

> **Talking point:** One Entra action, two clean outcomes — finely scoped, fully audited, no Azure portal involvement. Compare this to revoking a direct role assignment, which would require an Azure admin and leave an audit gap in Entra.

### Step R7 — Tear-down: show the cleanliness payoff

1. Delete `Demo-WI-Source`. The WI vanishes from Entra and is automatically removed from both groups.
2. Open the Key Vault and Storage account IAM blades. **No orphaned principals.** The role assignments still point to clean, living groups.
3. **Talking point for governance:** this is the briefing's WI provisioning checklist made durable — the checklist is "add the WI to the right groups," and deprovisioning is automatic when the workspace dies. The Azure RBAC surface area stays stable regardless of workspace churn.

---

## Demo Wrap-Up Cheat Sheet

| Asked During Demo | Crisp Answer |
|---|---|
| "Why not just use a service principal?" | WI is one; you do not manage its credentials, and its scope is the workspace, which matches how Fabric thinks about isolation. |
| "Can a WI be in an Entra group?" | Yes — and the Run phase shows why you should. Keep WI groups *separate* from human groups, but use the same group-driven pattern for both. |
| "What replaces it if the workspace is deleted?" | Nothing — by design. Recreate the workspace, recreate the WI, add it back to the same Entra groups. Azure RBAC never changes. |
| "Does Microsoft recommend WI in Prod?" | Yes — per Fabric security baseline, WI is the recommended auth for production connections. User-based auth stays acceptable in Dev/Test for traceability. |
| "Where is the gotcha documented?" | Microsoft Learn workspace-identity page — change dated 27 July 2025: no default Contributor for new WIs. |

---

## Cleanup

1. Delete both demo workspaces in Fabric.
2. Delete `rg-fabric-wi-demo` in Azure (removes Key Vault, Storage, and orphaned role assignments in one shot).
3. Remove the demo Entra groups if they were created fresh for this exercise.

---

*Companion to `Fabric_Security_Briefing.md`. Use this when you need to show — not just describe — how Workspace Identity makes the briefing's machine-access track real.*
