Resolving permissions when using SQL Server Windows Authentication - sql-server

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.

Related

SQL Login created but not mapped - user already exists - is there any connection between?

Greetings,
When I login into a particular MSSQL database as sa I see the following: somebody moved a database from server A to server B using restore option. I can see all the users in place (restored along with the database) - great. There are logins previously created on server A - great. All of those logins have sysadmin role. I think there's one problem - I don't see any mappings done between logins and users on server B (currently I have no access to Server A so I can't look at the configuration).
According to security properties - all of those 'local' database users are 'SQL user without login' - but I'm sure a proper application uses those users on a regular basis and there are configuration files where passwords are stored.
Question #1 - if there's a login with sysadmin role and there's a local database user of the same name (as login) - does the application use login or local db user in order to work properly? (there's no mapping between the two)
Question #2 - should mapping be done between all the logins and corresponding database users when moved from one server to another? At the moment there isn't any mapping done and my cooworkers are using logins with sysadmin role to access whole database.
Regards,
1) If a particular login has the sysadmin role the application or person using this login can do anything on the database server. It is generally not considered good practice to have a lot of sysadmin users because it opens up the database server (and more) to security breaches.
2) Mapping SQL logins to database users makes sense if the users have minimal server-wide permissions and if you want to assign several certain data access rights in different databases. For example, you have a login X but users Y and Z and want to have read-only permissions for user Y in database Y but read-write permissions for user Z in database Z; in this case mapping can be useful.
There is something else you should be mindful of. If you backup a database (including database SQL users) on server A and restore the database on server B and the database users that are residing on server A were not created on server B using the same SID for the corresponding login(s) you end up with orphaned users, meaning the name of the login is not important to SQL Server but the SID of the login is.
You can find the SIDs in system login tables:
SELECT * FROM sys.sql_logins
SELECT * FROM sys.syslogins
To make sure the login on both servers is exactly the same (same SID!) you have to create the logins using a script like this:
CREATE LOGIN MyTestUser WITH PASSWORD=N'!#MyTestPassword#$', SID=0x552C84CB83802C4A801C670265CCAFA4, DEFAULT_DATABASE=tempdb, DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
Hopefully this helps.

What are good practices for granting database permissions to a web service connection?

I have been searching for articles and SQL script examples that would demonstrate how to securely and conveniently solve one of the most common scenarios - connecting from a .Net Core Entity Framework based web application to an SQL database.
But somehow I could not find any coherent step-by-step guide from a reputable source.
Let's assume the following:
I cannot use integrated Windows auth in the connection string and must use username and password based auth (because hosting on a Linux server and the DB is on a different Windows server)
the web service will need your usual minimum set of permissions - connect to the database, read data, write data, delete data, execute stored procedures
While reading many tutorials, I find there are multiple ways to manage the connection permissions. To avoid this question being too broad, I'll list my current choices as I understand them (please correct me if I'm missing something).
Users and logins:
create a login and a user for the database
create a database-only user without a login (not sure if this is applicable to a web app and connection string, but still it's a feature that I've seen being used)
Assigning permissions:
assign the user to some fixed SQL role (db_datareader, db_datawriter AND also will have to grant EXECUTE permission)
grant all fixed permissions
create a custom role (let's say, db_web_apps) with required permissions
Which choices are better (more secure and easier to manage in general) and recommended by SQL DBAs?
I think every database administrator should have a template script handy for quickly adding a new user with minimum required permissions every time when developers ask for a new connection for their shiny new web app.
If you know a good, reliable tutorial or GitHub / Gist example that explains what and why is being done that way or a script that you yourself have used for years without any issues in production environments, I'll really appreciate if you could share it.
Create a role in the database and assign the required privileges to the role. Don't use the fixed database roles. Instead grant permissions directly to objects, schemas, or the entire database if necessary. Like this:
create role trusted_app_role
grant select, insert, update, delete, execute
on schema::dbo to trusted_app_role
That will grant the role full DML permissions on all the objects in the default dbo schema. So if you have any tables or procedures you don't want the app to have access to, just create them in a different schema, say, admin. This way you never have to fiddle with permissions as you add objects. The fixed database roles predate schema-based permissions, and aren't really needed any more.
For your application's identity, add Active Directory or Azure Active Directory (Azure SQL) identities to this role, or, if you can't, add SQL Users to the role.
If you are on Azure SQL, you should normally use a database user without a login. On SQL Server you can only add "contained database users" if you enable Partial Database Containment. Which you can do, but is incompatible with Change Tracking and Change Data Capture, so it's a tradeoff.
So normally for SQL Server you still create a login and map the user to the login. EG:
create login web_service_user with password = '5X+jeuAB6kmhw85R/AxAg'
create user web_service_user for login web_service_user
And then add that user to your role
alter role trusted_app_role add member web_service_user

User permissions in sql server DB assigned from AD groups

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;

How to map MULTIPLE ActiveDirectory Groups to SQL Logins?

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').

Finding out the windows group by virtue of which a user is able to access a database in sql server?

There is a SQL Server 2005 database with mixed-mode authentication.
Among others, we have the following logins on the server: our-domain\developers-group-1, and our-domain\developers-group-2 which are AD groups.
The our-domain\developer-group-2 is added to the sysadmin role on the server, by virture of which all domain users of that group can access any database as SQL Server implictly maps the sysadmin role to the dbo user in each database.
There are two users our-domain\good-user and our-domain\bad-user
The issue is the following: Both the good-user and the bad-user have the exact same AD group memberships. They are both members of our-domain\developers-group-1 and our-domain\developers-group-2. The good-user is able to access all the databases, and the bad-user is not. The bad-user is able to login, but he is unable access any databases. By the way, I am the good-user.
How do I go about finding out why?
Here's what I tried so far:
When I do print current_user, I get dbo
When I do print system_user, I get my-domain\good-user
When I do select * from fn_my_permissions(NULL, 'SERVER'), I see permissions.
But if do execute as user='my-domain\good-user'; select * from fn_my_permissions(NULL, 'SERVER'), I dont see any permisisons.
And When I do, execute as user='my-domain\bad-user'; select * from fn_my_permissions(NULL, 'SERVER'), I dont see any permisisons.
Also, I was wondering if there is a sql command that will tell me, "hey! the current database user is able to access this database because he is a member such-and-such ad-group, which is a login that is mapped to such-and-such user in this database".
If you have the relevant permissions within Management Studio, this shouldn't take too long to work out. It sounds like the bad-user AD group has limited permissions within SQL Server.
You need to check the settings in Security in the GUI, and check the mappings for each of these AD groups - clicking on the databases to see what permissions they have on each database.
Is it possible that you simply have implicit permissions as the creator/owner of the objects, yet no explicit permissions have been granted on the AD groups/roles or to your user individually?

Resources