We have MS SQL Server 2012 in production use and MS AD.
Let me explain in short what our concept of assigning user permissions is like.
For certain user group that has some access to a certain application we create AD group and assign AD users to it. Since this application needs to access data in other DB, we add that group to that DB as well and set access/execute rights to needed objects (either specific object or schemas).
Since certain people use other applications and DBs, they are added to other AD groups as well. Those groups, by no surprise, need to access some objects to second database too.
So we have situation when certain users are in few different AD groups with different accesses to the same objects in a DB. That causes lots of "strange" behaviors when, all of a sudden, some user gets denied access to objects in DB.
My questions are:
Is there any way to find out with which privileges (through which AD group) some user got access/denial for certain sql query that was triggered from application?
Can someone explain how sql server handles privileges in such environment?
I'm open for any suggestions on how to handle/set accesses differently altogether but not involving reprogramming applications (only DBA site).
Thank you.
Assuming that you're an admin, you can look at sys.login_token, sys.user_token, and sys.fn_my_permissions() while impersonating the user in question to get some idea. Something like:
execute as login='yourDom\User1';
select * from sys.login_token;
select * from sys.user_token;
select * from sys.fn_my_permission('dbo.someObject', 'OBJECT');
revert;
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 have revoked select permissions for a user in SQL Server and gave them access to one table but the user can still query all tables.
REVOKE SELECT ON "dbo"."TableName" FROM "Domain\user.name"
I have double and triple check all the permissions on both the login and user. Can someone please steer me in the right direction?
To identify all permissions someone may have in SQL, you have to look at:
The SQL Login configured for their domain login. Is it a member of any server-level groups? Does it have any server-level permissions?
What databases does it have access to?
Within those databases, what permissions does it have?
I'm guessing you've already done that. Next level:
Identify all domain groups for which SQL Logins have been created.
Determine which of these groups your user is a member of. Do the same checks as above, e.g. what can members of that group do in this SQL Instance.
Note that domain groups can contain domain groups. Depending on how in (or out of) control you Domain Administrators are, you could have crazy levels of nesting going on. And this is in the Domain, active directory, which you may or may not have sufficient access rights to review in detail.
Don't forget Local (that machine) groups, often set up by default. Is the user a member of a local machine group with elevated rights? You won't find anything out about this at the domain level.
This of course assumes that they are only using their own personal domain login, without aliasing, "Running As", SQL authenticated logins, application logins, and probably some even more obscure things I can't think of right now. (They probably aren't, unless they're griefing you.)
Note that this was off the top of my head. Configuring SQL Security is a Dark Art; figuring out who's been configured with what can be a nightmare (and worse when dealing with applications running on system accounts.) Good luck!
Evening,
I would like some practical confirmation in relation to an issue we are having.
We have a K2/SourceCode solution that turns upon the successful use of EXECUTE AS with Sql Server 2008 R2.
We have no direct control over how this solution is implemented, i.e. we cannot modify the queries that are submitted to the Sql Server engine. We can, of course, capture them using Profiler, and they tend to follow this pattern:
DECLARE #cookie VARBINARY(100);
EXECUTE AS LOGIN = 'DOMAIN\username' WITH COOKIE INTO #cookie;
SELECT #cookie;
exec [dbo].[SomeStoredProcedure] /* ... various params ...*/
exec sp_executesql N'REVERT WITH COOKIE = #cookie;',N'#cookie varbinary(100)',#cookie=/* some cookie value */
So what is happening is that [SomeStoredProcedure] is being executed in the security context of the user [Domain\username], with the service (application) account impersonating that user. Again, I emphasise that we have no control over this pattern. That's what the app does.
Outwardly this behaviour is perfectly-desirable, because we want things arranged in such a way that the stored procedure is effectively executed by whichever user is at the front-end of the application at the time.
However, these queries were consistently failing, and our investigation eventually led us to this, from the Sql Server documentation (my emphasis):
Specifying a User or Login Name
The user or login name specified in EXECUTE AS must exist as a principal in
sys.database_principals or sys.server_principals, respectively, or the
EXECUTE AS statement fails. Additionally, IMPERSONATE permissions
must be granted on the principal. Unless the caller is the database
owner, or is a member of the sysadmin fixed server role, the principal
must exist even when the user is accessing the database or instance of
SQL Server through a Windows group membership. For example, assume the
following conditions: CompanyDomain\SQLUsers group has access to the
Sales database. CompanyDomain\SqlUser1 is a member of SQLUsers and,
therefore, has implicit access to the Sales database. Although
CompanyDomain\SqlUser1 has access to the database through membership
in the SQLUsers group, the statement EXECUTE AS USER =
'CompanyDomain\SqlUser1' fails because CompanyDomain\SqlUser1 does not
exist as a principal in the database. If the user is orphaned (the
associated login no longer exists), and the user was not created with
WITHOUT LOGIN, EXECUTE AS will fail for the user.
We have a group of around 30 end users who need to be able to use this application, and the requirement is that the application security account must be able to impersonate any one of those users for the execution of these stored procedures. This requirement is fixed and non-negotiable.
The above documentation seems to preclude the possibility of meeting this requirement by adding all 30 users to an AD group, adding that group as a SQL Server login, and granting the group adequate permissions. And our practical testing results support this - EXECUTE AS fails.
Take one of those Users and give them their own, individual AD login on the Sql Server and the solution will work successfully for that user. EXECUTE AS succeeds, and the necessary permissions do not need to be assigned to the individual account because they have already been assigned by way of the AD group.
So, at this point, I am reasonably confident that I know what I am going to have to do. The requirement will be that every user has to have their AD account added as an individual Sql Server Windows login.
However, before I proceed with the rigmarole of implementing this, I wanted to ask the question publicly: is there something I am missing here?
It's instructive to imagine a similar scenario on an Enterprise-scale application - this model would somewhat fall apart, because of the need to add hundreds of individual, Windows-authenticated, Sql Server logins. Setting aside the possibility of automating this process, and the administrative burden that would ultimately result, I'm just finding it a bit of a stretch to imagine that this is the only way.
I would be grateful for confirmation and/or comments.
Thanks
Robert
As no-one has responded to the contrary (or indeed at all) we have assumed that BOL is accurate, and that there is no alternative resolution.
Situation:
A Windows user is member in multiple AD groups.
Every AD group is mapped to a SQL Server login.
Every SQL login is mapped to a database user.
Every database user has specific roles.
Question:
Is it possible that a Windows user is logging into SQL Server (using WinAuth) and that he gets all roles which he could get due to his membership in multiple AD groups?
Yes. A user's permissions on an object is the union of all permissions paths s/he qualifies for (including any DENY permissions). A quick way to verify is by using the sys.user_token and sys.login_token views as well as the sys.fn_my_permissions function. From an administrative perspective, these work especially well because they are accurate under impersonation (i.e. execute as login = 'yourDomain\someUser').
This is for SQL Server 2005 or later, but I'd be interested to know if SQL Server 2000 works in the same way. Consider the following situation.
Two SQL Server Windows Authentication logins whose Login name is a Windows group:
MyDomain\Group1
MyDomain\Group2
A database with two users that are mapped to these logins:
USE MyDatabase
CREATE USER [User1] FOR LOGIN [MyDomain\Group1]
CREATE USER [User2] FOR LOGIN [MyDomain\Group2]
User1 and User2 are granted disjoint permissions in the database, e.g.:
GRANT SELECT ON Table1 TO User1
DENY SELECT ON Table1 TO User2
GRANT SELECT ON Table2 TO User2
DENY SELECT ON Table2 TO User1
A client connects to SQL Server using a Windows Identity that is a member of both groups MyDomain\Group1 and MyDomain\Group2.
Which database user is the client mapped to? I.e. does SELECT USER_NAME() return User1or User2?
What permissions does the client have? Is there a defined precedence which determines whether the client connects as User1 or User2? Where is this documented in BOL?
Background
This concerns a database which is currently accessed by multiple applications, each of which currently has its own SQL Server login, and has application-specific permissions on database objects.
I want to switch to using Windows Authentication to improve security, and I'd prefer to use Windows Groups rather than users for flexibility (I don't want the DBAs to have to manage logins for all the individual users).
However a given user may use multiple applications (and hence be a member of multiple Windows Groups that map to SQL logins), hence the potential for ambiguity in the mapping of a connection to a database user.
I've googled and searched Books Online, and can't find explicit information on how such ambiguity is resolved (e.g. precedence rules).
Any tips and best practices would be welcome in addition to an answer to the questions above.
That's an interesting question.
I'd assume that your client should have no access at all to those tables, ad DENY takes precedence over GRANT. In SQL Server, there is an exception to the DENY-overrides-GRANT principle though: when a GRANT is done on column level, it will allow access even if the table as a whole has been denied access, as MSDN states.
Edit: To understand what applies it is important to notice that the Logins (to the server) are not the same as the database users. Users which logged on through the means of a Windows group membership will get an implicitly created user, and permissions will need to be applied on that. See also this blog article for more information.