Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 SQL Server Administration (2005)
 Query for logins permissions

Author  Topic 

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-03 : 15:06:42
Hello. I would like to query all SQL Server logins and report over all level of permissions. Is this easily accomplished in SQL Server 2005? Any suggestions on where to look?

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-10-03 : 15:14:59
have a look at sys.syslogins and sys.syspermissions views
Go to Top of Page

sodeep
Master Smack Fu Yak Hacker

7174 Posts

Posted - 2008-10-03 : 15:42:00
Yes. Here is what I use:

I hope you can find Server level Permission yourself

-- Database Level Permissions

select dp.name as [Owner], s.name as [Database Role/Schema], dp.type_desc,
dr.name as [Role Members], pe.name as [Schema Members], pe.[Schema Permission]
from sys.database_principals dp
left join sys.schemas s on s.principal_id = dp.principal_id
left join (select dr.role_principal_id, dp.name from sys.database_role_members dr
join sys.database_principals dp
on dr.member_principal_id = dp.principal_id) dr on dp.principal_id = dr.role_principal_id
left join (select schema_id, pr.name, pe.permission_name as [Schema Permission]
from sys.schemas s
join sys.database_permissions pe on s.schema_id = pe.major_id
join sys.database_principals pr on pe.grantee_principal_id = pr.principal_id
where pe.class_desc = 'SCHEMA' or pe.class_desc = 'DATABASE_PRINCIPAL') pe on s.schema_id = pe.schema_id
where dp.name <> 'sys' and dp.name <> 'guest' and
dp.name <> 'information_schema' and dp.name <> 'public'

-- OBJECT LEVEL PERMISSIONS --

select CASE WHEN o.type = 'P' THEN 'Stored Procedure'
WHEN o.type = 'TF' THEN 'Table Function'
WHEN o.type = 'FN' THEN 'Scalar Function'
WHEN o.type = 'U' THEN 'Table'
WHEN o.type = 'V' THEN 'View'
WHEN o.type = 'SQ' THEN 'Service Queue'
ELSE o.type
END AS [Type],
s.name as [Schema], o.name as [Object],
pr.name as [User], pe.permission_name as Permission
from sys.database_permissions pe
left join sys.database_principals pr
on pe.grantee_principal_id = pr.principal_id
join (select [object_id] as [id], [name], type, schema_id, 1 as [class] from sys.objects union
select [service_id] as [id], [name] COLLATE SQL_Latin1_General_CP1_CI_AS [name],
'Service', '0', 17 as [class] from sys.services union
select [service_contract_id] as [id], [name],
'Service Contract', '0', 16 as [class] from sys.service_contracts union
select [message_type_id] as [id], [name],
'Message Type', '0', 15 as [class] from sys.service_message_types) o
on pe.major_id = o.id and pe.class = o.class
left join sys.schemas s on o.schema_id = s.schema_id
where pr.name <> 'guest' and pr.name <> 'public'
order by pr.name, o.type, s.name, o.name
-- distinct tables by schema
select distinct o.name as [Object]
from sys.database_permissions pe
left join sys.database_principals pr
on pe.grantee_principal_id = pr.principal_id
join (select [object_id] as [id], [name], type, schema_id, 1 as [class] from sys.objects union
select [service_id] as [id], [name] COLLATE SQL_Latin1_General_CP1_CI_AS [name],
'Service', '0', 17 as [class] from sys.services union
select [service_contract_id] as [id], [name],
'Service Contract', '0', 16 as [class] from sys.service_contracts union
select [message_type_id] as [id], [name],
'Message Type', '0', 15 as [class] from sys.service_message_types) o
on pe.major_id = o.id and pe.class = o.class
left join sys.schemas s on o.schema_id = s.schema_id
where pr.name <> 'guest' and pr.name <> 'public' and s.name = 'SF'
group by o.name
order by o.name

Go to Top of Page

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-03 : 16:20:15
sodeep,thanks for the update. As far as the server roles, I'm writing something like so:

SELECT
SP.name,
SP.type_desc,
SP.is_disabled,
SP.create_date,
SP.modify_date,
SP.default_database_name,
SRBA.bulkadmin,
SRDC.dbcreator
FROM sys.server_principals AS SP
CROSS APPLY (
SELECT CASE WHEN SRM.member_principal_id IS NULL THEN 'N' ELSE 'Y' END AS bulkadmin
FROM sys.server_principals AS SR
LEFT JOIN sys.server_role_members AS SRM
ON SR.principal_id = SRM.role_principal_id
AND SRM.member_principal_id = SP.principal_id
WHERE SR.type = 'R'
AND SR.name = 'bulkadmin'
) AS SRBA
CROSS APPLY (
SELECT CASE WHEN SRM.member_principal_id IS NULL THEN 'N' ELSE 'Y' END AS dbcreator
FROM sys.server_principals AS SR
LEFT JOIN sys.server_role_members AS SRM
ON SR.principal_id = SRM.role_principal_id
AND SRM.member_principal_id = SP.principal_id
WHERE SR.type = 'R'
AND SR.name = 'dbcreator'
) AS SRDC

WHERE SP.type IN ('S', 'U', 'G') /* S = SQL Login, U = Windows Login, G = Windows Group */
ORDER BY SP.type_desc, SP.name


But I'm going to look into using PIVOT to see if I can do this w/o having to repeat the CROSS APPLY for every server role.
Go to Top of Page

sodeep
Master Smack Fu Yak Hacker

7174 Posts

Posted - 2008-10-03 : 16:25:24
I use like this:

--For Server role--

select pr.name as [Login], pe.permission_name as [Server Permission],
pr.type_desc as [Login Type], r.name as [Member]
from sys.server_permissions as pe
right join sys.server_principals as pr
ON pe.grantee_principal_id = pr.principal_id
left join (select r.role_principal_id, pr.name as name
from sys.server_role_members r
join sys.server_principals pr
on r.member_principal_id = pr.principal_id) r
on pr.principal_id = r.role_principal_id
where pr.type_desc <> 'CERTIFICATE_MAPPED_LOGIN' and pr.name <> 'public'
order by pr.name
Go to Top of Page

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-03 : 16:28:38
I'm looking to report the fixed server roles (bulkadmin, dbcreator, etc). But I also want it to be in a vertical format for each login (i.e. a Y/N column for each fixed server role).
Go to Top of Page

sodeep
Master Smack Fu Yak Hacker

7174 Posts

Posted - 2008-10-03 : 16:32:14
Then you can use simply like this.

select name , (case when sysadmin =1 then 'Y' else 'N' end)as sysadmin ,case..........................
from sys.syslogins
Go to Top of Page

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-03 : 16:42:23
Well... guess that is the easy option lol. That's what I get for running SQL Profiler over a refresh of the logins in SSMS!
Go to Top of Page

sodeep
Master Smack Fu Yak Hacker

7174 Posts

Posted - 2008-10-03 : 17:21:22
This is easy options but gives you what you are looking for:

select ss.name ,sp.type_desc, case when ss.sysadmin =1 then 'Y' else 'N' end as sysadmin,case.........
from sys.syslogins ss inner join
sys.server_principals sp
on ss.sid =sp.sid
Go to Top of Page

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-06 : 16:11:12
Actually, here is what I ended up doing. I needed to also provide each member for every domain group account setup. I borrowed all of this from various sources on the internet:


DECLARE @SQLUser TABLE (
PrincipalID INT NOT NULL,
LoginName SYSNAME NOT NULL,
DomainGroup SYSNAME NULL DEFAULT ('')
);

DECLARE @WindowsGroup TABLE (
PrincipalID INT NOT NULL,
DomainGroup SYSNAME NOT NULL
);

DECLARE @WindowUsersInGroup TABLE (
AccountName SYSNAME NOT NULL,
AccountType VARCHAR(8) NOT NULL,
Privilege VARCHAR(9) NOT NULL,
WindowsAccount SYSNAME NOT NULL,
DomainGroup SYSNAME NOT NULL,
PrincipalID INT NULL
);

/* First, insert all SQL logins (S) and Window logins (U) */
INSERT INTO @SQLUser (PrincipalID, LoginName)
SELECT SP.principal_id, SP.name
FROM sys.server_principals AS SP
WHERE SP.TYPE IN ('S', 'U') /* S = SQL Login, U = Windows Login */

/* Now, for all domain groups, obtain the member accounts that belong to each one */
INSERT INTO @WindowsGroup (PrincipalID, DomainGroup)
SELECT SP.principal_id, SP.name
FROM sys.server_principals AS SP
WHERE SP.TYPE IN ('G') /* G = Windows Group */

/* Iterate through all domain groups retrieving each domain account that belongs to that group */
DECLARE @CurrentDomainGroup SYSNAME;
DECLARE @CurrentPrincipalID INT;

