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.
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 |
|
|
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 Permissionsselect 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_idleft join (select dr.role_principal_id, dp.name from sys.database_role_members dr join sys.database_principals dpon dr.member_principal_id = dp.principal_id) dr on dp.principal_id = dr.role_principal_idleft 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_idjoin sys.database_principals pr on pe.grantee_principal_id = pr.principal_idwhere pe.class_desc = 'SCHEMA' or pe.class_desc = 'DATABASE_PRINCIPAL') pe on s.schema_id = pe.schema_idwhere 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.typeEND AS [Type],s.name as [Schema], o.name as [Object],pr.name as [User], pe.permission_name as Permissionfrom sys.database_permissions peleft join sys.database_principals pron pe.grantee_principal_id = pr.principal_idjoin (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 unionselect [service_contract_id] as [id], [name],'Service Contract', '0', 16 as [class] from sys.service_contracts unionselect [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.classleft join sys.schemas s on o.schema_id = s.schema_idwhere 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 peleft join sys.database_principals pron pe.grantee_principal_id = pr.principal_idjoin (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 unionselect [service_contract_id] as [id], [name],'Service Contract', '0', 16 as [class] from sys.service_contracts unionselect [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.classleft join sys.schemas s on o.schema_id = s.schema_idwhere pr.name <> 'guest' and pr.name <> 'public' and s.name = 'SF'group by o.nameorder by o.name |
|
|
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.dbcreatorFROM 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 SRDCWHERE 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. |
|
|
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 prON pe.grantee_principal_id = pr.principal_idleft join (select r.role_principal_id, pr.name as namefrom sys.server_role_members rjoin sys.server_principals pr on r.member_principal_id = pr.principal_id) ron pr.principal_id = r.role_principal_idwhere pr.type_desc <> 'CERTIFICATE_MAPPED_LOGIN' and pr.name <> 'public'order by pr.name |
|
|
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). |
|
|
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 |
|
|
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! |
|
|
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 spon ss.sid =sp.sid |
|
|
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.nameFROM sys.server_principals AS SPWHERE 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.nameFROM sys.server_principals AS SPWHERE 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 @WindowsGroupWHILE (@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 ENDINSERT INTO @SQLUser (PrincipalID, LoginName, DomainGroup)SELECT PrincipalID, AccountName, DomainGroupFROM @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.nameORDER BY SU.LoginName, SU.DomainGroup; |
|
|
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 ONGODECLARE @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.nameFROM sys.server_principals AS SPWHERE 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.nameFROM sys.server_principals AS SPWHERE 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 @WindowsGroupWHILE (@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 NTAccountListFROM @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 NTAccountListFROM @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; |
|
|
|
|
|
|
|