2016-04-22 50 views
0

我有这个脚本来获取SQL用户审计信息。这是一个很棒的脚本,但我似乎无法让它跨越所有数据库。我无法针对每个数据库手动运行此操作,因为这太费时。如何自动执行此操作以跨所有数据库运行?

我已经尝试了sp_MSforeachdb方法,但它在SELECT语句失败。

下面是脚本:

SELECT 
    ServerName   = @@SERVERNAME, 
    LoginName   = AccessSummary.LoginName, 
    LoginType   = CASE WHEN syslogins.isntuser = 1 THEN 'WINDOWS_LOGIN' WHEN syslogins.isntgroup = 1 THEN 'WINDOWS_GROUP' ELSE 'SQL_USER' END, 
    DatabaseName  = DB_NAME(), 
    SelectAccess  = MAX(AccessSummary.SelectAccess), 
    InsertAccess  = MAX(AccessSummary.InsertAccess), 
    UpdateAccess  = MAX(AccessSummary.UpdateAccess), 
    DeleteAccess  = MAX(AccessSummary.DeleteAccess), 
    DBOAccess   = MAX(AccessSummary.DBOAccess), 
    SysadminAccess  = MAX(AccessSummary.SysadminAccess) 
FROM 
    (
     /* Get logins with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipal.name, 
      SelectAccess  = CASE WHEN permission_name = 'SELECT' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = 'INSERT' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = 'UPDATE' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = 'DELETE' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipal 
      ON sysDatabasePrincipal.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipal.sid 
     WHERE sysDatabasePermission.class_desc = 'OBJECT_OR_COLUMN' 
      AND sysDatabasePrincipal.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_USER') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get group members with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipalMember.name, 
      SelectAccess  = CASE WHEN permission_name = 'SELECT' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = 'INSERT' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = 'UPDATE' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = 'DELETE' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalRole 
      ON sysDatabasePrincipalRole.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePermission.class_desc = 'OBJECT_OR_COLUMN' 
      AND sysDatabasePrincipalRole.type_desc = 'DATABASE_ROLE' 
      AND sysDatabasePrincipalRole.name <> 'public' 
      AND sysDatabasePrincipalMember.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_USER') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in db_owner, db_datareader and db_datawriter */ 
     SELECT 
      LoginName   = sysServerPrincipal.name, 
      SelectAccess  = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datareader') THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN sysDatabasePrincipalRole.name IN ('db_owner', 'db_datawriter') THEN 1 ELSE 0 END, 
      DBOAccess   = CASE WHEN sysDatabasePrincipalRole.name = 'db_owner' THEN 1 ELSE 0 END, 
      SysadminAccess  = 0 
     FROM sys.database_principals AS sysDatabasePrincipalRole 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePrincipalRole.name IN ('db_owner', 'db_datareader', 'db_datawriter') 
      AND sysServerPrincipal.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_LOGIN') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in sysadmin */ 
     SELECT 
      LoginName   = sysServerPrincipalMember.name, 
      SelectAccess  = 1, 
      InsertAccess  = 1, 
      UpdateAccess  = 1, 
      DeleteAccess  = 1, 
      DBOAccess   = 0, 
      SysadminAccess  = 1 
     FROM sys.server_principals AS sysServerPrincipalRole 
     INNER JOIN sys.server_role_members AS sysServerRoleMember 
      ON sysServerRoleMember.role_principal_id = sysServerPrincipalRole.principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipalMember 
      ON sysServerPrincipalMember.principal_id = sysServerRoleMember.member_principal_id 
     WHERE sysServerPrincipalMember.type_desc IN ('WINDOWS_LOGIN', 'WINDOWS_GROUP', 'SQL_LOGIN') 
      AND sysServerPrincipalMember.is_disabled = 0 
    ) AS AccessSummary 
INNER JOIN MASTER.dbo.syslogins AS syslogins 
    ON syslogins.loginname = AccessSummary.LoginName 
WHERE AccessSummary.LoginName NOT LIKE 'NT Service%' 
GROUP BY 
    AccessSummary.LoginName, 
    CASE WHEN syslogins.isntuser = 1 THEN 'WINDOWS_LOGIN' WHEN syslogins.isntgroup = 1 THEN 'WINDOWS_GROUP' ELSE 'SQL_USER' END 
+0

它是如何失败? –

+0

Msg 102,Level 15,State 1,Line 36 'THEN'附近语法不正确。 – BSanders

+0

这可能是因为sp_MSforeachdb只允许相当短的命令@ command1 nvarchar(2000) –

回答

0

其实我想通了。

DECLARE AllDatabases CURSOR FOR 
SELECT name FROM master.dbo.sysdatabases 

OPEN AllDatabases 

DECLARE @DBNameVar NVARCHAR(128),@Statement NVARCHAR(MAX) 

