Security and Permissions¶
The security section of fabric.yml manages workspace role assignments, OneLake data access roles, and row-level and column-level security. fab-bundle resolves Entra ID display names to GUIDs at deploy time, so you can write human-readable YAML instead of opaque identifiers.
Workspace roles¶
Fabric workspaces have four built-in roles:
| Role | Capabilities |
|---|---|
| Admin | Full control. Manage access, delete the workspace, configure settings. |
| Member | Create, edit, and delete all items. Share items. Cannot manage workspace settings. |
| Contributor | Create, edit, and delete items they own. Cannot share items or manage access. |
| Viewer | View items and run reports. Cannot edit or create items. |
Assign roles to Entra ID groups, individual users, or service principals:
security:
roles:
- name: data_engineers
entra_group: sg-data-engineering
workspace_role: contributor
- name: analysts
entra_group: sg-analytics-team
workspace_role: viewer
- name: project_lead
entra_user: jane.doe@contoso.com
workspace_role: admin
- name: cicd_deployer
service_principal: fab-bundle-cicd
workspace_role: admin
Each role entry requires exactly one principal (entra_group, entra_user, or service_principal) and one workspace_role.
Entra ID group resolution¶
You can reference Entra ID groups and service principals by their display name or by their GUID. When you use a display name, fab-bundle calls the Microsoft Graph API at deploy time to resolve it to the object's GUID.
# Display name (resolved via Graph API)
entra_group: sg-data-engineering
# GUID (used directly, no Graph API call)
entra_group: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Display name resolution requires the deploying identity (your user account or the CI/CD service principal) to have GroupMember.Read.All or Group.Read.All permission in Microsoft Graph. If the permission is missing, fab-bundle will report an error suggesting you use GUIDs instead.
Using GUIDs is faster (no API call) and avoids ambiguity when multiple groups share similar names.
OneLake data access roles¶
OneLake data access roles provide fine-grained, table-level and folder-level access control within a lakehouse. They operate below the workspace role level: a user can have Viewer access to the workspace but read access to only specific tables.
security:
roles:
- name: sales_analysts
entra_group: sg-sales-team
workspace_role: viewer
onelake_roles:
- tables: ["fact_sales", "dim_customer", "dim_product"]
permissions: [read]
- name: data_engineers
entra_group: sg-data-engineering
workspace_role: contributor
onelake_roles:
- tables: ["*"]
permissions: [read, write]
- folders: ["raw/*"]
permissions: [read, write]
- name: finance
entra_group: sg-finance
workspace_role: viewer
onelake_roles:
- tables: ["fact_revenue", "dim_cost_center"]
permissions: [read]
- folders: ["reports/finance/*"]
permissions: [read]
Supported permissions¶
| Permission | Description |
|---|---|
read |
Read data from the specified tables or folders |
write |
Write data to the specified tables or folders |
Wildcard patterns¶
["*"]-- All tables or all folders in the lakehouse.["raw/*"]-- All items under theraw/folder path.["dim_*"]-- All tables whose names start withdim_.
Portal prerequisite
OneLake data access roles must be enabled per-lakehouse in the Fabric portal before fab-bundle can manage them. Go to the lakehouse settings in the portal and enable OneLake data access roles (Preview). Without this, the API calls will fail with a 403 error.
Row-level security¶
Row-level security (RLS) restricts which rows a user can see in a semantic model. Define RLS roles with DAX filter expressions:
security:
row_level_security:
- semantic_model: sales_model
roles:
- name: region_us
description: "See only US sales data"
filter: "'dim_geography'[country] = \"US\""
members:
- entra_group: sg-sales-us
- name: region_eu
description: "See only EU sales data"
filter: "'dim_geography'[region] = \"EU\""
members:
- entra_group: sg-sales-eu
- name: all_regions
description: "See all data (no filter)"
filter: "TRUE()"
members:
- entra_group: sg-sales-leadership
Each RLS role defines a DAX filter expression applied to the specified table. The members list determines which Entra groups or users are assigned to that role.
Column-level security¶
Column-level security (CLS) restricts which columns a user can see. It is defined per semantic model and applies to specific tables:
security:
column_level_security:
- semantic_model: hr_model
restrictions:
- table: dim_employee
denied_columns: [salary, ssn, performance_rating]
applies_to:
- entra_group: sg-hr-viewers
- table: dim_employee
denied_columns: [ssn]
applies_to:
- entra_group: sg-hr-managers
Users in the applies_to list will see the table but the specified columns will be hidden. Users not in any restriction list see all columns.
Service principal permissions¶
The service principal used for CI/CD deployments needs specific permissions depending on what the bundle manages:
| Capability | Required Permission |
|---|---|
| Create, update, delete items | Workspace Contributor or Admin role |
| Manage workspace role assignments | Workspace Admin role |
| Manage OneLake data access roles | Workspace Admin role |
| Resolve Entra display names to GUIDs | Microsoft Graph Group.Read.All (application permission) |
| Manage RLS/CLS | Workspace Admin role + semantic model ownership |
If the service principal only needs to deploy items without managing security, Contributor is sufficient. If the bundle includes a security section, Admin is required.
Security in CI/CD¶
In a CI/CD pipeline, the service principal authenticates via environment variables (AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET) and must have the workspace roles listed above.
A common bootstrap pattern:
- A workspace admin manually grants the service principal Admin access to each target workspace (dev, staging, prod) through the Fabric portal.
- The service principal is also declared in the bundle's
securitysection so that its access is codified and will be re-applied on every deploy:
- From this point on, all security changes (adding new groups, modifying OneLake roles) go through the bundle and are deployed by the service principal.
See Service Principal Setup for full instructions on creating the service principal, granting permissions, and configuring CI/CD secrets.
Full YAML example¶
security:
roles:
# Workspace-level roles
- name: data_engineers
entra_group: sg-data-engineering
workspace_role: contributor
onelake_roles:
- tables: ["*"]
permissions: [read, write]
- name: analysts
entra_group: sg-analytics-team
workspace_role: viewer
onelake_roles:
- tables: ["fact_sales", "dim_customer", "dim_product"]
permissions: [read]
- name: external_vendor
entra_group: "b2c3d4e5-f6a7-8901-bcde-f12345678901" # GUID for external group
workspace_role: viewer
onelake_roles:
- tables: ["fact_sales_summary"]
permissions: [read]
- name: cicd_deployer
service_principal: fab-bundle-cicd
workspace_role: admin
# Row-level security
row_level_security:
- semantic_model: sales_model
roles:
- name: region_us
filter: "'dim_geography'[country] = \"US\""
members:
- entra_group: sg-sales-us
- name: region_eu
filter: "'dim_geography'[region] = \"EU\""
members:
- entra_group: sg-sales-eu
# Column-level security
column_level_security:
- semantic_model: hr_model
restrictions:
- table: dim_employee
denied_columns: [salary, ssn]
applies_to:
- entra_group: sg-hr-viewers