On a recent project, my client asked if we could secure members of a dimension by Active Directory groups. For example, in a dimension named “Region”, there might be a “Southeast” region. Members of the A/D group named Southeast should only be able to view the “Southeast” member. Below is an example of this, built using the AdventureWorks database. In this example, the Geography dimension is secured.
The Dimensional Model
The goal is that when a client application (like Excel) issues the below query, Analysis Services returns only specific geographies the user is authorized to view.
To secure the Geography dimension, two additional tables are added to the model: FactGeographySecurity and DimUser. Here’s the DDL:
Now insert some test data into the new tables. The below DML adds my user account, and then grants me access to cities in Great Britain and Canada.
In BIDS, add the DimGeography, DimReseller, and FactResellerSales tables to your Data Source View from the AdventureWorksDW database. Also add the two new tables, DimUser and FactGeographySecurity.
Create database/cube dimensions for Geography, Reseller, and User. Create Reseller Sales and Geography Security measure groups. Your cube structure should now look like the below:
Applying Security
In BIDS, create a new role. Mine is named “DimensionSecurity”. On the “Membership” Tab add your user account (I added my “black” account). On the “Dimension Data” Tab, open the “Advanced” sub-tab. Select the “Geography” dimension, and the “City” attribute. Then type the below MDX expression into the “Allowed member set” text box. You can also check “Enable Visual Totals” here if totals should be tallied based on the filtered set, not the entire set.
The exists function returns a set that is based on filtering the first set by members of the second set. And because the “Geography Security” measure group is specified, the second set, [User].[User Name].&[black], must also have associated rows in the FactGeographySecurity fact table. Now it should make sense why we added FactGeographySecurity as a measure group, and DimUser as a dimension.
Note: this only secures the City attribute. For each attribute in the drop-down list, type in an allowed member set similar to the one above. Only the first parameter would change. Ex., for the Country-Region attribute, the first parameter becomes [Geography].[Country-Region].MEMBERS.
Testing in BIDS
In BIDS, go to the cube browser, and click the “Change User” icon. Select the “Roles” option, and choose “DimensionSecurity” from the drop-down list. Expand Geography and drag the City attribute into the rows area. Drag any measure from Reseller Sales into the totals area. You should see, as in the below, that only cities from Great Britain and Canada are displayed.
Testing via MDX
Run the below MDX script in SSMS. Notice how the “Allowed member set” MDX from above is used on the row axis, with the username hardcoded. This might be useful if you just want to verify that the dimension/fact data is setup correctly.
Testing in Excel 2007
When connecting via Excel, you might expect it to just work. After all, your account is in the “DimensionSecurity” role. But if you are a server administrator, you will still see all of the City members, not just ones for Great Britain and Canada. But similar to the way you explicitly chose “DimensionSecurity” in the BIDS cube browser, you can test other roles by listing them (comma-delimited if more than one) in the connection string:
Provider=MSOLAP.4;Integrated Security=SSPI;Persist Security Info=True;Data Source=blackd820;Initial Catalog=SSAS Security;Roles=DimensionSecurity
To do this, (I’m using Excel 2007), go to the “Data” tab and select “Properties”. You’ll find the connection string on the “Definition” tab. Add the part highlighted in yellow above.
Note: If you’ve only set security on the “City” attribute, expand “More fields” and select “City” from the PivotTable Field List pane.
Populate the security table from Active Directory
You probably noticed that security is defined in the FactGeographySecurity table at the grain of the individual user, instead of the Active Directory role. This is because there is no IsUserInRole MDX function. So now we have to maintain data in the FactGeographySecurity table to keep it in sync with Active Directory. To do this, we need a way to query an A/D group and return a list of users.
A utility application scheduled to execute nightly could be written to accomplish this. The code snippet below retrieves a list of users in the specified A/D group; this list could be used to insert records into FactGeographySecurity.
Finally
Using this approach, each dimension can be secured by creating only a single role. This satisfied my client, who did not want to manually create a role per geography, then go into the role definition and manually select dimensions available to that role.
Hope this helps!