FETCH NEXT FROM AllDatabases INTO @DBNameVar 
WHILE (@@FETCH_STATUS = 0) 
BEGIN 
PRINT N'CHECKING DATABASE ' + @DBNameVar 
SET @Statement = N'USE ' + @DBNameVar + CHAR(13) 
+ N'SELECT 
    ServerName   = @@SERVERNAME, 
    LoginName   = AccessSummary.LoginName, 
    LoginType   = CASE WHEN syslogins.isntuser = 1 THEN ''WINDOWS_LOGIN'' WHEN syslogins.isntgroup = 1 THEN ''WINDOWS_GROUP'' ELSE ''SQL_USER'' END, 
    DatabaseName  = DB_NAME(), 
    SelectAccess  = MAX(AccessSummary.SelectAccess), 
    InsertAccess  = MAX(AccessSummary.InsertAccess), 
    UpdateAccess  = MAX(AccessSummary.UpdateAccess), 
    DeleteAccess  = MAX(AccessSummary.DeleteAccess), 
    DBOAccess   = MAX(AccessSummary.DBOAccess), 
    SysadminAccess  = MAX(AccessSummary.SysadminAccess) 
FROM 
    (
     /* Get logins with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipal.name, 
      SelectAccess  = CASE WHEN permission_name = ''SELECT'' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = ''INSERT'' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = ''UPDATE'' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = ''DELETE'' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipal 
      ON sysDatabasePrincipal.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipal.sid 
     WHERE sysDatabasePermission.class_desc = ''OBJECT_OR_COLUMN'' 
      AND sysDatabasePrincipal.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_USER'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get group members with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipalMember.name, 
      SelectAccess  = CASE WHEN permission_name = ''SELECT'' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = ''INSERT'' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = ''UPDATE'' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = ''DELETE'' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalRole 
      ON sysDatabasePrincipalRole.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePermission.class_desc = ''OBJECT_OR_COLUMN'' 
      AND sysDatabasePrincipalRole.type_desc = ''DATABASE_ROLE'' 
      AND sysDatabasePrincipalRole.name <> ''public'' 
      AND sysDatabasePrincipalMember.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_USER'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in db_owner, db_datareader and db_datawriter */ 
     SELECT 
      LoginName   = sysServerPrincipal.name, 
      SelectAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datareader'') THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      DBOAccess   = CASE WHEN sysDatabasePrincipalRole.name = ''db_owner'' THEN 1 ELSE 0 END, 
      SysadminAccess  = 0 
     FROM sys.database_principals AS sysDatabasePrincipalRole 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datareader'', ''db_datawriter'') 
      AND sysServerPrincipal.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_LOGIN'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in sysadmin */ 
     SELECT 
      LoginName   = sysServerPrincipalMember.name, 
      SelectAccess  = 1, 
      InsertAccess  = 1, 
      UpdateAccess  = 1, 
      DeleteAccess  = 1, 
      DBOAccess   = 0, 
      SysadminAccess  = 1 
     FROM sys.server_principals AS sysServerPrincipalRole 
     INNER JOIN sys.server_role_members AS sysServerRoleMember 
      ON sysServerRoleMember.role_principal_id = sysServerPrincipalRole.principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipalMember 
      ON sysServerPrincipalMember.principal_id = sysServerRoleMember.member_principal_id 
     WHERE sysServerPrincipalMember.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_LOGIN'') 
      AND sysServerPrincipalMember.is_disabled = 0 
    ) AS AccessSummary 
INNER JOIN MASTER.dbo.syslogins AS syslogins 
    ON syslogins.loginname = AccessSummary.LoginName 
WHERE AccessSummary.LoginName NOT LIKE ''NT Service%'' 
GROUP BY 
    AccessSummary.LoginName, 
    CASE WHEN syslogins.isntuser = 1 THEN ''WINDOWS_LOGIN'' WHEN syslogins.isntgroup = 1 THEN ''WINDOWS_GROUP'' ELSE ''SQL_USER'' END 
' 
EXEC sp_executesql @Statement 
PRINT CHAR(13) + CHAR(13) 
FETCH NEXT FROM AllDatabases INTO @DBNameVar 
END 

CLOSE AllDatabases 
DEALLOCATE AllDatabases 
0

使用这样的事情:

DECLARE @DB_Name varchar(100) 
DECLARE @Command nvarchar(max) 

DECLARE database_cursor CURSOR FOR 
SELECT name 
FROM MASTER.sys.sysdatabases 

OPEN database_cursor 

FETCH NEXT FROM database_cursor INTO @DB_Name 

WHILE @@FETCH_STATUS = 0 
BEGIN 


set @Command = 
' 
use ' + @DB_Name + '; 