SELECT TOP 1 @CurrentDomainGroup = DomainGroup, @CurrentPrincipalID = PrincipalID FROM @WindowsGroup

WHILE (@CurrentDomainGroup IS NOT NULL)
BEGIN
INSERT INTO @WindowUsersInGroup (AccountName, AccountType, Privilege, WindowsAccount, DomainGroup)
EXEC xp_logininfo @acctname=@CurrentDomainGroup, @option='members';

DELETE @WindowsGroup WHERE DomainGroup = @CurrentDomainGroup;

UPDATE @WindowUsersInGroup
SET PrincipalID = @CurrentPrincipalID
WHERE PrincipalID IS NULL

SET @CurrentDomainGroup = NULL;
SET @CurrentPrincipalID = NULL;
SELECT TOP 1 @CurrentDomainGroup = DomainGroup, @CurrentPrincipalID = PrincipalID FROM @WindowsGroup
END

INSERT INTO @SQLUser (PrincipalID, LoginName, DomainGroup)
SELECT PrincipalID, AccountName, DomainGroup
FROM @WindowUsersInGroup;

SELECT
SU.LoginName AS [Login Name],
SU.DomainGroup AS [Domain Group],
SP.type_desc AS [Login Type],
SP.is_disabled AS [Disabled],
SP.create_date AS [Create Date],
SP.modify_date AS [Modify Date],
SP.default_database_name AS [Default Database],
SL.denylogin AS [Deny Login],
SL.hasaccess AS [Has Access],
SL.isntname AS [IS NT Name],
SL.isntgroup AS [IS NT Group],
SL.isntuser AS [IS NT User],
SL.sysadmin AS [System Administrator],
SL.securityadmin AS [Security Administrator],
SL.serveradmin AS [Server Administrator],
SL.setupadmin AS [Setup Administrator],
SL.processadmin AS [Process Administrator],
SL.diskadmin AS [Disk Administrator],
SL.dbcreator AS [Database Creator],
SL.bulkadmin AS [Bulk Administrator]
FROM @SQLUser AS SU
INNER JOIN sys.server_principals AS SP
ON SU.PrincipalID = SP.principal_id
INNER JOIN sys.syslogins AS SL
ON SP.name = SL.name
ORDER BY SU.LoginName, SU.DomainGroup;

Go to Top of Page

tfountain
Constraint Violating Yak Guru

491 Posts

Posted - 2008-10-08 : 15:18:39
Ok, I have determined that just reporting over the fixed server roles will not provide the full picture of who has access to my server and what permissions they have. So I added a second query to the mix to report this. Any thoughts on if there is an easier way to obtain the information I am looking for?


SET NOCOUNT ON
GO

DECLARE @SQLMember TABLE (
PrincipalID INT NOT NULL,
MemberName SYSNAME NOT NULL
);

DECLARE @WindowsGroup TABLE (
PrincipalID INT NOT NULL,
DomainGroup SYSNAME NOT NULL
);

DECLARE @WindowUsersInGroup TABLE (
AccountName SYSNAME NOT NULL,
AccountType VARCHAR(8) NOT NULL,
Privilege VARCHAR(9) NOT NULL,
WindowsAccount SYSNAME NOT NULL,
DomainGroup SYSNAME NOT NULL,
PrincipalID INT NULL
);

/* First, insert all SQL logins (S) and Window logins (U) */
INSERT INTO @SQLMember (PrincipalID, MemberName)
SELECT SP.principal_id, SP.name
FROM sys.server_principals AS SP
WHERE SP.TYPE IN ('S', 'U', 'G') /* S = SQL Login, U = Windows Login */

/* Now, for all domain groups, obtain the member accounts that belong to each one */
INSERT INTO @WindowsGroup (PrincipalID, DomainGroup)
SELECT SP.principal_id, SP.name
FROM sys.server_principals AS SP
WHERE SP.TYPE IN ('G') /* G = Windows Group */

/* Iterate through all domain groups retrieving each domain account that belongs to that group */
DECLARE @CurrentDomainGroup SYSNAME;
DECLARE @CurrentPrincipalID INT;

SELECT TOP 1 @CurrentDomainGroup = DomainGroup, @CurrentPrincipalID = PrincipalID FROM @WindowsGroup

