When is IS_MEMBER set in Sql Server? - sql-server

I am trying to get IS_MEMBER working in a UDF in Sql Server 2005.
I have a windows group "Domain\TestGroup".
I allocate my Login "Domain\Kieran" to it.
select SUSER_NAME();
gives "Domain\Kieran"
but
select IS_MEMBER('Domain\TestGroup');
returns NULL.

The NULL answer from IS_MEMBER means that SQL Server does not recognise the Windows group.
It looks at the login token from your connection. It does not query Active Directory.
From the BOL link:
IS_MEMBER determines Windows group
membership by examining an access
token that is created by Windows. The
access token does not reflect changes
in group membership that are made
after a user connects to an instance
of SQL Server.
So, even though doamin\kieran is in the group you'll probably need to log out and back in so your login token is updated with the group membership.
It should all work in your UDF (unless you have EXECUTE AS USER or OWNER in the UDF)

Ah. I think I see the problem.
My login is in builtin\Administrators which is a member of the server fixed role sysadmin.
Therefore I'm a member of sysadmin, which means I'm dbo and won't see any role or group information.

Check your ERRORLOG and see if there is any error indicating that the SQL Server service cannot connect to the 'domain' Active Directory.

Related

SQL and Active Directory groups, Schema permissions

I have the following problem, we assign perms in SQL 2014 using ad groups. we have the following
l_sql-db-demodb-dbo: this is a local group where we assign the actual permission (dbowner against 'demodb')
g_sql-db-demodb-dbo: global group that is a member of the above
user: user is added to global group giving permissions for dbo to demodb.
This all works fine... mostly. User tries to run SQL profiler 2014 and run a trace and output trace to demodb. User can select the database, cannot select a schema.
If I assign the same exact permission set against the user account itself, it works as expected. for some reason the groups (or the nesting of groups) are killing this ability.
Note that this is SQL 2014 SP1. SP2 has not been approved for rollout, so I'm not sure if this is a bug..

Rename security group in AD, and mapped SQL login

Example:
Lets say I have a group named group_01, the group is mapped to a SQL Server an given some rights on some stuff.
When I rename the group in Active Directory to any value, lets say group_01_OLD.
The group name wont change in SQL Server, it's still group_01
Is this normal behavior? Can I force SQL to rename the group when renamed in AD?
An full answer is buried in the comments here: https://dba.stackexchange.com/questions/13766/user-windows-login-name-has-been-changed-in-ad-yet-session-in-sql-2008-profiler
Basically, a reboot of the whole server should pick up the change (assuming replication to all the DCs has already happened).
If you can't do that, you could try manually updating the name of the login:
ALTER LOGIN [domain\group_01] WITH NAME = [domain\group_01_OLD];
To complement Gabriel’s answer. Given your scenario (you have granted permissions to the group group_01 ), you must change the name in SQL using the ALTER LOGIN command
ALTER LOGIN [domain\group_01] WITH NAME = [domain\group_01_OLD];
The reason for this is that SQL Server looks for a matching login catalog views (i.e. sys.server_principals) within SQL itself before asking AD.
NOTE: When you rename a Windows login, SQL Server will verify that the new name matches the SID to verify that the login renaming is valid.
-Raul Garcia
A reboot do not fix anything as far as I've experienced. SID is of course the same but besides the change of login with...
ALTER LOGIN [domain\previousgroupname] WITH NAME = [domain\newgroupname];
...you also need to change Security\Users for each database the login has a role in, if you want the change reflected everywhere and not having mismatches between logins and users. Can be done using Management studio, editing the group at Security\Logins and Mapping. Untick database, tick and choose role again. Or using ALTER USER but that's just a lot more typing.
USE [db]
ALTER USER [domain\previousgroupname] WITH NAME=[domain\newgroupname];

IS_ROLEMEMBER erroneously returns 0 for database role members?