SELECT 
    ServerName   = @@SERVERNAME, 
    LoginName   = AccessSummary.LoginName, 
    LoginType   = CASE WHEN syslogins.isntuser = 1 THEN ''WINDOWS_LOGIN'' WHEN syslogins.isntgroup = 1 THEN ''WINDOWS_GROUP'' ELSE ''SQL_USER'' END, 
    DatabaseName  = DB_NAME(), 
    SelectAccess  = MAX(AccessSummary.SelectAccess), 
    InsertAccess  = MAX(AccessSummary.InsertAccess), 
    UpdateAccess  = MAX(AccessSummary.UpdateAccess), 
    DeleteAccess  = MAX(AccessSummary.DeleteAccess), 
    DBOAccess   = MAX(AccessSummary.DBOAccess), 
    SysadminAccess  = MAX(AccessSummary.SysadminAccess) 
FROM 
    (
     /* Get logins with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipal.name, 
      SelectAccess  = CASE WHEN permission_name = ''SELECT'' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = ''INSERT'' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = ''UPDATE'' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = ''DELETE'' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipal 
      ON sysDatabasePrincipal.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipal.sid 
     WHERE sysDatabasePermission.class_desc = ''OBJECT_OR_COLUMN'' 
      AND sysDatabasePrincipal.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_USER'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get group members with permissions */ 
     SELECT 
      LoginName   = sysDatabasePrincipalMember.name, 
      SelectAccess  = CASE WHEN permission_name = ''SELECT'' THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN permission_name = ''INSERT'' THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN permission_name = ''UPDATE'' THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN permission_name = ''DELETE'' THEN 1 ELSE 0 END, 
      DBOAccess   = 0, 
      SysadminAccess  = 0 
     FROM sys.database_permissions AS sysDatabasePermission 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalRole 
      ON sysDatabasePrincipalRole.principal_id = sysDatabasePermission.grantee_principal_id 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePermission.class_desc = ''OBJECT_OR_COLUMN'' 
      AND sysDatabasePrincipalRole.type_desc = ''DATABASE_ROLE'' 
      AND sysDatabasePrincipalRole.name <> ''public'' 
      AND sysDatabasePrincipalMember.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_USER'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in db_owner, db_datareader and db_datawriter */ 
     SELECT 
      LoginName   = sysServerPrincipal.name, 
      SelectAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datareader'') THEN 1 ELSE 0 END, 
      InsertAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      UpdateAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      DeleteAccess  = CASE WHEN sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datawriter'') THEN 1 ELSE 0 END, 
      DBOAccess   = CASE WHEN sysDatabasePrincipalRole.name = ''db_owner'' THEN 1 ELSE 0 END, 
      SysadminAccess  = 0 
     FROM sys.database_principals AS sysDatabasePrincipalRole 
     INNER JOIN sys.database_role_members AS sysDatabaseRoleMember 
      ON sysDatabaseRoleMember.role_principal_id = sysDatabasePrincipalRole.principal_id 
     INNER JOIN sys.database_principals AS sysDatabasePrincipalMember 
      ON sysDatabasePrincipalMember.principal_id = sysDatabaseRoleMember.member_principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipal 
      ON sysServerPrincipal.sid = sysDatabasePrincipalMember.sid 
     WHERE sysDatabasePrincipalRole.name IN (''db_owner'', ''db_datareader'', ''db_datawriter'') 
      AND sysServerPrincipal.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_LOGIN'') 
      AND sysServerPrincipal.is_disabled = 0 
     UNION ALL 
     /* Get users in sysadmin */ 
     SELECT 
      LoginName   = sysServerPrincipalMember.name, 
      SelectAccess  = 1, 
      InsertAccess  = 1, 
      UpdateAccess  = 1, 
      DeleteAccess  = 1, 
      DBOAccess   = 0, 
      SysadminAccess  = 1 
     FROM sys.server_principals AS sysServerPrincipalRole 
     INNER JOIN sys.server_role_members AS sysServerRoleMember 
      ON sysServerRoleMember.role_principal_id = sysServerPrincipalRole.principal_id 
     INNER JOIN sys.server_principals AS sysServerPrincipalMember 
      ON sysServerPrincipalMember.principal_id = sysServerRoleMember.member_principal_id 
     WHERE sysServerPrincipalMember.type_desc IN (''WINDOWS_LOGIN'', ''WINDOWS_GROUP'', ''SQL_LOGIN'') 
      AND sysServerPrincipalMember.is_disabled = 0 
    ) AS AccessSummary 
INNER JOIN MASTER.dbo.syslogins AS syslogins 
    ON syslogins.loginname = AccessSummary.LoginName 
WHERE AccessSummary.LoginName NOT LIKE ''NT Service%'' 
GROUP BY 
    AccessSummary.LoginName, 
    CASE WHEN syslogins.isntuser = 1 THEN ''WINDOWS_LOGIN'' WHEN syslogins.isntgroup = 1 THEN ''WINDOWS_GROUP'' ELSE ''SQL_USER'' END 
    ' 


    EXEC sp_executesql @Command 

    FETCH NEXT FROM database_cursor INTO @DB_Name 

END 

CLOSE database_cursor 
DEALLOCATE database_cursor