La row-level security (RLS) in Microsoft Fabric non è un’unica funzionalità: esistono due punti di applicazione distinti, e sceglierne uno al posto dell’altro è esattamente ciò che l’esame DP-600 verifica.

Dove applicare la sicurezza: modello o warehouse

Requisito Dove implementare Meccanismo
Consumo solo via report Power BI sul semantic model Semantic model Ruoli + filtri DAX
Query T-SQL dirette su Warehouse / SQL analytics endpoint Warehouse CREATE SECURITY POLICY + predicate function
Entrambi i canali Warehouse (base) + eventualmente modello La sicurezza SQL viene ereditata dai modelli in DirectQuery

La regola operativa: la RLS del semantic model protegge solo chi passa dal modello. Se un analista si collega al SQL analytics endpoint con SSMS o con una query diretta, i ruoli DAX non esistono per lui. Viceversa, la security policy T-SQL agisce sul motore SQL e vale per qualunque client che interroghi il warehouse, incluso un semantic model in DirectQuery.

RLS nel semantic model: ruoli e filtri DAX

In Power BI Desktop, da Modeling > Manage roles, si crea un ruolo e si assegna un’espressione DAX booleana a una tabella. Il filtro viene valutato come predicato di riga:

// Ruolo "Italy" sulla tabella DimTerritory
[Country] = "Italy"

Dopo la pubblicazione, i membri si assegnano dalle impostazioni Security del semantic model nel workspace (utenti, gruppi di sicurezza Microsoft Entra ID, gruppi M365).

Propagazione attraverso le relazioni

Il filtro non va quasi mai messo sulla tabella dei fatti: si filtra la dimensione e si lascia che il filtro propaghi lungo la relazione uno-a-molti verso i fatti. Filtrare DimTerritory filtra automaticamente FactSales, e da lì — se il modello è a stella — anche le misure aggregate.

Se la propagazione deve risalire (per esempio da una tabella ponte utente-territorio verso una dimensione), servono relazioni bidirezionali e, cosa che molti dimenticano, la casella “Apply security filter in both directions” nelle proprietà della relazione: senza quella spunta il cross-filtering bidirezionale non viene applicato in contesto RLS.

RLS dinamica con USERPRINCIPALNAME

La RLS statica richiede un ruolo per ogni territorio: ingestibile oltre poche unità. La versione dinamica usa un solo ruolo e una tabella di mapping.

  1. Crea una tabella UserTerritory con colonne UserPrincipalName e TerritoryKey.
  2. Collega UserTerritory a DimTerritory (molti-a-uno).
  3. Crea un ruolo unico con filtro su UserTerritory:
[UserPrincipalName] = USERPRINCIPALNAME()

USERPRINCIPALNAME() restituisce l’UPN dell’utente autenticato nel servizio (in Desktop restituisce l’utente locale, per questo si testa con View as > Other user). Il filtro colpisce la tabella di mapping, che propaga a DimTerritory e da lì ai fatti. Nascondi UserTerritory dalla vista report e valuta di marcarla come tabella privata.

RLS nel Warehouse: predicate function + security policy

Nel Warehouse (e nel SQL analytics endpoint del Lakehouse) la sintassi è quella di SQL Server:

CREATE FUNCTION Security.fn_TerritoryPredicate(@SalesRep AS varchar(100))
RETURNS TABLE WITH SCHEMABINDING
AS RETURN SELECT 1 AS granted
WHERE @SalesRep = USER_NAME();

CREATE SECURITY POLICY Security.TerritoryFilter
ADD FILTER PREDICATE Security.fn_TerritoryPredicate(SalesRep)
ON dbo.FactSales
WITH (STATE = ON);

Punti operativi: la funzione deve essere inline table-valued e WITH SCHEMABINDING; in Fabric l’identità si legge con USER_NAME() o SESSION_USER, che restituiscono l’UPN. Per nascondere colonne, non righe, si usa la column-level security (GRANT SELECT (col1, col2)) o il dynamic data masking, che non sono RLS.

Trappole tipiche d’esame

  • Scenario: un utente con ruolo Admin o Member sul workspace vede tutte le righe nonostante sia assegnato a un ruolo RLS. → Non è un bug: la RLS del semantic model si applica solo ai Viewer (e a chi riceve permessi diretti di sola lettura). Admin, Member e Contributor la bypassano. Soluzione: assegnare il ruolo Viewer.
  • Scenario: modello in Direct Lake, RLS configurata, ma l’utente legge i dati completi. → La RLS del modello non sostituisce i permessi OneLake: chi ha ReadAll sul Lakehouse può leggere i file Delta direttamente. Rimuovi il permesso OneLake e usa la RLS lato SQL o l’identità fissa del modello.
  • Scenario: il consumo avviene sia via Power BI sia via query SQL ad hoc. → Implementa la RLS nel warehouse con security policy: coprire solo il semantic model lascia scoperto il canale SQL.
  • Scenario: RLS dinamica corretta ma le vendite non si filtrano tramite la tabella ponte. → Manca il filtro di sicurezza bidirezionale sulla relazione.
  • Scenario: si chiede di nascondere la colonna Salary a un gruppo. → Non è RLS ma object-level security (modello) o column-level security (warehouse).