{"id":104782,"date":"2024-12-04T20:45:00","date_gmt":"2024-12-04T20:45:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=104782"},"modified":"2026-10-16T12:43:22","modified_gmt":"2026-10-16T12:43:22","slug":"granting-permissions-in-a-fabric-data-warehouse-and-lakehouse","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/data-analytics\/microsoft-fabric\/granting-permissions-in-a-fabric-data-warehouse-and-lakehouse\/","title":{"rendered":"Granting Permissions in a Fabric Data Warehouse and Lakehouse"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">We are becoming used to being a bit lazy when granting permissions to Data Warehouses and lakehouses in Fabric. We only go to the workspace level and add the user as a viewer or member. For more on this, <a href=\"https:\/\/www.red-gate.com\/simple-talk\/data-analytics\/microsoft-fabric\/using-a-service-account-in-microsoft-fabric\/\">see creating a Fabric service account.<\/a> For more on this, see <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/bi-sql-server\/choosing-between-the-lakehouse-and-warehouse-in-microsoft-fabric\/\">the differences between the Fabric warehouse and lakehouse.<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, this is far from a good idea.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This practice not only gives the user access to all tables in the warehouse or lakehouse, but also gives access to all objects in the workspace. Bad idea. For more on this, see <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/bi-sql-server\/using-virtual-network-data-gateways-to-secure-access-to-azure-sql-in-power-bi\/\">VNet data gateways for Power BI.<\/a> <\/p>\n\n\n\n<h2 id=\"h-the-solution\" class=\"wp-block-heading\">The Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The solution is on the old and good SQL security practices. A Fabric Data Warehouse has database roles in a very similar way as Azure SQL\/SQL Server<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"292\" height=\"354\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/a-screenshot-of-a-computer-description-automatica.png\" alt=\"A screenshot of a computer\n\nDescription automatically generated\" class=\"wp-image-104783\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can add to the roles users which have no access in the workspace. In this way, the user will receive access to the Data Warehouse\/Lakehouse, but not to the other objects in the workspace.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But what user?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fabric works in the same tenant as Azure, with the same security environment. Every user available in Azure is also available in Fabric.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, the statement below adds a user to the db_datareader role in a data warehouse<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">alter role db_datareader add member [dennes2@dennesbufaloinfocom.onmicrosoft.com]<\/p>\n\n\n\n<h2 id=\"h-after-adding-the-user\" class=\"wp-block-heading\">After Adding the user<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You can use the system table <strong>sys.database_principles<\/strong> to identify the users. An Azure user will not appear in this table, unless it received some kind of permission in the warehouse.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">select name, principal_id, type_desc from sys.database_principals<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1166\" height=\"229\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/a-screenshot-of-a-computer-description-automatica-1.png\" alt=\"A screenshot of a computer\n\nDescription automatically generated\" class=\"wp-image-104784\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Danger:<\/strong> It&#8217;s interesting to notice this user doesn&#8217;t appear in the option Manage Permissions in the Data Warehouse\/lakehouse. The granular permission management is good, but it can also be dangerous because you can lose track of who has access to what.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1115\" height=\"341\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/a-screenshot-of-a-browser-description-automatical.png\" alt=\"A screenshot of a browser\n\nDescription automatically generated\" class=\"wp-image-104785\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 id=\"h-more-granular-access-permissions\" class=\"wp-block-heading\">More Granular Access Permissions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Database Roles available give permission to read all tables or write on all tables. What if you would like to have more granular control than this?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You also have the DB Custom Roles. You can create a completely custom role; define the granular permissions you would like and add the user to the custom role.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The code will be like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">--remove the user from the current role\n\nalter role db_datareader drop member [dennes2@dennesbufaloinfocom.onmicrosoft.com]\n\n-- create a custom role\n\ncreate role MyCustomRole\n\n-- Grant permission to the custom role\n\nGrant SELECT on dbo.customer to MyCustomRole\n\n-- add the user to the custom role\n\nalter role MyCustomRole add member [dennes2@dennesbufaloinfocom.onmicrosoft.com]<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"214\" height=\"99\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/a-screenshot-of-a-computer-description-automatica-2.png\" alt=\"A screenshot of a computer\n\nDescription automatically generated\" class=\"wp-image-104786\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 id=\"h-checking-group-membership-of-a-user\" class=\"wp-block-heading\">Checking Group Membership of a User<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We need to be capable of checking the groups the user belongs to. This is especially important because these permissions don&#8217;t appear inside Manage Permissions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can do this making some joins with system tables, but it&#8217;s not a so simple query:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT\n    p.name AS PrincipalName,\n    p.type_desc AS PrincipalType,\n    r.name AS RoleName\nFROM\n   sys.database_principals p\n   LEFT JOIN\n   sys.database_role_members rm \n        ON p.principal_id = rm.member_principal_id\n   LEFT JOIN\n   sys.database_principals r \n        ON rm.role_principal_id = r.principal_id\nORDER BY p.name;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The table <strong>sys.database_role_members<\/strong> needs to be joined twice with sys.database_principals, one to retrieve the name of the user who belongs to a group and the other to retrieve the name of the group.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1371\" height=\"292\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2024\/12\/a-screenshot-of-a-computer-description-automatica-3.png\" alt=\"A screenshot of a computer\n\nDescription automatically generated\" class=\"wp-image-104787\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 id=\"h-lakehouse\" class=\"wp-block-heading\">Lakehouse<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">All these features also work in a SQL Endpoint of a lakehouse, but with some additional details:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li>The SQL Endpoint in a lakehouse is already read-only<\/li>\n\n\n\n<li>There were restrictions about if spark code in a notebook would respect the rules. This evolves all the time, take care and check the current state of this.<\/li>\n<\/ul>\n<\/div>\n\n\n<h2 id=\"h-summary\" class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We can and we should be managing permissions in our Fabric environment in a granular way. We need to leave behind old practices from Power BI era and increase the security level of our solutions<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are becoming used to being a bit lazy when granting permissions to Data Warehouses and lakehouses in Fabric. We only go to the workspace level and add the user as a viewer or member. For more on this, see creating a Fabric service account. For more on this, see the differences between the Fabric&#8230;&hellip;<\/p>\n","protected":false},"author":50808,"featured_media":104788,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[159164],"tags":[123645,158998,158997,4619],"coauthors":[6810],"class_list":["post-104782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-fabric","tag-data-warehouse","tag-lakehouse","tag-microsoft-fabric","tag-security"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/50808"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=104782"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104782\/revisions"}],"predecessor-version":[{"id":113852,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104782\/revisions\/113852"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/104788"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=104782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=104782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=104782"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=104782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}