[PowerBi] Seguridad de filas (RLS) con regla dinámica

En multiples ocasiones me he encontrado con muchos videos y artículos respecto a seguridad a nivel de filas sobre Power Bi. Todos ellos definen muy bien de que se trata pero la mayoría de las veces muestra un ejemplo desarrollado con un regla demasiado tradicional. En esos escenarios vemos el clásico [Pais] = "Argentina".

En mi experiencia laboral aplicamos una regla de ese estilo una sola vez puesto que si siguiera esa lógica habría participado de desarrollos que crearan como 80 reglas por cada tienda, provincia, región, etc.

En éste artículo vamos a ver como construir una ÚNICA regla dinámica para la columna que deseamos filtrar que se adaptará a cada resultado.

Contexto

Las entidades que tienen una gran cantidad de usuarios necesitan aplicar RLS en reportes que llevarían muchas reglas. Por esta razón, se acude a este tipo de prácticas donde el mantenimiento no está dentro de la solución/desarrollo de Bi sino en una parte más administrativa. 

NOTA: no existe ninguna solución que haga absolutamente todo dinámico y se adapte a todos los escenarios. Siempre en alguna parte se cargan datos que ayuden a mejorarlo

Como muchos pueden estar imaginando la solución pasa por las funciones USERNAME o USERPRINCIPALNAME de DAX. Éstas devuelven el usuario logueado en el entorno de Power Bi Service. De éste modo que podemos capturar un dato cambiante y dinámico que nos ayude a filtrar nuestro modelo.

Power BI Desktop

Suponiendo que tenemos un modelo estrella en nuestro informe, vamos a agregar un tabla auxiliar en el modelo que se relacionará a la dimensión que tiene la columna bajo la cual deseamos filtrar. La columna puede ser tanto la identificadora única de la dimensión como así también una cualquier dentro de la misma. Para ambos casos se ejecutará de igual modo.

La idea principal de la solución es generar una tabla estática en el origen (excel, sharepoint list, base de datos, etc) que contenga el correo con el cual loguea el usuario en Power Bi y el dato de la columna bajo la cual filtrar.

Veamos un diagrama para mejor comprensión. Tenemos nuestra dimension Stores relacionada al Hecho InternetSales y creamos TablaRLS con los correos de las personas y el o los países que deberían ver.

image

Una vez creada la tabla la relacionamos con nuestra dimension y aquí aparece un detalle importante. No importa si la relación a la tabla es por la clave única (1-*) o si es por otra columna que no pertenece a la clave (*-*) porque para que RLS se propague por una relación física en nuestro modelo, la dirección del filtro tiene que ser única/single. Si estuviéramos relacionando a la columna única de stores deberíamos forzar la relación *-* para que nos permita propagar el filtro desde TableRLS hacia Stores puesto que la bidireccionalidad NO es una opción para propagar un filtro RLS.

Tal vez muchos este ahora pensando que los tanos de SQLBI se la pasan diciendo que no hagamos relaciones muchos a muchos (*-*). Sin embargo que les recuerdo que ellos siempre aclaran "A menos que sepan lo que significa y puedan controlarlo". Este es un escenario que tendría controlada la relación muchos a muchos sin causar una falla en todo el modelo dado que sería un filtro no cambiante de una sola vez al cargar el modelo y no relacionado a otras tablas. 

NOTA: En sus videos de tratamiento de relaciones mucho a mucho también expresan la posibilidad de armar relaciones virtuales en una medida para expresar un resultado. Nosotros podríamos no relacionar las tablas y generar una relación virtual en la regla RLS pero sería más incomprensible.

Al momento de crear nuestra regla, vamos a generarla para la TableRLS que se ve así:

image

Colocando el siguiente código con USERNAME() aunque también podría usarse USERPRINCIPALNAME():

image

[Mail] = USERNAME()

Esa regla será suficiente para que cuando east@ladataweb.com.ar ingrese al informe, se propague el filtro de pais por la dimensión hasta la tabla de hecho generando que los resultados del informe estén filtrados por China y Germany puesto que tiene dos filas en dicho ejemplo. Podemos probarlo sencillamente con "Ver Rol Como".

image

Controlamos que así sea en una página:

image

Así es como llegamos al final de la implementación de Power Bi Desktop para una regla de RLS dinámica en cualquier modelo sobre cualquier columna.

Antes de cerrar la herramienta recuerden que es buena práctica crear un rol sin reglas para aquellos usuarios que debería ver todo sin filtros puesto que una vez activado RLS los usuarios visores deben tener un rol asignado para poder ver el informe.

Implementación

No todo termina aquí puesto que necesitamos configurar Power Bi. Si ya vieron la configuración recomendada clásica sabrán que ahora deberíamos asignar las X personas a su Rol con lo cual seguiríamos teniendo una solución de Bi dependiente del entorno. Por ello les recomiendo ir más allá. Lo ideal para el siguiente paso sería que el Departamento IT o administrador de Office 365 cree dos grupos de Office. Uno de ellos para los usuarios que ven todo dentro de los informes y otro grupo para aquellos usuarios que están limitados a ver países como sería el caso de los que están en la TableRLS.

De ese modo podemos dejar configurado en la Seguridad del Dataset dentro de Power Bi Service que el rol dinámico tenga un participante que es el grupo de Office de personas que tendrían filtrado por países y nuestro rol administrador el grupo de Office de personas que ven todo el informe. Entonces nuestro rol "Dynamic" tendría (1) grupo y VerTodo tendría (1) grupo. La siguiente imagen va a modo de ejemplo donde agregar.

image

Realizando esta división cada vez que sumamos una persona nueva en el entorno de Power Bi no es necesario realizar ningún cambio en el desarrollo de Bi, sino que el cambio consiste en incorporar la nueva persona al grupo de Office y a la planilla de roles en caso que lo requiera para que automáticamente se aplique todo el manejo de filtros a nivel de fila del informe.

Ahora si tenemos un desarrollo de seguridad a nivel de filas con roles dinámicos que controlaríamos por data y no dentro de la solución. Espero que les sea útil para sus soluciones.