无法评论已接受的答案,所以我在这里添加一些评论:
sys.objects
sys.schemas
[ObjectType]
obj.type_desc
OBJECT_OR_COLUMN
perm.[class_desc]
IMPERSONATE
LEFT JOIN
sys.database_principals
perm.major_id = imp.principal_id
sys.login_token
sys.server_principals
'G'
sys
INFORMATION_SCHEMA
我将发布所有建议修复的第一段脚本,其他部分也应该更改:
SELECT [UserName] = ulogin.[name], [UserType] = CASE princ.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' WHEN 'G' THEN 'Windows Group' END, [DatabaseUserName] = princ.[name], [Role] = null, [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = CASE perm.[class] WHEN 1 THEN obj.type_desc -- Schema-contained objects ELSE perm.[class_desc] -- Higher-level objects END, [ObjectName] = CASE perm.[class] WHEN 1 THEN OBJECT_NAME(perm.major_id) -- General objects WHEN 3 THEN schem.[name] -- Schemas WHEN 4 THEN imp.[name] -- Impersonations END, [ColumnName] = col.[name] FROM --database user sys.database_principals princ LEFT JOIN --Login accounts sys.server_principals ulogin on princ.[sid] = ulogin.[sid] LEFT JOIN --Permissions sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id] LEFT JOIN --Table columns sys.columns col ON col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] LEFT JOIN sys.objects obj ON perm.[major_id] = obj.[object_id] LEFT JOIN sys.schemas schem ON schem.[schema_id] = perm.[major_id] LEFT JOIN sys.database_principals imp ON imp.[principal_id] = perm.[major_id] WHERE princ.[type] IN ('S','U','G') AND -- No need for these system accounts princ.[name] NOT IN ('sys', 'INFORMATION_SCHEMA')
非常感谢精彩的审计脚本。
我强烈建议审核用户使用真棒Kenneth Fisher( b | Ť )存储过程:
以下是Jeremy 2011年8月查询的完整版本,其中Brad(2011年10月)和iw.kuchin(2012年5月)建议的更改包含:
[ObjectName]
希望这可以节省其他人一两个小时的生命。 :)
:)
/* Security Audit Report 1) List all access provisioned to a SQL user or Windows user/group directly 2) List all access provisioned to a SQL user or Windows user/group through a database or application role 3) List all access provisioned to the public role Columns Returned: UserType : Value will be either 'SQL User', 'Windows User', or 'Windows Group'. This reflects the type of user/group defined for the SQL Server account. DatabaseUserName: Name of the associated user as defined in the database user account. The database user may not be the same as the server user. LoginName : SQL or Windows/Active Directory user account. This could also be an Active Directory group. Role : The role name. This will be null if the associated permissions to the object are defined at directly on the user account, otherwise this will be the name of the role that the user is a member of. PermissionType : Type of permissions the user/role has on an object. Examples could include CONNECT, EXECUTE, SELECT DELETE, INSERT, ALTER, CONTROL, TAKE OWNERSHIP, VIEW DEFINITION, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. PermissionState : Reflects the state of the permission type, examples could include GRANT, DENY, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ObjectType : Type of object the user/role is assigned permissions on. Examples could include USER_TABLE, SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. Schema : Name of the schema the object is in. ObjectName : Name of the object that the user/role is assigned permissions on. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ColumnName : Name of the column of the object that the user/role is assigned permissions on. This value is only populated if the object is a table, view or a table value function. */ --1) List all access provisioned to a SQL user or Windows user/group directly SELECT [UserType] = CASE princ.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' WHEN 'G' THEN 'Windows Group' END, [DatabaseUserName] = princ.[name], [LoginName] = ulogin.[name], [Role] = NULL, [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects ELSE perm.[class_desc] -- Higher-level objects END, [Schema] = objschem.[name], [ObjectName] = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas WHEN 4 THEN imp.[name] -- Impersonations ELSE OBJECT_NAME(perm.[major_id]) -- General objects END, [ColumnName] = col.[name] FROM --Database user sys.database_principals AS princ --Login accounts LEFT JOIN sys.server_principals AS ulogin ON ulogin.[sid] = princ.[sid] --Permissions LEFT JOIN sys.database_permissions AS perm ON perm.[grantee_principal_id] = princ.[principal_id] LEFT JOIN sys.schemas AS permschem ON permschem.[schema_id] = perm.[major_id] LEFT JOIN sys.objects AS obj ON obj.[object_id] = perm.[major_id] LEFT JOIN sys.schemas AS objschem ON objschem.[schema_id] = obj.[schema_id] --Table columns LEFT JOIN sys.columns AS col ON col.[object_id] = perm.[major_id] AND col.[column_id] = perm.[minor_id] --Impersonations LEFT JOIN sys.database_principals AS imp ON imp.[principal_id] = perm.[major_id] WHERE princ.[type] IN ('S','U','G') -- No need for these system accounts AND princ.[name] NOT IN ('sys', 'INFORMATION_SCHEMA') UNION --2) List all access provisioned to a SQL user or Windows user/group through a database or application role SELECT [UserType] = CASE membprinc.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' WHEN 'G' THEN 'Windows Group' END, [DatabaseUserName] = membprinc.[name], [LoginName] = ulogin.[name], [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects ELSE perm.[class_desc] -- Higher-level objects END, [Schema] = objschem.[name], [ObjectName] = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas WHEN 4 THEN imp.[name] -- Impersonations ELSE OBJECT_NAME(perm.[major_id]) -- General objects END, [ColumnName] = col.[name] FROM --Role/member associations sys.database_role_members AS members --Roles JOIN sys.database_principals AS roleprinc ON roleprinc.[principal_id] = members.[role_principal_id] --Role members (database users) JOIN sys.database_principals AS membprinc ON membprinc.[principal_id] = members.[member_principal_id] --Login accounts LEFT JOIN sys.server_principals AS ulogin ON ulogin.[sid] = membprinc.[sid] --Permissions LEFT JOIN sys.database_permissions AS perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN sys.schemas AS permschem ON permschem.[schema_id] = perm.[major_id] LEFT JOIN sys.objects AS obj ON obj.[object_id] = perm.[major_id] LEFT JOIN sys.schemas AS objschem ON objschem.[schema_id] = obj.[schema_id] --Table columns LEFT JOIN sys.columns AS col ON col.[object_id] = perm.[major_id] AND col.[column_id] = perm.[minor_id] --Impersonations LEFT JOIN sys.database_principals AS imp ON imp.[principal_id] = perm.[major_id] WHERE membprinc.[type] IN ('S','U','G') -- No need for these system accounts AND membprinc.[name] NOT IN ('sys', 'INFORMATION_SCHEMA') UNION --3) List all access provisioned to the public role, which everyone gets by default SELECT [UserType] = '{All Users}', [DatabaseUserName] = '{All Users}', [LoginName] = '{All Users}', [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects ELSE perm.[class_desc] -- Higher-level objects END, [Schema] = objschem.[name], [ObjectName] = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas WHEN 4 THEN imp.[name] -- Impersonations ELSE OBJECT_NAME(perm.[major_id]) -- General objects END, [ColumnName] = col.[name] FROM --Roles sys.database_principals AS roleprinc --Role permissions LEFT JOIN sys.database_permissions AS perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN sys.schemas AS permschem ON permschem.[schema_id] = perm.[major_id] --All objects JOIN sys.objects AS obj ON obj.[object_id] = perm.[major_id] LEFT JOIN sys.schemas AS objschem ON objschem.[schema_id] = obj.[schema_id] --Table columns LEFT JOIN sys.columns AS col ON col.[object_id] = perm.[major_id] AND col.[column_id] = perm.[minor_id] --Impersonations LEFT JOIN sys.database_principals AS imp ON imp.[principal_id] = perm.[major_id] WHERE roleprinc.[type] = 'R' AND roleprinc.[name] = 'public' AND obj.[is_ms_shipped] = 0 ORDER BY [UserType], [DatabaseUserName], [LoginName], [Role], [Schema], [ObjectName], [ColumnName], [PermissionType], [PermissionState], [ObjectType]
上面的GetPermissions存储过程很好但是它使用Sp_msforeachdb,这意味着如果您的SQL实例具有包含空格或短划线和其他非最佳实践字符的任何数据库名称,它将会中断。我创建了一个避免使用Sp_msforeachdb的版本,还包括两个指示1的列 - 如果Login是sysadmin登录(IsSysAdminLogin),则为2 - 如果登录是孤儿用户(IsEmptyRow)。
USE [master] ; GO IF EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.uspGetPermissionsOfAllLogins_DBsOnColumns') AND [type] in (N'P',N'PC') ) BEGIN DROP PROCEDURE dbo.uspGetPermissionsOfAllLogins_DBsOnColumns ; END GO CREATE PROCEDURE dbo.uspGetPermissionsOfAllLogins_DBsOnColumns AS SET NOCOUNT ON ; BEGIN TRY IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].dbo.[#permission]') ) DROP TABLE #permission ; IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].dbo.[#userroles_kk]') ) DROP TABLE #userroles_kk ; IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].dbo.[#rolemember_kk]') ) DROP TABLE #rolemember_kk ; IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = object_id(N'[tempdb].dbo.[##db_name]') ) DROP TABLE ##db_name ; DECLARE @db_name VARCHAR(255) ,@sql_text VARCHAR(MAX) ; SET @sql_text = 'CREATE TABLE ##db_name ( LoginUserName VARCHAR(MAX) ,' ; DECLARE cursDBs CURSOR FOR SELECT [name] FROM sys.databases ORDER BY [name] ; OPEN cursDBs ; FETCH NEXT FROM cursDBs INTO @db_name WHILE @@FETCH_STATUS = 0 BEGIN SET @sql_text = @sql_text + QUOTENAME(@db_name) + ' VARCHAR(MAX) ,' FETCH NEXT FROM cursDBs INTO @db_name END CLOSE cursDBs ; SET @sql_text = @sql_text + 'IsSysAdminLogin CHAR(1) ,IsEmptyRow CHAR(1) )' --PRINT @sql_text EXEC (@sql_text) ; DEALLOCATE cursDBs ; DECLARE @RoleName VARCHAR(255) ,@UserName VARCHAR(255) ; CREATE TABLE #permission ( LoginUserName VARCHAR(255) ,databasename VARCHAR(255) ,[role] VARCHAR(255) ) ; DECLARE cursSysSrvPrinName CURSOR FOR SELECT [name] FROM sys.server_principals WHERE [type] IN ( 'S', 'U', 'G' ) AND principal_id > 4 AND [name] NOT LIKE '##%' ORDER BY [name] ; OPEN cursSysSrvPrinName ; FETCH NEXT FROM cursSysSrvPrinName INTO @UserName WHILE @@FETCH_STATUS = 0 BEGIN CREATE TABLE #userroles_kk ( databasename VARCHAR(255) ,[role] VARCHAR(255) ) ; CREATE TABLE #rolemember_kk ( dbrole VARCHAR(255) ,membername VARCHAR(255) ,membersid VARBINARY(2048) ) ; DECLARE cursDatabases CURSOR FAST_FORWARD LOCAL FOR SELECT [name] FROM sys.databases ORDER BY [name] ; OPEN cursDatabases ; DECLARE @DBN VARCHAR(255) ,@sqlText NVARCHAR(4000) ; FETCH NEXT FROM cursDatabases INTO @DBN WHILE @@FETCH_STATUS = 0 BEGIN SET @sqlText = N'USE ' + QUOTENAME(@DBN) + '; TRUNCATE TABLE #RoleMember_kk INSERT INTO #RoleMember_kk EXEC sp_helprolemember INSERT INTO #UserRoles_kk (DatabaseName,[Role]) SELECT db_name(),dbRole FROM #RoleMember_kk WHERE MemberName = ''' + @UserName + ''' ' --PRINT @sqlText ; EXEC sp_executesql @sqlText ; FETCH NEXT FROM cursDatabases INTO @DBN END CLOSE cursDatabases ; DEALLOCATE cursDatabases ; INSERT INTO #permission SELECT @UserName 'user' ,b.name ,u.[role] FROM sys.sysdatabases b LEFT JOIN #userroles_kk u ON QUOTENAME(u.databasename) = QUOTENAME(b.name) ORDER BY 1 ; DROP TABLE #userroles_kk ; DROP TABLE #rolemember_kk ; FETCH NEXT FROM cursSysSrvPrinName INTO @UserName END CLOSE cursSysSrvPrinName ; DEALLOCATE cursSysSrvPrinName ; TRUNCATE TABLE ##db_name ; DECLARE @d1 VARCHAR(MAX) ,@d2 VARCHAR(MAX) ,@d3 VARCHAR(MAX) ,@ss VARCHAR(MAX) ; DECLARE cursPermisTable CURSOR FOR SELECT * FROM #permission ORDER BY 2 DESC ; OPEN cursPermisTable ; FETCH NEXT FROM cursPermisTable INTO @d1,@d2,@d3 WHILE @@FETCH_STATUS = 0 BEGIN IF NOT EXISTS ( SELECT 1 FROM ##db_name WHERE LoginUserName = @d1 ) BEGIN SET @ss = 'INSERT INTO ##db_name(LoginUserName) VALUES (''' + @d1 + ''')' EXEC (@ss) ; SET @ss = 'UPDATE ##db_name SET ' + @d2 + ' = ''' + @d3 + ''' WHERE LoginUserName = ''' + @d1 + '''' EXEC (@ss) ; END ELSE BEGIN DECLARE @var NVARCHAR(MAX) ,@ParmDefinition NVARCHAR(MAX) ,@var1 NVARCHAR(MAX) ; SET @var = N'SELECT @var1 = ' + QUOTENAME(@d2) + ' FROM ##db_name WHERE LoginUserName = ''' + @d1 + '''' ; SET @ParmDefinition = N'@var1 NVARCHAR(600) OUTPUT ' ; EXECUTE Sp_executesql @var,@ParmDefinition,@var1 = @var1 OUTPUT ; SET @var1 = ISNULL(@var1, ' ') ; SET @var = ' UPDATE ##db_name SET ' + @d2 + '=''' + @var1 + ' ' + @d3 + ''' WHERE LoginUserName = ''' + @d1 + ''' ' ; EXEC (@var) ; END FETCH NEXT FROM cursPermisTable INTO @d1,@d2,@d3 END CLOSE cursPermisTable ; DEALLOCATE cursPermisTable ; UPDATE ##db_name SET IsSysAdminLogin = 'Y' FROM ##db_name TT INNER JOIN dbo.syslogins SL ON TT.LoginUserName = SL.[name] WHERE SL.sysadmin = 1 ; DECLARE cursDNamesAsColumns CURSOR FAST_FORWARD LOCAL FOR SELECT [name] FROM tempdb.sys.columns WHERE OBJECT_ID = OBJECT_ID('tempdb..##db_name') AND [name] NOT IN ('LoginUserName','IsEmptyRow') ORDER BY [name] ; OPEN cursDNamesAsColumns ; DECLARE @ColN VARCHAR(255) ,@tSQLText NVARCHAR(4000) ; FETCH NEXT FROM cursDNamesAsColumns INTO @ColN WHILE @@FETCH_STATUS = 0 BEGIN SET @tSQLText = N'UPDATE ##db_name SET IsEmptyRow = ''N'' WHERE IsEmptyRow IS NULL AND ' + QUOTENAME(@ColN) + ' IS NOT NULL ; ' --PRINT @tSQLText ; EXEC sp_executesql @tSQLText ; FETCH NEXT FROM cursDNamesAsColumns INTO @ColN END CLOSE cursDNamesAsColumns ; DEALLOCATE cursDNamesAsColumns ; UPDATE ##db_name SET IsEmptyRow = 'Y' WHERE IsEmptyRow IS NULL ; UPDATE ##db_name SET IsSysAdminLogin = 'N' FROM ##db_name TT INNER JOIN dbo.syslogins SL ON TT.LoginUserName = SL.[name] WHERE SL.sysadmin = 0 ; SELECT * FROM ##db_name ; DROP TABLE ##db_name ; DROP TABLE #permission ; END TRY BEGIN CATCH DECLARE @cursDBs_Status INT ,@cursSysSrvPrinName_Status INT ,@cursDatabases_Status INT ,@cursPermisTable_Status INT ,@cursDNamesAsColumns_Status INT ; SELECT @cursDBs_Status = CURSOR_STATUS('GLOBAL','cursDBs') ,@cursSysSrvPrinName_Status = CURSOR_STATUS('GLOBAL','cursSysSrvPrinName') ,@cursDatabases_Status = CURSOR_STATUS('GLOBAL','cursDatabases') ,@cursPermisTable_Status = CURSOR_STATUS('GLOBAL','cursPermisTable') ,@cursDNamesAsColumns_Status = CURSOR_STATUS('GLOBAL','cursPermisTable') ; IF @cursDBs_Status > -2 BEGIN CLOSE cursDBs ; DEALLOCATE cursDBs ; END IF @cursSysSrvPrinName_Status > -2 BEGIN CLOSE cursSysSrvPrinName ; DEALLOCATE cursSysSrvPrinName ; END IF @cursDatabases_Status > -2 BEGIN CLOSE cursDatabases ; DEALLOCATE cursDatabases ; END IF @cursPermisTable_Status > -2 BEGIN CLOSE cursPermisTable ; DEALLOCATE cursPermisTable ; END IF @cursDNamesAsColumns_Status > -2 BEGIN CLOSE cursDNamesAsColumns ; DEALLOCATE cursDNamesAsColumns ; END SELECT ErrorNum = ERROR_NUMBER(),ErrorMsg = ERROR_MESSAGE() ; END CATCH GO /* EXEC [master].dbo.uspGetPermissionsOfAllLogins_DBsOnColumns ; */
根据Andomar的建议,这是我在查询中的第一次破解。此查询旨在提供用户直接应用于用户帐户或通过的权限列表 用户拥有的角色。
/* Security Audit Report 1) List all access provisioned to a sql user or windows user/group directly 2) List all access provisioned to a sql user or windows user/group through a database or application role 3) List all access provisioned to the public role Columns Returned: UserName : SQL or Windows/Active Directory user cccount. This could also be an Active Directory group. UserType : Value will be either 'SQL User' or 'Windows User'. This reflects the type of user defined for the SQL Server user account. DatabaseUserName: Name of the associated user as defined in the database user account. The database user may not be the same as the server user. Role : The role name. This will be null if the associated permissions to the object are defined at directly on the user account, otherwise this will be the name of the role that the user is a member of. PermissionType : Type of permissions the user/role has on an object. Examples could include CONNECT, EXECUTE, SELECT DELETE, INSERT, ALTER, CONTROL, TAKE OWNERSHIP, VIEW DEFINITION, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. PermissionState : Reflects the state of the permission type, examples could include GRANT, DENY, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ObjectType : Type of object the user/role is assigned permissions on. Examples could include USER_TABLE, SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ObjectName : Name of the object that the user/role is assigned permissions on. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ColumnName : Name of the column of the object that the user/role is assigned permissions on. This value is only populated if the object is a table, view or a table value function. */ --List all access provisioned to a sql user or windows user/group directly SELECT [UserName] = CASE princ.[type] WHEN 'S' THEN princ.[name] WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI END, [UserType] = CASE princ.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' END, [DatabaseUserName] = princ.[name], [Role] = null, [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --database user sys.database_principals princ LEFT JOIN --Login accounts sys.login_token ulogin on princ.[sid] = ulogin.[sid] LEFT JOIN --Permissions sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id] LEFT JOIN --Table columns sys.columns col ON col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] LEFT JOIN sys.objects obj ON perm.[major_id] = obj.[object_id] WHERE princ.[type] in ('S','U') UNION --List all access provisioned to a sql user or windows user/group through a database or application role SELECT [UserName] = CASE memberprinc.[type] WHEN 'S' THEN memberprinc.[name] WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI END, [UserType] = CASE memberprinc.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' END, [DatabaseUserName] = memberprinc.[name], [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --Role/member associations sys.database_role_members members JOIN --Roles sys.database_principals roleprinc ON roleprinc.[principal_id] = members.[role_principal_id] JOIN --Role members (database users) sys.database_principals memberprinc ON memberprinc.[principal_id] = members.[member_principal_id] LEFT JOIN --Login accounts sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid] LEFT JOIN --Permissions sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN --Table columns sys.columns col on col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] LEFT JOIN sys.objects obj ON perm.[major_id] = obj.[object_id] UNION --List all access provisioned to the public role, which everyone gets by default SELECT [UserName] = '{All Users}', [UserType] = '{All Users}', [DatabaseUserName] = '{All Users}', [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --Roles sys.database_principals roleprinc LEFT JOIN --Role permissions sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN --Table columns sys.columns col on col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] JOIN --All objects sys.objects obj ON obj.[object_id] = perm.[major_id] WHERE --Only roles roleprinc.[type] = 'R' AND --Only public role roleprinc.[name] = 'public' AND --Only objects of ours, not the MS objects obj.is_ms_shipped = 0 ORDER BY princ.[Name], OBJECT_NAME(perm.major_id), col.[name], perm.[permission_name], perm.[state_desc], obj.type_desc--perm.[class_desc]
从SQL Server 2005开始,您可以使用系统视图。例如,此查询列出数据库中的所有用户及其权限:
select princ.name , princ.type_desc , perm.permission_name , perm.state_desc , perm.class_desc , object_name(perm.major_id) from sys.database_principals princ left join sys.database_permissions perm on perm.grantee_principal_id = princ.principal_id
请注意,用户也可以通过角色获得权限。例如, db_data_reader 角色授予 select 大多数对象的权利。
db_data_reader
select
CREATE PROCEDURE Get_permission AS DECLARE @db_name VARCHAR(200), @sql_text VARCHAR(max) SET @sql_text='Create table ##db_name (user_name varchar(max),' DECLARE db_cursor CURSOR FOR SELECT name FROM sys.databases OPEN db_cursor FETCH next FROM db_cursor INTO @db_name WHILE @@FETCH_STATUS = 0 BEGIN SET @sql_text=@sql_text + @db_name + ' varchar(max),' FETCH next FROM db_cursor INTO @db_name END CLOSE db_cursor SET @sql_text=@sql_text + 'Server_perm varchar(max))' EXEC (@sql_text) DEALLOCATE db_cursor DECLARE @RoleName VARCHAR(50) DECLARE @UserName VARCHAR(50) DECLARE @CMD VARCHAR(1000) CREATE TABLE #permission ( user_name VARCHAR(50), databasename VARCHAR(50), role VARCHAR(50) ) DECLARE longspcur CURSOR FOR SELECT name FROM sys.server_principals WHERE type IN ( 'S', 'U', 'G' ) AND principal_id > 4 AND name NOT LIKE '##%' AND name <> 'NT AUTHORITY\SYSTEM' AND name <> 'ONDEMAND\Administrator' AND name NOT LIKE 'steel%' OPEN longspcur FETCH next FROM longspcur INTO @UserName WHILE @@FETCH_STATUS = 0 BEGIN CREATE TABLE #userroles_kk ( databasename VARCHAR(50), role VARCHAR(50) ) CREATE TABLE #rolemember_kk ( dbrole VARCHAR(100), membername VARCHAR(100), membersid VARBINARY(2048) ) SET @CMD = 'use ? truncate table #RoleMember_kk insert into #RoleMember_kk exec sp_helprolemember insert into #UserRoles_kk (DatabaseName, Role) select db_name(), dbRole from #RoleMember_kk where MemberName = ''' + @UserName + '''' EXEC Sp_msforeachdb @CMD INSERT INTO #permission SELECT @UserName 'user', b.name, u.role FROM sys.sysdatabases b LEFT OUTER JOIN #userroles_kk u ON u.databasename = b.name --and u.Role='db_owner' ORDER BY 1 DROP TABLE #userroles_kk; DROP TABLE #rolemember_kk; FETCH next FROM longspcur INTO @UserName END CLOSE longspcur DEALLOCATE longspcur TRUNCATE TABLE ##db_name DECLARE @d1 VARCHAR(max), @d2 VARCHAR(max), @d3 VARCHAR(max), @ss VARCHAR(max) DECLARE perm_cur CURSOR FOR SELECT * FROM #permission ORDER BY 2 DESC OPEN perm_cur FETCH next FROM perm_cur INTO @d1, @d2, @d3 WHILE @@FETCH_STATUS = 0 BEGIN IF NOT EXISTS(SELECT 1 FROM ##db_name WHERE user_name = @d1) BEGIN SET @ss='insert into ##db_name(user_name) values (''' + @d1 + ''')' EXEC (@ss) SET @ss='update ##db_name set ' + @d2 + '=''' + @d3 + ''' where user_name=''' + @d1 + '''' EXEC (@ss) END ELSE BEGIN DECLARE @var NVARCHAR(max), @ParmDefinition NVARCHAR(max), @var1 NVARCHAR(max) SET @var = N'select @var1=' + @d2 + ' from ##db_name where USER_NAME=''' + @d1 + ''''; SET @ParmDefinition = N'@var1 nvarchar(300) OUTPUT'; EXECUTE Sp_executesql @var, @ParmDefinition, @var1=@var1 output; SET @var1=Isnull(@var1, ' ') SET @var= ' update ##db_name set ' + @d2 + '=''' + @var1 + ' ' + @d3 + ''' where user_name=''' + @d1 + ''' ' EXEC (@var) END FETCH next FROM perm_cur INTO @d1, @d2, @d3 END CLOSE perm_cur DEALLOCATE perm_cur SELECT * FROM ##db_name DROP TABLE ##db_name DROP TABLE #permission
不幸的是,由于声誉不足,我无法对Sean Rose帖子发表评论,但是我不得不修改脚本的“公共”角色部分,因为它没有显示SCHEMA范围的权限,因为(INNER)JOIN对sys。对象。之后更改为LEFT JOIN我还需要修改WHERE子句逻辑以省略系统对象。我对公共权限的修改查询如下。
--3) List all access provisioned to the public role, which everyone gets by default SELECT @@servername ServerName , db_name() DatabaseName , [UserType] = '{All Users}', [DatabaseUserName] = '{All Users}', [LoginName] = '{All Users}', [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = CASE perm.[class] WHEN 1 THEN obj.[type_desc] -- Schema-contained objects ELSE perm.[class_desc] -- Higher-level objects END, [Schema] = objschem.[name], [ObjectName] = CASE perm.[class] WHEN 3 THEN permschem.[name] -- Schemas WHEN 4 THEN imp.[name] -- Impersonations ELSE OBJECT_NAME(perm.[major_id]) -- General objects END, [ColumnName] = col.[name] FROM --Roles sys.database_principals AS roleprinc --Role permissions LEFT JOIN sys.database_permissions AS perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN sys.schemas AS permschem ON permschem.[schema_id] = perm.[major_id] --All objects LEFT JOIN sys.objects AS obj ON obj.[object_id] = perm.[major_id] LEFT JOIN sys.schemas AS objschem ON objschem.[schema_id] = obj.[schema_id] --Table columns LEFT JOIN sys.columns AS col ON col.[object_id] = perm.[major_id] AND col.[column_id] = perm.[minor_id] --Impersonations LEFT JOIN sys.database_principals AS imp ON imp.[principal_id] = perm.[major_id] WHERE roleprinc.[type] = 'R' AND roleprinc.[name] = 'public' AND isnull(obj.[is_ms_shipped], 0) = 0 AND isnull(object_schema_name(perm.[major_id]), '') <> 'sys' ORDER BY [UserType], [DatabaseUserName], [LoginName], [Role], [Schema], [ObjectName], [ColumnName], [PermissionType], [PermissionState], [ObjectType]
令人敬畏的剧本杰里米和贡献者!谢谢!
我有大量用户,所以为所有用户运行这是一个噩梦。我无法添加评论,所以我发布了包含更改的整个脚本。我添加了一个变量+ where子句,因此我可以在用户名中搜索最多匹配5个字符的任何内容(或者在留空时搜索所有用户)。没什么特别的,但我认为在一些用例中会有所帮助。
DECLARE @p_userName NVARCHAR(5) = 'UName' -- Specify up to five characters here (or none for all users) /* Security Audit Report 1) List all access provisioned to a sql user or windows user/group directly 2) List all access provisioned to a sql user or windows user/group through a database or application role 3) List all access provisioned to the public role Columns Returned: UserName : SQL or Windows/Active Directory user cccount. This could also be an Active Directory group. UserType : Value will be either 'SQL User' or 'Windows User'. This reflects the type of user defined for the SQL Server user account. DatabaseUserName: Name of the associated user as defined in the database user account. The database user may not be the same as the server user. Role : The role name. This will be null if the associated permissions to the object are defined at directly on the user account, otherwise this will be the name of the role that the user is a member of. PermissionType : Type of permissions the user/role has on an object. Examples could include CONNECT, EXECUTE, SELECT, DELETE, INSERT, ALTER, CONTROL, TAKE OWNERSHIP, VIEW DEFINITION, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. PermissionState : Reflects the state of the permission type, examples could include GRANT, DENY, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ObjectType : Type of object the user/role is assigned permissions on. Examples could include USER_TABLE, SQL_SCALAR_FUNCTION, SQL_INLINE_TABLE_VALUED_FUNCTION, SQL_STORED_PROCEDURE, VIEW, etc. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ObjectName : Name of the object that the user/role is assigned permissions on. This value may not be populated for all roles. Some built in roles have implicit permission definitions. ColumnName : Name of the column of the object that the user/role is assigned permissions on. This value is only populated if the object is a table, view or a table value function. */ DECLARE @userName NVARCHAR(4) = @p_UserName + '%' --List all access provisioned to a sql user or windows user/group directly SELECT [UserName] = CASE princ.[type] WHEN 'S' THEN princ.[name] WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI END, [UserType] = CASE princ.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' END, [DatabaseUserName] = princ.[name], [Role] = null, [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --database user sys.database_principals princ LEFT JOIN --Login accounts sys.login_token ulogin on princ.[sid] = ulogin.[sid] LEFT JOIN --Permissions sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id] LEFT JOIN --Table columns sys.columns col ON col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] LEFT JOIN sys.objects obj ON perm.[major_id] = obj.[object_id] WHERE princ.[type] in ('S','U') AND princ.[name] LIKE @userName -- Added this line --CSLAGLE UNION --List all access provisioned to a sql user or windows user/group through a database or application role SELECT [UserName] = CASE memberprinc.[type] WHEN 'S' THEN memberprinc.[name] WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI END, [UserType] = CASE memberprinc.[type] WHEN 'S' THEN 'SQL User' WHEN 'U' THEN 'Windows User' END, [DatabaseUserName] = memberprinc.[name], [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --Role/member associations sys.database_role_members members JOIN --Roles sys.database_principals roleprinc ON roleprinc.[principal_id] = members.[role_principal_id] JOIN --Role members (database users) sys.database_principals memberprinc ON memberprinc.[principal_id] = members.[member_principal_id] LEFT JOIN --Login accounts sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid] LEFT JOIN --Permissions sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN --Table columns sys.columns col on col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] LEFT JOIN sys.objects obj ON perm.[major_id] = obj.[object_id] WHERE memberprinc.[name] LIKE @userName -- Added this line --CSLAGLE UNION --List all access provisioned to the public role, which everyone gets by default SELECT [UserName] = '{All Users}', [UserType] = '{All Users}', [DatabaseUserName] = '{All Users}', [Role] = roleprinc.[name], [PermissionType] = perm.[permission_name], [PermissionState] = perm.[state_desc], [ObjectType] = obj.type_desc,--perm.[class_desc], [ObjectName] = OBJECT_NAME(perm.major_id), [ColumnName] = col.[name] FROM --Roles sys.database_principals roleprinc LEFT JOIN --Role permissions sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id] LEFT JOIN --Table columns sys.columns col on col.[object_id] = perm.major_id AND col.[column_id] = perm.[minor_id] JOIN --All objects sys.objects obj ON obj.[object_id] = perm.[major_id] WHERE --Only roles roleprinc.[type] = 'R' AND --Only public role roleprinc.[name] = 'public' AND --Only objects of ours, not the MS objects obj.is_ms_shipped = 0 ORDER BY princ.[Name], OBJECT_NAME(perm.major_id), col.[name], perm.[permission_name], perm.[state_desc], obj.type_desc--perm.[class_desc]