Server Permissions Audit

Applicability:

SQL Server 2000: N/A

SQL Server 2005: Tested

SQL Server 2008: Tested

SQL Server 2008R2: Tested

SQL Server 2012: Tested

SQL Server 2014: Tested

SQL Server 2016: Tested

SQL Server 2017: Tested

Credits:

Author: Jim Sebastiano

Date: 7 May 2010

Description

Lists all Server and Database roles on the server, along with their member logins and users

Code

/*************************************************************************************************

*** Server Permissions Audit ***

**************************************************************************************************


This script is used for auditing the permissions that exist on a SQL Server. It will scan every

database on the server (separate scripts to run only one database are commented at the bottom)

and return four record sets:

1. Audit who is in server-level roles

2. Audit roles on each database, defining what they are and what they can do

3. Audit the roles that users are in

4. Audit any users that have access to specific objects outside of a role


NOTE: This script was written for MS SQL Server 2005 and uses undocumented system tables, rather

than the standard MS procedures. It is likely that this script will not work in future versions

of SQL Server.


Created: 2010-05-07

Jim Sebastiano


NOTE: ChillyDBA - Tested on SQL 2017, so it's pretty safe to say it works on everything in between



*/


DECLARE @ShowOnlyThisLogin VARCHAR(50)

SET @ShowOnlyThisLogin = NULL -- leave null for all IDs, otherwise 'SomeLogin'


SET STATISTICS TIME OFF

SET STATISTICS IO OFF

SET NOCOUNT ON


DECLARE @currDB VARCHAR(100), @sql varchar(2000)

DECLARE @databases TABLE (dbname VARCHAR(100))


INSERT INTO @databases (dbname)

SELECT [Name]

FROM master.sys.databases

WHERE state_desc <> 'OFFLINE'


CREATE TABLE #AuditServerRoles

(ServerName VARCHAR(100), DatabaseName VARCHAR(100), ServerRole VARCHAR(100), MemberName VARCHAR(100))

CREATE TABLE #AuditDatabaseRoles

(ServerName VARCHAR(100), DatabaseName VARCHAR(100), RoleName VARCHAR(100), SchemaName VARCHAR(100),

ObjectName VARCHAR(100), PermissionType VARCHAR(100), StateDesc VARCHAR(100), Grantor VARCHAR(100))

CREATE TABLE #AuditDatabaseRoleAssignments

(ServerName VARCHAR(100), DatabaseName VARCHAR(100), RoleName VARCHAR(100), UserName VARCHAR(100))

CREATE TABLE #AuditUserLevelAssignments

(ServerName VARCHAR(100), DatabaseName VARCHAR(100), SchemaName VARCHAR(100), ObjectName VARCHAR(100),

ObjectType VARCHAR(100), Grantee VARCHAR(100), Grantor VARCHAR(100),

UserType VARCHAR(100), PermissionType VARCHAR(100), PermissionState VARCHAR(100))



-- Step 1: Audit who is in server-level roles

INSERT INTO #AuditServerRoles

SELECT

@@SERVERNAME AS ServerName, DB_NAME() AS DatabaseName,

SUSER_NAME(rm.role_principal_id) AS ServerRole, lgn.name AS MemberName

FROM

sys.server_role_members rm

INNER JOIN sys.server_principals lgn

ON rm.role_principal_id >=3 AND rm.role_principal_id <=10

AND rm.member_principal_id = lgn.principal_id

ORDER BY 1, 2, 3, 4


-- loop through all databases

while exists (select * from @databases)

begin

set @currDB = (select top 1 dbname from @databases order by dbname)

PRINT @currdb


-- Step 2: Audit roles on each database, defining what they are, what they can do, and who belongs in them

INSERT INTO #AuditDatabaseRoles