WHILE (@CurrentDomainGroup IS NOT NULL)
BEGIN
/* Grab all members in this group */
INSERT INTO @WindowUsersInGroup (AccountName, AccountType, Privilege, WindowsAccount, DomainGroup)
EXEC xp_logininfo @acctname=@CurrentDomainGroup, @option='members';

/* Remove this group from our list that controls the loop */
DELETE @WindowsGroup WHERE DomainGroup = @CurrentDomainGroup;

/* Stamp all the new users with this principal ID for later use */
UPDATE @WindowUsersInGroup
SET PrincipalID = @CurrentPrincipalID
WHERE PrincipalID IS NULL;

/* Get the next group - all without a cursor */
SET @CurrentDomainGroup = NULL;
SET @CurrentPrincipalID = NULL;
SELECT TOP 1 @CurrentDomainGroup = DomainGroup, @CurrentPrincipalID = PrincipalID FROM @WindowsGroup
END

/* This returns specific server roles */
SELECT
SERVERPROPERTY('SERVERNAME') AS ServerName,
R.name AS RoleName,
R.type_desc AS RoleType,
SM.MemberName AS MemberName,
M.type_desc AS MemberType,
CASE WHEN M.is_disabled = 1 THEN 'Yes' ELSE 'No' END AS Disabled,
ISNULL(LEFT(AL.AccountList, LEN(AL.AccountList) - 1), '') AS NTAccountList
FROM @SQLMember AS SM
INNER JOIN sys.server_role_members AS RM
ON SM.PrincipalID = RM.member_principal_id
INNER JOIN sys.server_principals AS R
ON RM.role_principal_id = R.principal_id
INNER JOIN sys.server_principals AS M
ON RM.member_principal_id = M.principal_id
/* For Window groups, pull off a list of network accounts from the above loop */
OUTER APPLY
(
SELECT AccountName + ', '
FROM @WindowUsersInGroup
WHERE PrincipalID = SM.PrincipalID
ORDER BY AccountName
FOR XML PATH('')
) AS AL (AccountList)
ORDER BY
R.name,
CASE
WHEN M.type_desc = 'SQL_LOGIN' THEN 1
WHEN M.type_desc = 'WINDOWS_LOGIN' THEN 2
WHEN M.type_desc = 'WINDOWS_GROUP' THEN 3
END,
SM.MemberName;

/* This returns specific server permissions */
SELECT
SERVERPROPERTY('SERVERNAME') AS ServerName,
P.class_desc AS PermissionClass,
P.state_desc AS PermissionState,
ISNULL(LEFT(PL.PermissionList, LEN(PL.PermissionList) - 1), '') AS PermissionList,
SM.MemberName AS MemberName,
SP.type_desc AS MemberType,
CASE WHEN SP.is_disabled = 1 THEN 'Yes' ELSE 'No' END AS Disabled,
ISNULL(LEFT(AL.AccountList, LEN(AL.AccountList) - 1), '') AS NTAccountList
FROM @SQLMember AS SM
INNER JOIN sys.server_principals AS SP
ON SM.PrincipalID = SP.principal_id
INNER JOIN (SELECT DISTINCT class, class_desc, major_id, minor_id, grantee_principal_id, grantor_principal_id, state, state_desc FROM sys.server_permissions) AS P
ON SP.principal_id = P.grantee_principal_id
CROSS APPLY (
SELECT permission_name + ', '
FROM sys.server_permissions
WHERE class = P.class
AND class_desc = P.class_desc
AND major_id = P.major_id
AND minor_id = P.minor_id
AND grantee_principal_id = P.grantee_principal_id
AND grantor_principal_id = P.grantor_principal_id
AND state = P.state
AND state_desc = P.state_desc
ORDER BY permission_name
FOR XML PATH('')
) AS PL (PermissionList)
/* For Window groups, pull off a list of network accounts from the above loop */
OUTER APPLY
(
SELECT AccountName + ', '
FROM @WindowUsersInGroup
WHERE PrincipalID = SM.PrincipalID
ORDER BY AccountName
FOR XML PATH('')
) AS AL (AccountList)
ORDER BY
SERVERPROPERTY('SERVERNAME'),
P.class_desc,
P.state_desc,
CASE
WHEN SP.type_desc = 'SQL_LOGIN' THEN 1
WHEN SP.type_desc = 'WINDOWS_LOGIN' THEN 2
WHEN SP.type_desc = 'WINDOWS_GROUP' THEN 3
END,
SM.MemberName;
Go to Top of Page
   

- Advertisement -