My team has a service deployed internally, and part of this service is a list of client accounts stored in a sql table. SSRS is hosted on another server and we have integration jobs which [will eventually] pull these client accounts (along with additional info) from our 3 production environments to this SSRS database.
Also on this SSRS database, I’m creating a new table that will be a mapping of domain accounts and client accounts. I need this table so I can filter my report based on which client accounts the logged on user is allowed to see.
Pretty simple so far.
The next requirement of this is that I need to restrict access to the report itself. I understand I could normally use a security group to do this, but that would result in two separate locations to manage permissions for one resource and this is what I want to avoid.
The solution I’m looking into is to create a security extension to validate the logged in user against the database, allowing them access to the folder/report if they exist in the table. Once in, I can then use that same table again to filter their results.
What I’m not sure of is 1) if this is the best solution and 2) can I use a security extension for just MY portion of the site. There are many other users and reports on this site that I don’t deal with and don’t want to conflict with those.
Could you fill the DB table automatically from AD? Then you can use the standard windows security, but still only do the administration in Active Directory.
link text
You could set up an internal report parameter, called something like UserID, and set its default value to be the non-queried expression =User!UserID . (This user ID can be selected from the list of globals in the Edit Expression dialog.)
You could then add a cartesian/cross join to your users table in your query, with a selection condition based on your internal report parameter - eg. ...and UserTable.ID = #UserID . This would ensure that no records were returned if an unauthorised user was running the report.
Note that the User!UserID field will only return the user for interactively-run reports - in scheduled reports, this will be the account for the scheduling service.
Can't you restrict access to the report by using a security group (either in it's own folder or report level permissions). Use windows authentication in your datasource connection and filter you report retrieving your username using the sql function ORIGINAL_LOGIN?
Related
I have a report that accesses sensitive data and I'm required to have the user log in to the SSRS portal and then again into the data source to make sure the data isn't viewed by the wrong staff.
I feel like I've tried everything at this point, but no matter what I try I cannot access a data source by logging in to it from an SSRS report. I've tried:
Logging in with a windows authenticated db_owner account. Produces "Cannot create a connection to data source" error without any other info.
Logging in with a SQL authenticated account with select permissions to the view used by the data source with the same result.
Using current users credentials, same result.
I've enable remote errors on SSRS, but cannot locate a log of errors and the errors produced on SSRS portal have not changed.
I've read just about every tutorial about creating logins and users and how to set them up to access data sources.
Voodoo
Psychics
Therapists
All users have access through to the data when i run a select statement in SSMS, so I'm stumped. I've messed around with giving explicit rights to Connect, Select, Authenticate for the Server, DB, view and still no luck.
Are your users in Active Directory, or are you using SQL Authentication? Because if your users are in AD you can do this easily. I think you need the SSRS in Native Mode not SharePoint mode too, but I'm not 100% certain about that.
Create an AD group to hold privileged users, I'll call it
MyOU\SSRSViewers
Put all the users who can access this sensitive data in this group
In SSRS, in the security settings for the reports, data sets, and
data sources, give this group read or read/execute permissions
In the database create stored procedures to access your sensitive
data (you can give data_reader access instead, but if you want to
lock down data then access through stored procedures is much easier
to control).
In the database, create a USER for the MyOU\SSRSViewers group. At
the server level users need PUBLIC role, this lets them see the
server at all. They probably already inherit that from elsewhere,
but if not you can tie it to this group, too.
Grant EXECUTE permission on those stored procedures to the
MyOU\SSRSViewers user (it's a group, but it looks like a user in
SSMS, don't worry)
Create or modify your report data sources to use WINDOWS
AUTHENTICATION method and data sets to call the stored procedures to
get the data instead of SELECT statements.
Make sure you don't have any explicit deny permissions on the data
in question, or if you do at least test them very carefully, because
they can mess up this access (by denying access to somebody who
should have it, not by leaking your data)
If you do all this, here's how access works - when a users first goes to SSRS to view a report, SSRS will check to see if the user has permission to see the (empty) report. If they are in the group (or have permissions another way, so this is hard for a developer to test on their own machine) they get the empty report.
SSRS then checks the data source (which has no credentials!) to see if they can use it. Again, if in the group, yes. They still don't have data, but they can get the connection details. If they can, SSRS will pass a token from their windows session to the database to see if they can actually get the data.
If they make it this far, SQL will only let them execute the stored procedure (and get the data) if they are in that group with EXECUTE permissions on that stored procedure.
The users don't see these logins, the browser is automatically forwarding their login tokens (not credentials), but authorization is checked at every step and is very secure.
A few notes:
First, your SSRS server has to be in a trusted zone for this to work smoothly, if it is then the browser will pass authentication tokens to SSRS seamlessly. If not, they'll have to "log in" to SSRS every time, which gets old fast. Set this with your Group Policy.
Second, some configurations may include 2-hop authentication, a problem for ordinary NTLM. You may need to set up Delegated Constraints to make this work smoothly.
I didn't do either of these myself, but we had to do both at my company. Neither was particularly painful (or at least the guy who did it didn't complain), but I couldn't tell you how to do either, and I may not be using the ideal descriptions/terms.
Third, this scales well, if you have 3 different types of reports, you can create 3 different groups and your users can be in any combination of groups, getting access to only the data relevant to the groups they are in.
I am looking for different ways to uniquely identify an application user in SQL Server 2008.
To give some back ground to the issue:
The ASP.NET 4 web application I work with uses an SQL Server 2008 database, there is one SQL Server login and DB User for all connections from the application to database.
We are developing a reporting solution using Crystal Reports where users can write and execute their own reports through the application. The crystal reports can only return data from Views. Each application user will have their own unique login to the server.
The View then uses SELECT SYSTEM_USER() to find the logged in user and restrict data returned from the view.
Is it bad practice to create a distinct login and DB user for each application user? This would mean > 1000 users per DB, across up to 80 databases (Creation of
each log in would be handled through T-SQL, not manually)
What other ways can the user be identified in the View in the DB?
We looked at altering the connection string to include the user id in the Workstation ID, we can use SELECT HOST_NAME() to get the ID, but this seems like abuse of the Workstation ID.
Any other suggestions about how the user can be uniquely identified would be appreciated.
Many thanks
Have you considered using Windows Authentication as apposed to SQL Authentication? That would at least reduce the number of logins & users that would need to be managed.
Y can use external database,file or other resource to store user access to any data when u use msql 2008.
http://msdn.microsoft.com/en-us/library/dd392015%28v=sql.100%29.aspx
That give y change to not mix data with audit elements for performance and security reasons.
Use profiler on your sql server and in profiler is information about ( aplication , user , and host ). So that kind of information y can easy get by audit or from custom trigger on certain database objects.
Your aplication can also have own user table and share the same connection string too all users or give users with windows auth type only public privilege. And use in stored procedures run as command ( run as another user in db).
So y can log any user and give them minimal rights.
Its my firs post here and I actually learning English lol.
There were two solutions that we came up with:
Before the Crystal report is executed, in .Net we can extract the SQL the report (and sub report) will generate, execute the SQL and put the results in a dataset and generate the report from the dataset. The advantage of this is that because we have the SQL, before the SQL executes, we can supply user information to the SQL server session that can be used to identify the user when the SQL is executing.
Have a limited number of SQL Server user logins which can be dynamically assigned to application users. We will have a table which will map the SQL Server Login to an application user just before they run a Crystal report. When they query has finished executing the Login is released. Obviously this means that at busy times we may run out of Logins, but more can be added depending on usage.
In SQL Server I have a many to many relationship between items and active directory groups. I want to build a query, that based on a supplied active directory user, I would be able to query for all items associated to an active directory group if the user is a member of the group.
I went down the road of using IS_Member, but that only works for the currently connected user. The stored procedure will be called by an asp.net web app, which currently connects with a specific sql user account. I don't think I can connect using integrated authentication and impersonation in the web app, because I don't beleive our infrastructure configuration will allow delegation from the user machine, through the web server, then to the db server (3 hop issue).
What can I do here?
Write a C# or VB.NET .exe that queries AD and populates a table in the database with all the users/groups and call it from a SQL job that you execute daily. Then just use the synched up table data to do the comparisons. This way you can avoid all the other complexity of trying to do it on the fly. Group membership doesn't change that often. Even if something changed in AD you can just manually run your "sync job" and things would be ok. You can use Windows.Identity() or whatever it is from ASP.NET to check the username.
The issue you describe is a classic double-hop scenario, which can be (eventually) resolved through the painstaking process known as Kerberos configuration. A lazier workaround would involve passing the credentials from the asp.net application as a variable to a SQL query on your database.
If the SQL Server has the LDAP Server configured as a linked server, you could rewrite your stored procedures to accept the user as an input variable and check to see if the user is a member of an AD group before proceeding. Consider incorporating OPENQUERY into your stored procedures as shown below:
CREATE PROCEDURE CheckAccess
#CurrentUser varchar(max)
AS
IF #CurrentUser IN
(
SELECT CN
FROM OPENQUERY(ADSI,'<LDAP://DC=Your,DC=DomainComponent,DC=com>;(&(CN=*)
(memberOf=CN=YourADGroupName,OU=Your,OU=OrganizationalUnit,OU=Name,DC=Your,DC=DomainComponent,DC=com));CN')
)
THEN
SELECT 'Authorized User'
ELSE
SELECT 'Unauthorized User'
END
If you can, consult with your LDAP admins to make sure you get the group's correct domainComponents and organizationalUnits to tweak the OPENQUERY. One drawback to this is that it can take a while to query your AD group, obviously depending on the size of membership. It can be a pain, but as long as your app can pass the user as a variable, you can leverage OPENQUERY or even query sys.database_principals to check their access.
I'm having a problem with my SSRS 2008 configuration at the moment. This is how we are currently set up.
1 server hosting SQL Server and SSRS, no integration with sharepoint etc. Users access the SSRS web application, and then from there they access the "Report Builder 1.0" too, which they can use to create and run reports based off a reporting model.
This is all done using Windows Authentication - so they login with their domain account to the web application, and then again when loading the Report Builder. Each domain user is configured to be able to login to SQL Server rather than using a generic SSRS account, and all of the above works fine.
The way this is setup means that you can always tell which individual user is logged in and running reports - either to the website or when running reports through report builder. This is a requirement of this application as all users will see slightly different versions of the data models (this is controlled by the underlying views, based off the domain account running the query). So Tom may get 100 rows back from his query but Harry will only get 50, etc.
The Datasource is setup to use integrated security (Which passes through this domain account to SQL Server).
My problem comes when a user creates a report in report builder, and then saves it to the server. When they login to the web application and run the report there - it works fine, but when they try to setup an email subscription, they get this message:
"Subscriptions cannot be created because the credentials used to run the report are not stored, or if a linked report, the link is no longer valid"
A bit of research leads me to think that this is down to the integrated security settings, as for some reason SSRS is ignoring the currently logged on user account or cannot use that to setup the subscription.
Everything works if I set the datasource to use a specific account - but then that breaks the data filtering based on user account (obviously, as it would now be just using one account for everyone!).
Any ideas for how I can approach this? Is there a configuration setting that I can play with to try and get this working using integrated security? Any help/comments are appreciated!
To create a report subscription you must meet a few reqs:
First is,
A report that can run unattended (that is, a report that uses stored credentials or no credentials).
To do what your wanting to do I suggest you setup data driven subscriptions. Heres a link to get you started. Data Driven Subscriptions Theres also several good videos of the basic setup. Like this one sqlLunch #8
Here's another walkthrough that's pretty decent: Walkthrough
Hope any of this helps ya.
Thats a nice one to have in your tool belt as well.
If you just drop the subscribed report into a file share instead of emailing it, the users can fill in their username and password, so it will run as them. The only problem with doing it this way is when they change their password, they will need to go and put the new password into the subscription again.
I guess they could have another account with a password that wont expire to run the report as, but that's probably not good practice
what you could do is have the list of users in a table in the database with what they're permissions are, then set up a data-driven subscription to get the list of users and get their permissions and filter the report accordingly.
I'm considering using reporting services 05 SP2 with share point integration on a new reporting project.
In this project's reports users can only see records they own. I was thinking a simple userId parameter on the report would allow me to filter the report's results to only these "owned" records.
I'm curious: Can I pass the current share point user's ID to the report some how? Can it be done in such a way that its not possible for the user to somehow alter it? How would I do this if possible?
The sharepoint UserID = the one RS will use and detect.
This is defined by UserID global in RS and picked up form the login token.
You can hide the parameter (Report) or just specify it at the dataset level (SQL).
Have you tried getting row level security happening at the database end?
You project then only needs to pass the users credentials through as it does anyway and you can then let SQL server security handle the issue?