exec ('use ' + @currdb + ';

SELECT @@SERVERNAME AS ServerName, DB_NAME() AS DatabaseName, dprin.name AS RoleName,

ISNULL(sch.name, osch.name) AS SchemaName, ISNULL(o.name, ''.'') AS ObjectName,

dperm.permission_name, dperm.state_desc, grantor.name AS Grantor

FROM

sys.database_permissions dperm

INNER JOIN sys.database_principals dprin

ON dperm.grantee_principal_id = dprin.principal_id

INNER JOIN sys.database_principals grantor

ON dperm.grantor_principal_id = grantor.principal_id

LEFT OUTER JOIN sys.schemas sch

ON dperm.major_id = sch.schema_id AND dperm.class = 3

LEFT OUTER JOIN sys.all_objects o

ON dperm.major_id = o.OBJECT_ID AND dperm.class = 1

LEFT OUTER JOIN sys.schemas osch

ON o.schema_id = osch.schema_id

WHERE dprin.name <> ''public'' AND dperm.type <> ''CO'' AND dprin.type = ''R''

ORDER BY 1, 2, 3, 4, 5, 6')

-- Step 3: Audit the roles that users are in

INSERT INTO #AuditDatabaseRoleAssignments

exec ('use ' + @currdb + ';

SELECT

@@SERVERNAME AS ServerName, DB_NAME() AS DatabaseName,

CASE WHEN (r.principal_id IS NULL) THEN ''public''

ELSE r.name

END AS RoleName,

u.name AS UserName

FROM

sys.database_principals u

LEFT JOIN (sys.database_role_members m JOIN sys.database_principals r ON m.role_principal_id = r.principal_id)

ON m.member_principal_id = u.principal_id

ORDER BY 1, 2, 3, 4')

-- Step 4: Audit any users that have access to specific objects outside of a role

INSERT INTO #AuditUserLevelAssignments

exec ('use ' + @currdb + ';

SELECT

@@SERVERNAME AS ServerName, DB_NAME() AS DatabaseName,

ISNULL(sch.name, osch.name) AS SchemaName, ISNULL(o.name, ''.'') AS ObjectName,

o.type_desc,

dprin.NAME AS Grantee,

grantor.name AS Grantor,

dprin.type_desc AS principal_type_desc,

dperm.permission_name,

dperm.state_desc AS permission_state_desc

FROM

sys.database_permissions dperm

INNER JOIN sys.database_principals dprin

ON dperm.grantee_principal_id = dprin.principal_id

INNER JOIN sys.database_principals grantor

ON dperm.grantor_principal_id = grantor.principal_id

LEFT OUTER JOIN sys.schemas sch

ON dperm.major_id = sch.schema_id AND dperm.class = 3

LEFT OUTER JOIN sys.all_objects o

ON dperm.major_id = o.OBJECT_ID AND dperm.class = 1

LEFT OUTER JOIN sys.schemas osch

ON o.schema_id = osch.schema_id

WHERE dprin.name <> ''public'' AND dperm.type <> ''CO'' AND dprin.type <> ''R''

ORDER BY 1, 2, 3, 4, 5')


DELETE FROM @databases WHERE dbname = @currDB

END


IF @ShowOnlyThisLogin IS NULL

BEGIN

SELECT 'Server Roles', * FROM #AuditServerRoles ORDER BY 1,2,3,4,5

SELECT 'Database Roles', * FROM #AuditDatabaseRoles ORDER BY 1,2,3,4,5,6,7

SELECT 'DB Role Assignments', * FROM #AuditDatabaseRoleAssignments ORDER BY 1,2,3,4,5

SELECT 'User Level Assignments', * FROM #AuditUserLevelAssignments ORDER BY 1,2,3,4,5,6

END ELSE BEGIN

SELECT 'Server Roles', * FROM #AuditServerRoles WHERE MemberName = @ShowOnlyThisLogin ORDER BY 1,2,3,4,5

SELECT 'DB Role Assignments', * FROM #AuditDatabaseRoleAssignments WHERE UserName = @ShowOnlyThisLogin ORDER BY 1,2,3,4,5

SELECT 'User Level Assignments', * FROM #AuditUserLevelAssignments WHERE Grantee = @ShowOnlyThisLogin ORDER BY 1,2,3,4,5,6

END


DROP TABLE #AuditServerRoles, #AuditDatabaseRoles, #AuditDatabaseRoleAssignments, #AuditUserLevelAssignments