Dimension Security in SSAS & SSRS - sql-server

I am stuck with a problem of implementing security at dimension level in SSAS. Here is what I did -
1. Defined a role in SSAS and applied security at dimension level (Unchecking cube dimensions that I don't want this role to access and setting Allowed & denied Sets).
2. Tested using Cube Browser, it worked fine.
3. Tested using SSRS, no change, I was still able to query the dimensions & get results that I don't want.
Question - Is it possible to propagate the security I define at Cube level to SSRS? I would like to believe yes it is.
If yes then here is what I need -
Users will logon to the Report Manager using Windows Identity (Integrated Authentication on IIS turned on -done)
Capture this identity to find out SSAS role that they belong to - I guess this would be through a query, does not seem to work automatically (How to do this?)
User works within the restrictions of this role in SSRS (role based security applied at SSAS level) i.e. if dimension X is not available to user, he/she should not be able to query it. (How to do this?)
I have referred quite a few blogs on this and even found one - http://www.sqlmag.com/Article/ArticleID/96763/sql_server_96763.html
but this one seems to have more information on how to set it up within SSAS, rather than how to use this in SSRS.
Anyone who has worked on this approach OR have an understanding of this please let me know.

I think you need to look at your datasource in SSRS on the report server, and make sure it is set to use the logged in users windows cred's once authenticated, it might be what you are looking for.

All you need to do is:
In the data source in SSRS report, specify the Role Name created in SSAS database like this:
Data Source=LOCALHOST;Initial Catalog=XXXXX;Roles=RoleName
Thanks
Sameer

I haven't done this in SSAS, but I've done it in the engine. Jeremiah Peschka has a blog about row-based security setup, and if you're going to do this with integrated Windows security, then you can use the user_name() function to grab the current login's name. You'll be using a lookup table for each dimension, with a row for each dimension row plus the user's name. When querying, join to the dimension security table like this:
FROM dbo.Customers cs
INNER JOIN dbo.CustomersSecurity css ON cs.CustomerId = css.CustomerId AND css.UserName = User_Name()
That way, your join will only return records for customers that the user can see.
The drawback is that if you're using partitioning, the engine won't build a good execution plan to only pluck the right records from the right partitions based on what your user can see. For example, if you log in as a user that can only see records in Florida, and your data is partitioned by state, it won't matter - the engine will still scan all partitions, because it won't be able to predict the user's info when the plan is built.

Related

Import Active Directory to SQL Server

I'm working on a Microsoft BI project.
I am currently in the process of connecting my systems to SQL Server. I want to connect my Active Directory to a table in SQL Server and I want to sync to one table per hour. This means that every hour the details of the Active Directory will be updated.
I realized that it is necessary to use SSIS to do this I would be happy for help to connect my AD to SQL Server with the help of SSIS.
There are two routes available to you to sync AC user classes to a table. You can use an ADO source in an SSIS Data Flow Task or you can write custom .NET code as part of a Script Source. The right answer depends on your team's ability to maintain and troubleshoot a particular solution as well as the size of your AD tree/forest. If you're a small shop (under a thousand) anything is going to work. If you're a larger shop, then you need to worry about the query mechanism and the total rows returned as there is an upper boundary of how many results can be returned in a single query. In that case, then a script task likely makes more sense as you can more easily write a query to pull all the accounts that start with A, B, etc. I've never worked with Hebrew, so I assume one could do a similar filter for aleph, bet, etc.
General steps
Identify your domain controller as you need to know what server to ask information from. I do not know how to deal with Azure Active Directory requests as I believe it works a bit different there but haven't had client work that needed it.
Create a Connection Manager for ADO.NET . Use the ".Net Providers for OleDb\OLE DB Provider for Microsoft Directory Services" and point that to your DC.
Write a query to pull back the data you need. Based on the comment, it seems you want something like this
SELECT
distinguishedName
, mail
, samaccountname
, mobile
, telephoneNumber
, objectSid
, userAccountControl
, title
, sn
FROM
'LDAP://DC=domain,DC=net'
WHERE
sAMAccountType = 805306368
ORDER BY
sAMAccountName ASC
Using that query, we'll add a Data Flow Task and within it, add an ADO.NET Source. Configure it to use our ADO.NET Connection manager and use the above query (adjusting for the LDAP line and any other fields you do/don't need)
Add an OLE DB Connection Manager to your package and point it to the database that will record the data.
Add an OLE DB Destination to the Data Flow and connect the output line from the ADO.NET Source to this destination. Pick the table in the drop down list and on the Columns tab, make sure you have all of your columns connected. You might run into issues where the data types don't match so you'll need to figure out how to handle that - either change your table definition to match the source or you need to add data conversion/derived columns components to the data flow to mangle the data into the correct shape.
You might be tempted to pull in group membership. Do not. Make that a separate task as a person might be a member of many groups (at one client, I am in 94 groups). Also, the MemberOf data type is a DistinguishedName, DN, which SSIS cannot handle. So, check your types before you add them into an AD query.
References
ldap query to get disabled user records with whenchanged within 30 days
http://billfellows.blogspot.com/2011/04/active-directory-ssis-data-source.html
http://billfellows.blogspot.com/2013/11/biml-active-directory-ssis-data-source.html
Is there a particular part of the AD that you want? In any but the smallest corporations the AD tends to be huge. Making a SQL copy of an entire forest every hour is a very strange thing that may have many adverse effects on your AD, network, security and domain-wide performance.
If you are just looking to backup your AD, I believe that there are other options available, specific to the Windows AD (maybe even built-in, I'm not an AD expert).
If you really, truly want to do this here is a link to get you started: https://social.technet.microsoft.com/Forums/ie/en-US/79bb4879-4d82-4a41-81a4-c62afc6c4b1e/copy-all-ad-objects-to-sql-database?forum=winserverDS. You can find many more articles on this just by Googling "Copy AD to Sql".
However, heed the warnings well: the AD is effectively a multi-domain-wide distributed database, attempting to copy it into a centralized database like SQL Server every hour is contra-indicated. You are really fighting against its design.
UPDATE Based on the Comments:
Basically you've got too much in one question here. Sql Server, SSIS and the Active Directory (AD) are each huge subjects in and of themselves and the first time that you attempt to use all of them together you will run into many individual issues depending on your environment, experience and specific project goals. We cannot anticipate all of them in a single answer on this site.
You need to start using the information you have from the following links to begin to implement this yourself, and then ask specific questions as you run into problems along the way.
Here are the links that you can start with,
The link I provided above from MS: https://social.technet.microsoft.com/Forums/ie/en-US/79bb4879-4d82-4a41-81a4-c62afc6c4b1e/copy-all-ad-objects-to-sql-database?forum=winserverDS
The link that you provided in the comments that explains how to setup ADSI as a linked server and how to use T-SQL on it: https://yiengly.wordpress.com/2018/04/08/query-active-directory-in-sql-server-with-linked-server/
This one explain how to use AD from within an SSIS DataFlow task (but is limited to 1000 rows): https://dataqueen.unlimitedviz.com/2012/05/importing-data-from-active-directory-using-ssis/
This related one explains how to use AD within an SSIS Script task to get around the DataFlow task limits: https://dataqueen.unlimitedviz.com/2012/09/get-around-active-directory-paging-on-ssis-import/
As you work your way through this you may run into specific problems, which you can ask about at https://dba.stackexchange.com which has more specific expertise with Sql Server and SSIS.
Based on your goals, I think that you will want to use a staging table approach. That is, use your AD/Sql query to import all of the AD users records into a new/empty temporary table that has the same column definition as your production table, then use a Merge query to find and update the changed user records and insert the new user records (this is called a Differential or Type II update).

Azure SQL: How to be notified if someone exports the database?

I run a system based around an Azure SQL Database.
A few different team members need to have read access to this database to perform support and management tasks.
However, I am concerned that by having access to the database, one of them may - with the best of intentions - export the database and manage the backup carelessly, resulting in a data breach.
How can I get Azure to notify me if somebody backs up the database (or downloads more than X million rows, maybe?) These people need to have database access, I would just like to know if they use it in a way that could cause a security risk for the platform.
You can use Extended Events for this.
To set it up on Azure you can follow this tutorial.
For your case
You create a session
You Select the rpc_completed (docs) event and click configure
In the Global Fields tab you can select the fields you want to keep track of. I.e.: Username, sql_text, session_id, database_name, client_*
In the Filter tab you can select a filter condition. In your case row_count would be appropriate.
When malicious users are smart, and retrieve small numbers of rows and page them this will go undetected. So a second filter could be Querys without WHERE clauses or a different approach based on your case.
When extended events are setup to write to blobstorage. You would have a different process (Azure Function, Runbook, ...) that would inspect the result and alert you.
Extended events are moslty used for troubleshooting, they replace SQL profiler. So turning it on a production server may have a performance impact.

Restrict data access

I have a SQL Server 2014 Database with Analysis services and have created an Initial CUBE using Visual studio 2013. All works as expected however I want to be able to restrict specific users to specific data within the cube.
On all of the dimensions there is a field called "ACCOUNT" and what I need to do is restrict users to specific accounts only. The user should not be able to change or alter this list. I am using both EXCEL and Teleriks RadPivotGrid for WPF as the client front end. I know that telerik has a report filter which I can add to programmatically however the user can remove and/or change this filter which I cannot allow the user to do.
I may have data within about 700 different accounts on it and does anyone have any idea how to do this?
A simple way to implement this would be to set up roles on SSAS, and then apply dimension security using the roles.
I.e. Assign 1 or more members in your dimension to a role, and assign your users to that role.
Here's the Books Online pages:
Dimension Data (Role Designer)
Security Roles
Here's a basic step through: Introduction to Dimension Security

Dimensional Level Security / Per User Data Security in SSAS Cube?

I'm part of a team looking to move from our relational data warehouse to a SSAS cube. With our current setup we have an "EmployeeCache" table (basically a fact) which is a mapping from each of our employee ids to their viewable employee ids. This table is joined in our model to our DimEmployee table so that for every query that needs personally identifiable information the DimEmployee records are filtered. The filter is applied from a session variable that is the user id which is making the query.
All of the examples we researched to provide dimension level security in a SSAS cube have required the use of Windows managed security. The systems that create the data that is being analyzed handle their own security. Our ETLs map the security structure into the aforementioned EmployeeCache and DimEmployee tables. We would like to keep this simple structure of security.
As we see it there is no way to pass in session values (aside from using the query string which we're not seeing it possible with Cognos 10.1) to the cube. We're also not seeing any examples out there on security which does not require the use of Windows auth.
Can someone explain if there is a way to achieve dimensional security as I have previously described in a SSAS cube? If there is no way possible could another cube provider have this functionality?
Two thoughts. Firstly, SSAS only supports windows authentication (see Analysis Services Only Windows Authentication) and this is unchanged in Sql Server 2012. But you can pass credentials in the connection string to analysis services. Secondly, could you alter the MDX of every query and add a slicer to restrict the data to only the data a user should see?

improve security at "database layer" - only select queries allow

I am building a application in silverlight which will enable users read information about their payment. Their login and password will be save in table in db.
It is possibility to improve security in my app by limiting what data a query has access to? For instance i want to prevent a user from selecting data they do not own. A limitation is that my application is using a its own table for users, so i cannot use GRANT PERMISSION :/. I am using Linq to build my sql queries.
This question is from my teacher who "suggest" me to improve security, so if it's impossible - it's no big deal ;)
Well, it is kind of a vague question you've asked, but I'll hazard a stab at it.
You must be doing some authentication on the user's identity to only be showing them their payment, as opposed to someone else's payment. So, if you can do that, you should be able to create triggers that disallow any insert, updates, or deletes on your tables from those same identities... I don't think this is a very robust or scalable solution, but it's an idea.
CREATE TRIGGER [x] ON [TABLE] FOR INSERT
/* Disallow Users to insert */
IF EXISTS( SELECT 1 1 FROM [Users] WHERE [Users].UserID = [Y])
--Rollback transaction, set error, etc
Do you have any more details? Anything else could be helpful in finding a better solution.
A fine tuned access control for database resources is a very uncommon method of securing your application. User level access control is best implanted by the application. The sql user account used by the application should be as restricted as possible. For instance it should only be able to use the database(s) it needs to function, and nothing more.
There is 1, and only 1 project that has fine grained access control for a sql database, and that project is SE-PostgreSQL.
"It can provide fine grained mandatory
access control to various database
objects such as tables, columns or
tuples and can apply consistent
authority of remote/local client
integrated with operation system
independent from database
authorization."
Create a view named 'MyPayments', on the 'Payments' table. Make sure you have a WHERE clause in the view definition, so that the view returns only the relevant data to each user. Here is what the WHERE clause of your view will look like:
WHERE PaymentOwner = SUSER_SNAME()
The SUSER_SNAME() system function returns the currently logged in user's login name. If the first user logs in with the login name 'User1' and inserts a row, his/her login name is stored along with the row. The SUSER_SNAME() function in the WHERE clause of the view definition makes sure 'User1' see only those rows that have the 'PaymentOwner' column set to 'User1'.
More here

Resources