15 comments:
Thanks so much for this information. It will really simplify our security. I did have to modify the Dimension Data MDX statement to remove the ALL attribute.
EXCEPT(Exists([Customer].[Territory].MEMBERS,StrToMember("[User].[User Name].[" + Username + "]"), "Territory Security"), [Customer].[Territory].[ALL])
But other than that it looks like it will work for us. Thanks again!
I have this following error, kindly help.
Check MDX script syntax failed because of the following error:
An error occurred in the MDX script for the dimension attribute permission's allowed member set: The dimension '[Dim User]' was not found in the cube when the string, [Dim User].[User Name].&[blackd820\black], was parsed.
I am encountering the following error, kindly help.
Check MDX script syntax failed because of the following error:
An error occurred in the MDX script for the dimension attribute permission's allowed member set: The dimension '[Dim User]' was not found in the cube when the string, [Dim User].[User Name].&[a\b], was parsed.
Sonal, I was discussing this Chuck Rivel, one of our BI specialists. I thought it had to do with the "\" in the [a\b]. Here is a response from Chuck:
To me, it looks like it cannot find the Dimension itself since the error states that it cannot find the Dim User.
Since it is in the brackets, I do not think that the slash would be an issue but I would not be surprised if it was.
I would have Sonal write another MDX statement, something simple like:
select [Measures].[Measure Amt] on columns,
[Dim User].[User Name].children on rows
from [Cube]
(Sonal supplies a measurement and cube name)
Ensure that this works and the a\b record comes across.
Hi Steve,
Thanks for such a quick response.
Actually, my problem is that when I am running the following query thru SSMS, its working fine:
select [Measures].[Internet GPM] on 0,
EXISTS(Customer.[Email Address].members,{STRTOMEMBER("[Employee].[Login ID].[" + Username + "]")}, "Fact Secure Customer") on 1
from [Analysis Services Tutorial]
But when I am writing this expression in the "allowed member set":
EXISTS(Customer.[Email Address].members,{STRTOMEMBER("[Employee].[Login ID].[" + Username + "]")}, "Fact Secure Customer")
I am getting the above said error.
So, it would be of great help if you can help me out with this.
Hello All,
I got the resolution for my problem.
I was trying to implement custom security on database dimension instead of cube dimension. So, when I tried the same thing on cube dimensions, it worked perfectly.
Thanks for this great article.
Hi,
Badly need your help. I followed your article and did exactly whats in here but when I am trying to create a Grid in Performancepoint server using the role, its not fetching any data. However, when I hard code the value of the user and do not use the role, the thing works.
Please let me know if there is a problem with the role that I created. Here is what I specified in the role:
In membership, added my userid.
In Datasources, gave read permission.
In cubes, gave read permission with drillthrough.
In cell data, selected the cube from dropdown and checked the 3 checkbox.
In dimension data, chose the Region dimension and for the Region Name attribute added the below MDX in the allowed set
Exists([Region].[Region Name].MEMBERS,StrToMember("[ME].[Domainame].&[" + Username + "]"), "Fact Region User Security").
When I try it in SSMs by hardcoding the domain username it works. However with Performance it doesn't.
Please help!!!
Figured out the issue. I mis-spelled the Dimension hierarchy.
Must say that this post has been extremely well written in a very lucid manner and it really helped me.
Thank you. Nice work out.
Thank you very much, This post helped me in implementing dynamic security for the first time.
Good Stuff, thanks a lot was looking for this for a while :)
Great post. But i've run into the same error
"An error occurred in the MDX script for the dimension attribute permission's allowed member set
The dimension was not found in the cube when the string was parsed"
It's a department dimension, named department. Department is also a role playing dimension and when i'm testing this in visual studio other user it also throwing an error:
The 'Departmentdescription' attribute in the 'LastDepartment' dimension has a generated dimension security expression that is not valid.
something to do with cube and regular dimension?
Hi will this pass curren login from sharepoint user to the USERNAME in cube filter...
Hello,
Thanks for the excellent post. I was able to accomplish security as required.
I had a question on this and would appreciate any help. My requirement is to make the security implementation totally dynamic and not require a cube refresh each time a user needs to be set up or his/her access request changed. I am trying to accomplish this by having the user dimension and the M:M table sourced from a database View instead, so that all changes are automatically reflected. However, the Views don't seem to help and still requires processing the cube for the access changes to take effect. Is there a workaround?
Thanks in advance!
-Subah
Hi Subah,
In order to avoid the required refresh, you will need to design and use an Analysis Services .Net Stored Procedure.
The procedure will need to query the security source (a table, directly against ActiveDirectory, or something else) and return a dynamically constructed set of members for the current user.
Then in the role, you will call your .Net Stored Procedure.
Here's an example of what I have in mind...
http://dwbijourney.blogspot.com/2008/10/dynamic-dimension-security-in-ssas.html
And here's a great placce to review some examples of Analysis Services .Net Store Procedures...
http://www.codeplex.com/wikipage?ProjectName=ASStoredProcedures
Post a Comment