Running a local instance of SQL Server 2012.
I have created a custom role:
CREATE ROLE [my_user] AUTHORIZATION [dbo]
For all my users (local Windows users and SQL users), I have specified this role for my database (under the User Mappings setting). Thus, the following query should return 1:
SELECT IS_ROLEMEMBER('my_user')
For my Windows-authenticated users it does indeed return 1, but as soon as I'm logged on as an SQL user, it returns 0. I have triple-checked that the SQL user does indeed have this role. What am I missing here?
Update
Performed some more testing. This certainly is weird behavior. I performed these steps:
On my local SQL Server I created a database test with user sa. Role my_user added.
Logged on as sa in the Management Studio and added MYDOMAIN\MyUser to this role.
Re-logged on with Windows Authentication and executed IS_ROLEMEMBER('my_user'). Returns 0.
Tried the query using both sa (specifying the username) and the Windows user. Same problem.
Tried restarting the SQL Server, just in case.
This makes no sense! If I right-click the role I can see that my Windows user is indeed a member of it. The IS_ROLEMEMBER function is flawed! When I run the following query, it shows that my user is indeed a member of the database role:
SELECT
USER_NAME(memberuid), USER_NAME(groupuid)
FROM
sys.sysmembers
WHERE
USER_NAME(groupuid) = 'my_user'
This also shows my membership:
select r.name as role_name, m.name as member_name from sys.database_role_members rm
inner join sys.database_principals r on rm.role_principal_id = r.principal_id
inner join sys.database_principals m on rm.member_principal_id = m.principal_id
Some additional information:
I'm on a domain, but currently disconnected. I have seen this problem when connected too though.
Running Windows 8.1 64-bit.
Update 2
If I explicitly specify the principal as some have suggested, I get this error (executing as sa):
SELECT IS_ROLEMEMBER('my_user', 'MYDOMAIN\UserX')
Msg 15404, Level 16, State 19, Line 1
Could not obtain information about Windows NT group/user 'MYDOMAIN\UserX',
error code 0x54b.
Could it be that IS_ROLEMEMBER experiences the same problem, but does not print the error?
I just had this same issue... I found that the user in question had server roles also assigned to them. When I removed all server roles except 'public', suddenly the is_rolemember query started correctly reporting a 1 instead of the zero..... I tested this back and forth a few times to confirm.
Also had this issue. Turns out I had to remove sysadmin server role, then it worked.
This is taken from: https://learn.microsoft.com/en-us/sql/t-sql/functions/is-member-transact-sql
Members of the sysadmin fixed server role enter every database as the dbo user. Checking permission for member of the sysadmin fixed server role, checks permissions for dbo, not the original login. Since dbo can't be added to a database role and doesn’t exist in Windows groups, dbo will always return 0 (or NULL if the role doesn't exist).
Try specifying the principal explicitly.
SELECT IS_ROLEMEMBER('my_user', 'SqlLogin')
I tested this and it returned 1.
CREATE DATABASE TestDatabase;
GO
USE TestDatabase;
GO
CREATE ROLE TestRole AUTHORIZATION dbo;
GO
CREATE USER TestUser WITHOUT LOGIN;
GO
EXEC sp_addrolemember 'TestRole', 'TestUser';
GO
SELECT IS_ROLEMEMBER('TestRole', 'TestUser');
GO

SQL Server Server Logins and Database Users

At work we use AD groups to control access to SQL Server databases.
I can see these groups in Security > Logins and (database) > Security > Users.
The problem is that some DBs have 50+ such AD groups as valid logins/users and I know I am a member of more than one.
Is there a way I can determine which of these AD groups I am logged in under?
You're effectively logged in as all of them. You'll have the union of all of the individual permissions granted to each group that you're a member of.
There are 2 straight forward built in commands that can help with what you are looking for:
First the extended procedure XP_LoginInfo (available at least since SS2000) will show you all the connection paths a particular login is allowed to use to connect to the instance with
DECLARE #LoginName sysname
SELECT #LoginName = SYSTEM_USER
EXEC xp_LoginInfo #AcctName = #LoginName, #Option = 'all'
All the group names shown under the last column "permission path" are the groups that the supplied LoginName is part of. Also note the "privilege" column; it will show if a login has admin or user level rights on the instance.
Now, the function fn_my_permissions (available since SS2005) will show you all the permissions the currently connected login has on the current database or the server.
SELECT * FROM fn_my_permissions(NULL, 'DATABASE');
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
As Damien_The_Unbeliever responded on 11/28/12, basically the final list of permissions is the union of all the permissions assigned--both Grant and Deny--to each group's (and individually where an ID has been added explicitly) permission path you see by executing xp_LoginInfo.
So the answer basically is that you don't exactly connect with any one group when there are multiple allowed paths. Instead, in essence, you connect with them all. While nowhere does SQL Server clearly show or even state the 'unioned' nature of permissions, it can be inferred with the above 2 commands.
A ton of useful Security Catalog Views can be found on MSDN here.

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