Forum Discussion
Azure Analysis Services RLS and Embedding
We would like to embed reports with RLS but I'm starting to get the feeling that is not possible with Analysis Services(both Azure and on premise) using live connection in Power BI.
We started with on-premise analysis service (live connection) but that is not supported according to the following document:
https://docs.microsoft.com/en-us/azure/power-bi-embedded/power-bi-embedded-connect-datasource
Therefore, we moved the data to Azure and now we have Azure Analysis Service live connection and would like to embed that with RLS.
We are having problems implementing this and on the following webpage there is a note saying that Analysis Services live connections are not supported:
https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-embedded-rls/
Is this really the case and if so when can we expect to embed RLS Power Bi reports with Analysis Service data (live connection)? Is this on the roadmap?
Btw, we are working with big datasets so using import instead of live connection is not really an option for us.
I finally got this to work with PowerBi Embedding and RLS using the followingt instructions:
Make sure that you use Customdata DAX funtion to filter the data and also that add an Azure user to the Role:
=INS_TABLE[column] = Customdata()
I used the sample project found here:
https://docs.microsoft.com/en-us/power-bi/developer/embed-sample-for-customers#embed-your-content-using-the-sample-applicationwith the following modification:
// Generate Embed Token for reports without effective identities.
var rls = new EffectiveIdentity("xxxAzureUserName", new List<string> { report.DatasetId }, new List<string>() { "SchoolFiltering" }, "SchoolName");generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view", identities: new List<EffectiveIdentity> { rls });
Hope this helps
33 Replies
- AnonymousNot applicable
I'm also very confused about this also.
I can sucessfully embed a report connecting to Azure AS (live connection) using a master account and then generating the embed token using 'GenerateTokenInGroup' (code: https://github.com/guyinacube/Embed-API-Sample).
But when trying to use the Identities property to use RLS I always get this error:
"Creating embed token for accessing dataset a5fc8daa-a34b-48b3-85fc-d76d0e21a8db requries effective identity username to be identical to the caller's principal name”
I dont know if it's a limitation around Power BI Embed + Azure AS or if it is somekind of configuration issue.
Thanks
- Alex-FNew Member
I'm facing with the same issue as Anonymous is.
Thanks
- cmarquisNew Member
Running into the same situation here as well. Trying to use direct query to Azure AS with PowerBI embedded (app owns data) and need to be able to apply RLS.
Is there any timeline on when this will be possible?
- Valtyr
Advocate I
I finally got this to work with PowerBi Embedding and RLS using the followingt instructions:
Make sure that you use Customdata DAX funtion to filter the data and also that add an Azure user to the Role:
=INS_TABLE[column] = Customdata()
I used the sample project found here:
https://docs.microsoft.com/en-us/power-bi/developer/embed-sample-for-customers#embed-your-content-using-the-sample-applicationwith the following modification:
// Generate Embed Token for reports without effective identities.
var rls = new EffectiveIdentity("xxxAzureUserName", new List<string> { report.DatasetId }, new List<string>() { "SchoolFiltering" }, "SchoolName");generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view", identities: new List<EffectiveIdentity> { rls });
Hope this helps
- rg2018
Advocate I
Thanks for the post. I have simillar scnerio where in embedded mode I need to display PowerBi report and Powerbi is consuming data from Azure analasis Services. I need to filter data from analysis services based on RLS rule (AccountID). Not getting how you have specified CustomeData() function. Can you please pass on any sample? thanks.
- Valtyr
Advocate I
Hi,
The method works like this:
=TABLENAME[COLUMNNAME] = Customdata()
In your case it might look something like this:
=ACCOUNTS[ACCOUNTID] = Customdata()
Hope this helps :)
- Rishabh-Maini
Helper II
Hi Valtyr ,
I have been trying to embed a powerbi report based on an AAS model as well
We keep getting the following error:Result
11:12:36:747 USER_DEBUG [153]|DEBUG|Body: {"error":{"code":"InvalidRequest","message":"Creating embed token for accessing dataset *dataset id* requires effective identity to be provided"}}
The modification specified in your comment, which file did you add it in?
And did you not use Customdata() function along with it?
Is there a sample code you can provide with which we can get this working?
I would really appreciate any kind of help.
Thanks!- MattStannettFrequent Visitor
Assuming that you're using C#, below is an implementation that I have used for a Razor pages implementation.
It is by no means perfect but it works, I hope it helps
// CSPROJ <PackageReference Include="Microsoft.AnalysisServices.NetCore.retail.amd64" Version="19.10.0-Preview" /> <PackageReference Include="Microsoft.ApplicationInsights" Version="2.14.0" /> <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.14.0" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.7" /> <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.7.0" /> <PackageReference Include="Microsoft.Identity.Web" Version="1.2.0" /> <PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.8" /> <PackageReference Include="Microsoft.PowerBI.Api" Version="3.14.0" /> // App Settings "ActiveDirectoryUpn": { "ClaimTypesToSearch": [ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "preferred_username" ] } // Reports.cshtml.cs // _settingsType is an enum public async Task OnGetAsync(Guid? reportId) { ClaimsPrincipal user = _httpContextAccessor.HttpContext.User; List<Claim> claims = user.Claims.ToList(); IList<Report> reportsResult = await _reportRepository.GetAvailableReportsAsync(_settingsType); Reports = new List<Report>(reportsResult); string[] claimTypesToSearch = _activeDirectoryUpnSettings.Value.ClaimTypesToSearch; // SECURITY : Don't do this unless we can secure things downstream string upn = claims.Where(c => claimTypesToSearch.Contains(c.Type) && RegexUtilities.IsValidEmail(c.Value)).Select(c => c.Value).FirstOrDefault(); string claimsJson = JsonConvert.SerializeObject(GenerateDictionaryForUserClaims(claims)); if (reportId.HasValue) { SelectedReport = await _reportRepository.GetEmbeddedReportConfigAsync(reportId.Value, upn, claimsJson, _settingsType); var identityNameId = user.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); var identityName = user.Claims.FirstOrDefault(x => x.Type == "preferred_username"); _telemetry.TrackEvent("ReportOpened", new Dictionary<string, string> { { "report_Id", SelectedReport.Id }, { "report_Name", SelectedReport.Name } }); } else { SelectedReport = await _reportRepository.GetEmbeddedReportConfigAsync(null, upn, claimsJson, _settingsType); } } // ReportRepository.cs using Microsoft.PowerBI.Api; using Microsoft.PowerBI.Api.Models; public async Task<EmbeddedReportConfig> GetEmbeddedReportConfigAsync(Guid? reportId, string name, string claimsJson, SettingsTypeEnum settingsType) { PowerBiSettings powerBiSettings = GetPowerBiSettings(settingsType); AzureToken azureToken = await _authenticationHandler.GetAzureTokenDataAsync(settingsType); using (var powerBiClient = new PowerBIClient(new Uri(powerBiSettings.ApiUrl), azureToken.TokenCredentials)) { List<string> roles = await GetDataFromAzureAnalysisServices(settingsType, name); int assignedRolesCount = roles.Count; string debugOutput = BuildDebugOutput(reportId, name, claimsJson, roles, assignedRolesCount); if (!reportId.HasValue) { // Initial page load where no report is selected or the user has manually removed the report GUID from the URL return GetEmbeddedReportConfig(null, null, 0, debugOutput); } else if (!roles.Any()) { // A report is selected but the user has no roles return GetEmbeddedReportConfig(new Report(reportId.Value), null, 0, debugOutput); } try { Report powerBiReport = await powerBiClient.Reports.GetReportAsync(powerBiSettings.WorkspaceId, reportId.Value); // SECURITY : Is there a better way to do Effective Identity without passing through CustomData? EffectiveIdentity rowLevelSecurityIdentity = new EffectiveIdentity(powerBiSettings.Username, roles: roles, datasets: new List<string> { powerBiReport.DatasetId }, customData: name); GenerateTokenRequest powerBiTokenRequestParameters = new GenerateTokenRequest("View", powerBiReport.DatasetId, false, rowLevelSecurityIdentity); EmbedToken powerBiTokenResponse = await powerBiClient.Reports.GenerateTokenInGroupAsync(powerBiSettings.WorkspaceId, powerBiReport.Id, powerBiTokenRequestParameters); return GetEmbeddedReportConfig(powerBiReport, powerBiTokenResponse, assignedRolesCount, debugOutput); } catch (HttpOperationException ex) { //Bad Request var content = ex.Response.Content; Console.WriteLine(content); throw; } } } private EmbeddedReportConfig GetEmbeddedReportConfig(Report powerBiReport, EmbedToken powerBiTokenResponse, int assignedRolesCount, string debugOuput) { return new EmbeddedReportConfig { Id = powerBiReport?.Id.ToString(), Name = powerBiReport?.Name, EmbedUrl = powerBiReport?.EmbedUrl, AccessToken = powerBiTokenResponse?.Token, AssignedRolesCount = assignedRolesCount, DebugInformation = debugOuput }; } private async Task<List<string>> GetDataFromAzureAnalysisServices(SettingsTypeEnum settingsType, string upn) { AzureAnalysisServicesEndpointSettings settings = GetAzureAnalysisServicesEndpointSettings(settingsType); string serverDomain = settings.ServerDomain; string serverName = settings.ServerName; // Use the trial database as a safe default string databaseModel = settingsType == SettingsTypeEnum.Premium ? "PilotV1" : "PilotV2Demo"; string serverAddress = $"asazure://{serverDomain}/{serverName}"; // Used to be used in the authority URL string tenantId = settings.TenantId; string appId = settings.ApplicationId; string appSecret = settings.AppSecret; string authorityUrl = settings.AuthorityUrl; AuthenticationContext authContext = new AuthenticationContext(authorityUrl); // Config for OAuth client credentials ClientCredential clientCred = new ClientCredential(appId, appSecret); AuthenticationResult authenticationResult = await authContext.AcquireTokenAsync($"https://{serverDomain}", clientCred); string connectionString = $"Provider=MSOLAP;Data Source={serverAddress};Initial Catalog={databaseModel};User ID=;Password={authenticationResult.AccessToken};Persist Security Info=True;Impersonation Level=Impersonate"; List<string> roles = new List<string>(); using (Server server = new Server()) { server.Connect(connectionString); // If your database isn't appearing here, then it is most likely because the AAS role which has the "Full Control" permission // along a member entry for app:<app-registration-object-id>@<azure-active-directory-tenant-id> has been removed. Database database = server.Databases.FindByName(databaseModel); if (database == null) { return roles; } var modelRoles = database.Model.Roles; List<RoleMapping> roleMappings = modelRoles.Select(r => new RoleMapping(r.Name, r.Members.Select(m => m.MemberName).ToList())).ToList(); roles = roleMappings.Where(g => g.Members.Contains(upn, StringComparer.InvariantCultureIgnoreCase)).Select(k => k.Name).ToList(); } return roles; }
- TomMartens
Super User
- AnonymousNot applicable
we are also facing the same issue - thought the future was supposed to be azure, not on-prem.
- robrien6
Advocate IV
Im facing exactly the same issue. Very little support for those paying the most in licencing costs........
- footmarksRegular VisitorWe are experiencing the same issue. When will this be supported?
- edugp_sp
Advocate I
I have the same issue. Does anyone have any updated about this issue?
- markus_x5Regular Visitor
I'm having the same issue, and I thought I was doing something wrong (the documentation is not great), but apparently it's a lack in the service.. Like everyone else in this thread, I would also love to get more info on future plans for support.
Edit:
I create a feedback entry for this issue at feedback.azure.com, feel free to upvote it, that way maybe we can get some attention on this:
- Valtyr
Advocate I
I've heard vague rumours that this might be support in Q1 2018. I would like to get that confirmed but I'm not sure where to get a proper answer.
- AnonymousNot applicable
Are all these about only Azure AS or also about on premise AS 2017? The first post said both were tried but that was Oct and in Oct it wasn't ready for RLS, but came out shortly thereafter for changes in the web app. We are using SSAS 2017 on premise because we felt Azure AS didn't have RLS working yet. We are using AppOwnsData model and have RLS and using live connections to tabular cubes on premise, but we display these through the gateway on Salesforce and it works fine. Is this only a problem with Azure AS? It would be good to know as we want to go there, but felt it wasn't ready for prime time yet.
- Eric_Zhang
Microsoft Employee
Valtyr wrote:
We would like to embed reports with RLS but I'm starting to get the feeling that is not possible with Analysis Services(both Azure and on premise) using live connection in Power BI.
We started with on-premise analysis service (live connection) but that is not supported according to the following document:
https://docs.microsoft.com/en-us/azure/power-bi-embedded/power-bi-embedded-connect-datasource
Therefore, we moved the data to Azure and now we have Azure Analysis Service live connection and would like to embed that with RLS.
We are having problems implementing this and on the following webpage there is a note saying that Analysis Services live connections are not supported:
https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-embedded-rls/
Is this really the case and if so when can we expect to embed RLS Power Bi reports with Analysis Service data (live connection)? Is this on the roadmap?
Btw, we are working with big datasets so using import instead of live connection is not really an option for us.
The limitation in the second link is specific for the Embedding with non-Power BI users (app owns data). For the other embeding feature Embedding with Power BI users (users own data), the RLS shall work . The main difference between those embedding feature is on license aspect. If you prefer live connection, use the latter approach to embed.
- Valtyr
Advocate I
Thanks for the reply Eric_Zhang.
I disagree that this is only a matter of licensing. It is quite inconvenient for our users to have to log into power bi when they want to access the reports. The reason why we are looking into embedding is to avoid this.
Will RLS with direct analysis services (app owns data) will be supported any time soon? This is quite urgent matter and I would guess that there are a lot of companies in the same situation as we are.
- AnonymousNot applicable
I concur with Valtyr; this feature is also critical and an urgent matter for us to go forward with our PBI Embedded project.
- Valtyr
Advocate I
I've spent so much time trying to get this to work for 'app owns' data before realizing it is not possible. Can you please confirm that RLS will work with live connection azure reports if I use the 'user owns' data method?
- edugp_sp
Advocate I
I have the same issue. Does anyone have any updates about it?