Files
sql-scripts/list non AD group logins and permissions.sql
Thierry Schork 94be4e48e8 sync
2025-08-15 10:17:18 +02:00

1085 lines
48 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
USE master;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET XACT_ABORT ON;
SET NOCOUNT ON;
GO
IF OBJECT_ID('dbo.sp_DBPermissions') IS NULL
EXECUTE sp_executesql N'CREATE PROCEDURE dbo.sp_DBPermissions AS PRINT ''Stub'';';
GO
/*********************************************************************************************
sp_DBPermissions V7.0
Kenneth Fisher
http://www.sqlstudies.com
https://github.com/sqlstudent144/SQL-Server-Scripts/blob/master/sp_DBPermissions.sql
This stored procedure returns 3 data sets. The first dataset is the list of database
principals, the second is role membership, and the third is object and database level
permissions.
The final 2 columns of each query are "Un-Do"/"Do" scripts. For example removing a member
from a role or adding them to a role. I am fairly confident in the role scripts, however,
the scripts in the database principals query and database/object permissions query are
works in progress. In particular certificates, keys and column level permissions are not
scripted out. Also while the scripts have worked flawlessly on the systems I've tested
them on, these systems are fairly similar when it comes to security so I can't say that
in a more complicated system there won't be the odd bug.
Standard disclaimer: You use scripts off of the web at your own risk. I fully expect this
script to work without issue but I've been known to be wrong before.
Parameters:
@DBName
If NULL use the current database, otherwise give permissions based on the parameter.
There is a special case where you pass in ALL to the @DBName. In this case the SP
will loop through (yes I'm using a cursor) all of the DBs in sysdatabases and run
the queries into temp tables before returning the results. WARNINGS: If you use
this option and have a large number of databases it will be SLOW. If you use this
option and don't specify any other parameters (say a specific @Principal) and have
even a medium number of databases it will be SLOW. Also the undo/do scripts do
not have USE statements in them so please take that into account.
@Principal
If NOT NULL then all three queries only pull for that database principal. @Principal
is a pattern check. The queries check for any row where the passed in value exists.
It uses the pattern '%' + @Principal + '%'
@Role
If NOT NULL then the roles query will pull members of the role. If it is NOT NULL and
@DBName is NULL then DB principal and permissions query will pull the principal row for
the role and the permissions for the role. @Role is a pattern check. The queries
check for any row where the passed in value exists. It uses the pattern '%' + @Role +
'%'
@Type
If NOT NULL then all three queries will only pull principals of that type.
S = SQL login
U = Windows login
G = Windows group
R = Server role
C = Login mapped to a certificate
K = Login mapped to an asymmetric key
@ObjectName
If NOT NULL then the third query will display permissions specific to the object
specified and the first two queries will display only those users with those specific
permissions. Unfortunately at this point only objects in sys.all_objects will work.
This parameter uses the pattern '%' + @ObjectName + '%'
@Permission
If NOT NULL then the third query will display only permissions that match what is in
the parameter. The first two queries will display only those users with that specific
permission.
@LoginName
If NOT NULL then each of the queries will only pull back database principals that
have the same SID as a login that matches the pattern '%' + @LoginName + '%'
@UseLikeSearch
When this is set to 1 (the default) then the search parameters will use LIKE (and
%'s will be added around the @Principal, @Role, @ObjectName, and @LoginName parameters).
When set to 0 searchs will use =.
@IncludeMSShipped
When this is set to 1 (the default) then all principals will be included. When set
to 0 the fixed server roles and SA and Public principals will be excluded.
@CopyTo
If @Principal is filled in then the value in @CopyTo is used in the drop and create
scripts instead of @Principal. In the case of the CREATE USER statement @CopyTo
also replaces the name of the server level principal, however it does not affect the
default schema name.
NOTE: It is very important to note that if @CopyTo is not a valid name the drop/create
scripts may fail.
@DropTempTables
When this is set to 1 (the default) the temp tables used are dropped. If it's 0
then the tempt ables are kept for references after the code has finished.
The temp tables are:
##DBPrincipals
##DBRoles
##DBPermissions
@ShowOrphans
By default this is 0. If it is 1 then it shows only orphaned principals and scripts to fix them.
Note: This option is 2012 and up only.
@Output
What type of output is desired.
Default - Either 'Default' or it doesn't match any of the allowed values then the SP
will return the standard 3 outputs.
None - No output at all. Usually used if you keeping the temp tables to do your own
reporting.
CreateOnly - Only return the create scripts where they aren't NULL.
DropOnly - Only return the drop scripts where they aren't NULL.
ScriptOnly - Return drop and create scripts where they aren't NULL.
Report - Returns one output with one row per principal and a comma delimited list of
roles the principal is a member of and a comma delimited list of the
individual permissions they have.
@Print
Defaults to 0, but if a 1 is passed in then the queries are not run but printed
out instead. This is primarily for debugging.
Data is ordered as follows
1st result set: DBPrincipal
2nd result set: RoleName, UserName if the parameter @Role is used else
UserName, RoleName
3rd result set: If @ObjectName is used then DBName, SchemaName, ObjectName, Grantee_Name, permission_name
otherwise DBName, GranteeName, SchemaName, ObjectName, permission_name
-- V2.0
-- 8/18/2013 Create a stub if the SP doesnt exist, then always do an alter
-- 8/18/2013 - Use instance collation for all concatenated strings
-- 9/04/2013 - dbo cant be added or removed from roles. Dont script.
-- 9/04/2013 - Fix scripts for schema level permissions.
-- 9/04/2013 Change print option to show values of variables not the
-- Variable names.
-- V3.0
-- 10/5/2013 - Added @Type parameter to pull only principals of a given type.
-- 10/10/2013 - Added @ObjectName parameter to pull only permissions for a given object.
-- V4.0
-- 11/18/2013 - Added parameter names to sp_addrolemember and sp_droprolemember.
-- 11/19/2013 - Added an ORDER BY to each of the result sets. See above for details.
-- 01/04/2014 - Add an ALL option to the DBName parameter.
-- V4.1
-- 02/07/2014 - Fix bug scripting permissions where object and schema have the same ID
-- 02/15/2014 - Add support for user defined types
-- 02/15/2014 - Fix: Add schema to object GRANT and REVOKE scripts
-- V5.0
-- 4/29/2014 - Fix: Removed extra print statements
-- 4/29/2014 - Fix: Added SET NOCOUNT ON
-- 4/29/2014 - Added a USE statement to the scripts when using the @DBName = 'All' option
-- 5/01/2014 - Added @Permission parameter
-- 5/14/2014 - Added additional permissions based on information from Kendal Van Dyke's
post http://www.kendalvandyke.com/2014/02/using-sysobjects-when-scripting.html
-- 6/02/2014 - Added @LoginName parameter
-- V5.5
-- 7/15/2014 - Bunch of changes recommended by @SQLSoldier/"https://twitter.com/SQLSoldier"
Primarily changing the strings to unicode & adding QUOTENAME in a few places
I'd missed it.
-- V6.0
-- 10/19/2014 - Add @UserLikeSearch and @IncludeMSShipped parameters.
-- 11/29/2016 - Fixed permissions for symmetric keys
-- Found and fixed by Brenda Grossnickle
-- 03/25/2017 - Move SID towards the end of the first output so the more important
-- columns are closer to the front.
-- 03/25/2017 - Add IF Exists to drop and create user scripts
-- 03/25/2017 - Remove create/drop user scripts for guest, public, sys and INFORMATION_SCHEMA
-- 03/25/2017 - Add @DropTempTables to keep the temp tables after the SP is run.
-- 03/26/2017 - Add @Output to allow different types of output.
-- V6.1
-- 06/25/2018 - Skip snapshots
-- 02/13/2019 - Fix to direct permissions column in the report output to show schema permissions correctly
-- 04/05/2019 - For 'All' DB parameter fix to only look at ONLINE and EMERGENCY DBs.
-- 06/04/2019 - Add SchemaName and permission_name to the order of the third data set.
This makes the order more reliable.
-- 06/04/2019 - Begin cleanup of the dynamic SQL (specifically removing carrage return & extra quotes)
-- 06/04/2019 - Fix @print where part of the permissions query was being truncated.
-- V6.2
-- 07/15/2022 - Add @CopyTo parameter to handle requests like "Please copy permissions from x to y."
-- 07/15/2022 - Clean up dyanmic formatting to remove most of the N' and "' + CHAR(13) + " strings.
-- 07/31/2022 - Formatting: Replace tabs with spaces
-- 01/14/2023 - Fixes for unicode strings
-- V7.0
-- 08/15/2023 - Add orphan functionality with @ShowOrphans parameter.
*********************************************************************************************/
ALTER PROCEDURE [dbo].sp_DBPermissions
(
@DBName sysname = NULL,
@Principal sysname = NULL,
@Role sysname = NULL,
@Type NVARCHAR(30) = NULL,
@ObjectName sysname = NULL,
@Permission sysname = NULL,
@LoginName sysname = NULL,
@UseLikeSearch BIT = 1,
@IncludeMSShipped BIT = 1,
@CopyTo sysname = NULL,
@DropTempTables BIT = 1,
@ShowOrphans BIT = 0,
@Output VARCHAR(30) = 'Default',
@Print BIT = 0
)
AS
SET NOCOUNT ON;
DECLARE @Collation NVARCHAR(75);
SET @Collation = N' COLLATE ' + CAST(SERVERPROPERTY('Collation') AS NVARCHAR(50));
DECLARE @sql NVARCHAR(MAX);
DECLARE @sql2 NVARCHAR(MAX);
DECLARE @ObjectList NVARCHAR(MAX);
DECLARE @ObjectList2 NVARCHAR(MAX);
DECLARE @use NVARCHAR(500);
DECLARE @AllDBNames sysname;
IF @DBName IS NULL OR @DBName = N'All'
BEGIN
SET @use = '';
IF @DBName IS NULL
SET @DBName = DB_NAME();
--SELECT @DBName = db_name(database_id)
--FROM sys.dm_exec_requests
--WHERE session_id = @@SPID
END;
ELSE
-- IF EXISTS (SELECT 1 FROM sys.databases WHERE name = @DBName)
IF DB_ID(@DBName) IS NOT NULL
SET @use = N'USE ' + QUOTENAME(@DBName) + N';' + NCHAR(13);
ELSE
BEGIN
RAISERROR (N'%s is not a valid database name.',
16,
1,
@DBName);
RETURN;
END;
DECLARE @LikeOperator NVARCHAR(4);
IF @UseLikeSearch = 1
SET @LikeOperator = N'LIKE';
ELSE
SET @LikeOperator = N'=';
IF @UseLikeSearch = 1
BEGIN
IF LEN(ISNULL(@Principal,'')) > 0
SET @Principal = N'%' + @Principal + N'%';
IF LEN(ISNULL(@Role,'')) > 0
SET @Role = N'%' + @Role + N'%';
IF LEN(ISNULL(@ObjectName,'')) > 0
SET @ObjectName = N'%' + @ObjectName + N'%';
IF LEN(ISNULL(@LoginName,'')) > 0
SET @LoginName = N'%' + @LoginName + N'%';
END;
IF (@Principal IS NULL AND @CopyTo IS NOT NULL) OR LEN(@CopyTo) = 0
SET @CopyTo = NULL;
IF @Print = 1 AND @DBName = N'All'
BEGIN
PRINT 'DECLARE @AllDBNames sysname';
PRINT 'SET @AllDBNames = ''master''';
PRINT '';
END;
--=========================================================================
-- Database Principals
SET @sql =
N'SELECT ' + CASE WHEN @DBName = 'All' THEN N'@AllDBNames' ELSE N'N''' + @DBName + N'''' END + N' AS DBName,
DBPrincipals.principal_id AS DBPrincipalId, DBPrincipals.name AS DBPrincipal, SrvPrincipals.name AS SrvPrincipal,
DBPrincipals.type, DBPrincipals.type_desc, DBPrincipals.default_schema_name, DBPrincipals.create_date,
DBPrincipals.modify_date, DBPrincipals.is_fixed_role,
Authorizations.name AS RoleAuthorization, DBPrincipals.sid,
CASE WHEN DBPrincipals.is_fixed_role = 0 AND DBPrincipals.name NOT IN (''dbo'',''guest'', ''INFORMATION_SCHEMA'', ''public'', ''sys'') THEN ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' + NCHAR(13) ELSE N'' END +
N' ''IF DATABASE_PRINCIPAL_ID(N'''''' + ' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'DBPrincipals.name') + ' + '''''') IS NOT NULL '' +
''DROP '' + CASE DBPrincipals.[type] WHEN ''C'' THEN NULL
WHEN ''K'' THEN NULL
WHEN ''R'' THEN ''ROLE''
WHEN ''A'' THEN ''APPLICATION ROLE''
ELSE ''USER'' END +
'' ''+QUOTENAME(' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'DBPrincipals.name') + '' + @Collation + N') + '';'' ELSE NULL END AS DropScript,
CASE WHEN DBPrincipals.is_fixed_role = 0 AND DBPrincipals.name NOT IN (''dbo'',''guest'', ''INFORMATION_SCHEMA'', ''public'', ''sys'') THEN ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' +NCHAR(13) ELSE N'' END +
N' ''IF DATABASE_PRINCIPAL_ID(N'''''' + ' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'DBPrincipals.name') + ' + '''''') IS NULL '' +
''CREATE '' + CASE DBPrincipals.[type] WHEN ''C'' THEN NULL
WHEN ''K'' THEN NULL
WHEN ''R'' THEN ''ROLE''
WHEN ''A'' THEN ''APPLICATION ROLE''
ELSE ''USER'' END +
'' ''+QUOTENAME(' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'DBPrincipals.name') + '' + @Collation + N') END +
CASE WHEN DBPrincipals.[type] = ''R'' THEN
ISNULL('' AUTHORIZATION ''+QUOTENAME(Authorizations.name' + @Collation + N'),'''')
WHEN DBPrincipals.[type] = ''A'' THEN
''''
WHEN DBPrincipals.[type] NOT IN (''C'',''K'') THEN
ISNULL('' FOR LOGIN '' +
QUOTENAME(' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'SrvPrincipals.name') + '' + @Collation + N'),'' WITHOUT LOGIN'') +
ISNULL('' WITH DEFAULT_SCHEMA = ''+
QUOTENAME(DBPrincipals.default_schema_name' + @Collation + N'),'''')
ELSE ''''
END + '';'' +
CASE WHEN DBPrincipals.[type] NOT IN (''C'',''K'',''R'',''A'')
AND SrvPrincipals.name IS NULL
AND DBPrincipals.sid IS NOT NULL
AND DBPrincipals.sid NOT IN (0x00, 0x01)
THEN '' -- Possible missing server principal''
ELSE '''' END
AS CreateScript' +
CASE WHEN SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1 THEN N',
CASE WHEN DBPrincipals.name = ''dbo'' THEN ''NULL'' ELSE
''IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'' + QUOTENAME(DBPrincipals.name,'''''''') + '') ' +
N'CREATE LOGIN '' + QUOTENAME(DBPrincipals.name) +
CASE WHEN DBPrincipals.type = (''S'') THEN '' WITH PASSWORD = ''''<Insert Strong Password Here '+ CAST(NEWID() AS NVARCHAR(36))+'>'''', '' +
'' SID = '' + CONVERT(varchar(85), DBPrincipals.sid, 1)
WHEN DBPrincipals.type IN (''U'',''G'') THEN '' FROM WINDOWS ''
ELSE '''' END END AS CreateLogin, ' +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' +NCHAR(13) ELSE N'' END +
N' CASE WHEN DBPrincipals.name = ''dbo'' THEN ''EXEC sp_changedbowner ''''<existing login>'''';'' ELSE
''ALTER USER '' + QUOTENAME(DBPrincipals.name) + '' WITH LOGIN = '' + QUOTENAME(DBPrincipals.name) + '';'' END AS AlterUser' ELSE '' END + '
FROM sys.database_principals DBPrincipals
LEFT OUTER JOIN sys.database_principals Authorizations
ON DBPrincipals.owning_principal_id = Authorizations.principal_id
LEFT OUTER JOIN sys.server_principals SrvPrincipals
ON DBPrincipals.sid = SrvPrincipals.sid
AND DBPrincipals.sid NOT IN (0x00, 0x01)
WHERE 1=1 ';
IF SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.authentication_type_desc <> ''NONE''
AND SrvPrincipals.principal_id IS NULL
AND DBPrincipals.sid NOT IN (0x00, 0x01)';
IF LEN(ISNULL(@Principal,@Role)) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.name ' + @LikeOperator + N' N' +
ISNULL(QUOTENAME(@Principal,N''''),QUOTENAME(@Role,''''));
ELSE
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.name ' + @LikeOperator + N' ISNULL(@Principal,@Role) ';
IF LEN(@Type) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.type ' + @LikeOperator + N' N' + QUOTENAME(@Type,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.type ' + @LikeOperator + N' @Type';
IF LEN(@LoginName) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND SrvPrincipals.name ' + @LikeOperator + N' N' + QUOTENAME(@LoginName,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND SrvPrincipals.name ' + @LikeOperator + N' @LoginName';
IF LEN(@ObjectName) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1 ' + NCHAR(13) +
N' FROM sys.all_objects [Objects] ' + NCHAR(13) +
N' INNER JOIN sys.database_permissions Permission ' + NCHAR(13) +
N' ON Permission.major_id = [Objects].object_id ' + NCHAR(13) +
N' WHERE Permission.major_id = [Objects].object_id ' + NCHAR(13) +
N' AND Permission.grantee_principal_id = DBPrincipals.principal_id ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + N' AND [Objects].name ' + @LikeOperator + N' N' + QUOTENAME(@ObjectName,'''');
ELSE
SET @sql = @sql + N' AND [Objects].name ' + @LikeOperator + N' @ObjectName';
SET @sql = @sql + N')';
END;
IF LEN(@Permission) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1 ' + NCHAR(13) +
N' FROM sys.database_permissions Permission ' + NCHAR(13) +
N' WHERE Permission.grantee_principal_id = DBPrincipals.principal_id ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + N' AND Permission.permission_name ' + @LikeOperator + N' N' + QUOTENAME(@Permission,'''');
ELSE
SET @sql = @sql + N' AND Permission.permission_name ' + @LikeOperator + N' @Permission';
SET @sql = @sql + N')';
END;
IF @IncludeMSShipped = 0
SET @sql = @sql + NCHAR(13) + N' AND DBPrincipals.is_fixed_role = 0 ' + NCHAR(13) +
' AND DBPrincipals.name NOT IN (''dbo'',''public'',''INFORMATION_SCHEMA'',''guest'',''sys'') ';
IF @Print = 1
BEGIN
PRINT N'-- Database Principals';
PRINT CAST(@sql AS NVARCHAR(MAX));
PRINT ''; -- Spacing before the next print
PRINT '';
END;
ELSE
BEGIN
IF OBJECT_ID('tempdb..##DBPrincipals') IS NOT NULL
DROP TABLE ##DBPrincipals;
-- Create temp table to store the data in
CREATE TABLE ##DBPrincipals (
[dbname] sysname NULL,
DBPrincipalId INT NULL,
DBPrincipal sysname NULL,
SrvPrincipal sysname NULL,
TYPE CHAR(1) NULL,
[type_desc] NCHAR(60) NULL,
[default_schema_name] sysname NULL,
[create_date] DATETIME NULL,
[modify_date] DATETIME NULL,
[is_fixed_role] BIT NULL,
RoleAuthorization sysname NULL,
[sid] VARBINARY(85) NULL,
DropScript NVARCHAR(MAX) NULL,
CreateScript NVARCHAR(MAX) NULL
);
IF SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1
BEGIN
ALTER TABLE ##DBPrincipals ADD CreateLogin NVARCHAR(MAX) NULL;
ALTER TABLE ##DBPrincipals ADD AlterUser NVARCHAR(MAX) NULL;
END;
SET @sql = @use + N'INSERT INTO ##DBPrincipals ' + NCHAR(13) + @sql;
IF @DBName = 'All'
BEGIN
-- Declare a READ_ONLY cursor to loop through the databases
DECLARE cur_DBList CURSOR
READ_ONLY
FOR SELECT [name] FROM [sys].[databases]
WHERE STATE IN (0,5)
AND [source_database_id] IS NULL
ORDER BY [name];
OPEN cur_DBList;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
SET @sql2 = N'USE ' + QUOTENAME(@AllDBNames) + N';' + NCHAR(13) + @sql;
EXECUTE sp_executesql @sql2,
N'@Principal sysname, @Role sysname, @Type nvarchar(30), @ObjectName sysname,
@AllDBNames sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @AllDBNames, @Permission, @LoginName;
-- PRINT @sql2
END;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
END;
CLOSE cur_DBList;
DEALLOCATE cur_DBList;
END;
ELSE
EXECUTE sp_executesql @sql, N'@Principal sysname, @Role sysname, @Type nvarchar(30),
@ObjectName sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @Permission, @LoginName;
END;
--=========================================================================
-- Database Role Members
IF NOT (SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1)
BEGIN
SET @sql =
N'SELECT ' + CASE WHEN @DBName = 'All' THEN N'@AllDBNames' ELSE N'N''' + @DBName + N'''' END + N' AS DBName,
Users.principal_id AS UserPrincipalId, Users.name AS UserName, Roles.name AS RoleName, ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' + NCHAR(13) ELSE N'' END +
N' CASE WHEN Users.is_fixed_role = 0 AND Users.name <> ''dbo'' THEN
''EXEC sp_droprolemember @rolename = N''+QUOTENAME(Roles.name' + @Collation +
N','''''''')+'', @membername = N''+QUOTENAME(CASE WHEN Users.name = ''dbo'' THEN NULL
ELSE ' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'Users.name') + ' END' + @Collation +
N','''''''')+'';'' END AS DropScript, ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' + NCHAR(13) ELSE N'' END +
N' CASE WHEN Users.is_fixed_role = 0 AND Users.name <> ''dbo'' THEN
''EXEC sp_addrolemember @rolename = N''+QUOTENAME(Roles.name' + @Collation +
N','''''''')+'', @membername = N''+QUOTENAME(CASE WHEN Users.name = ''dbo'' THEN NULL
ELSE ' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'Users.name') + ' END' + @Collation +
N','''''''')+'';'' END AS AddScript
FROM sys.database_role_members RoleMembers
JOIN sys.database_principals Users
ON RoleMembers.member_principal_id = Users.principal_id
JOIN sys.database_principals Roles
ON RoleMembers.role_principal_id = Roles.principal_id
WHERE 1=1 ';
IF LEN(ISNULL(@Principal,'')) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Users.name ' + @LikeOperator + N' N'+QUOTENAME(@Principal,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Users.name ' + @LikeOperator + N' @Principal';
IF LEN(ISNULL(@Role,'')) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Roles.name ' + @LikeOperator + N' N'+QUOTENAME(@Role,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Roles.name ' + @LikeOperator + N' @Role';
IF LEN(@Type) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Users.type ' + @LikeOperator + N' N' + QUOTENAME(@Type,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Users.type ' + @LikeOperator + N' @Type';
IF LEN(@LoginName) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1
FROM sys.server_principals SrvPrincipals
WHERE Users.sid NOT IN (0x00, 0x01)
AND SrvPrincipals.sid = Users.sid
AND Users.type NOT IN (''R'') ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + NCHAR(13) + ' AND SrvPrincipals.name ' + @LikeOperator + N' N' + QUOTENAME(@LoginName,'''');
ELSE
SET @sql = @sql + NCHAR(13) + ' AND SrvPrincipals.name ' + @LikeOperator + N' @LoginName';
SET @sql = @sql + N')';
END;
IF LEN(@ObjectName) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1
FROM sys.all_objects [Objects]
INNER JOIN sys.database_permissions Permission
ON Permission.major_id = [Objects].object_id
WHERE Permission.major_id = [Objects].object_id
AND Permission.grantee_principal_id = Users.principal_id ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + N' AND [Objects].name ' + @LikeOperator + N' N' + QUOTENAME(@ObjectName,'''');
ELSE
SET @sql = @sql + N' AND [Objects].name ' + @LikeOperator + N' @ObjectName';
SET @sql = @sql + N')';
END;
IF LEN(@Permission) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1
FROM sys.database_permissions Permission
WHERE Permission.grantee_principal_id = Users.principal_id ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + N' AND Permission.permission_name ' + @LikeOperator + N' N' + QUOTENAME(@Permission,'''');
ELSE
SET @sql = @sql + N' AND Permission.permission_name ' + @LikeOperator + N' @Permission';
SET @sql = @sql + N')';
END;
IF @IncludeMSShipped = 0
SET @sql = @sql + NCHAR(13) + N' AND Users.is_fixed_role = 0 ' + NCHAR(13) +
' AND Users.name NOT IN (''dbo'',''public'',''INFORMATION_SCHEMA'',''guest'',''sys'') ';
IF @Print = 1
BEGIN
PRINT N'-- Database Role Members';
PRINT CAST(@sql AS NVARCHAR(MAX));
PRINT ''; -- Spacing before the next print
PRINT '';
END;
ELSE
BEGIN
IF OBJECT_ID('tempdb..##DBRoles') IS NOT NULL
DROP TABLE ##DBRoles;
-- Create temp table to store the data in
CREATE TABLE ##DBRoles (
[dbname] sysname NULL,
UserPrincipalId INT NULL,
UserName sysname NULL,
RoleName sysname NULL,
DropScript NVARCHAR(MAX) NULL,
AddScript NVARCHAR(MAX) NULL
);
SET @sql = @use + NCHAR(13) + 'INSERT INTO ##DBRoles ' + NCHAR(13) + @sql;
IF @DBName = 'All'
BEGIN
-- Declare a READ_ONLY cursor to loop through the databases
DECLARE cur_DBList CURSOR
READ_ONLY
FOR SELECT [name] FROM [sys].[databases]
WHERE STATE IN (0,5)
AND [source_database_id] IS NULL
ORDER BY [name];
OPEN cur_DBList;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
SET @sql2 = 'USE ' + QUOTENAME(@AllDBNames) + ';' + NCHAR(13) + @sql;
EXECUTE sp_executesql @sql2,
N'@Principal sysname, @Role sysname, @Type nvarchar(30), @ObjectName sysname,
@AllDBNames sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @AllDBNames, @Permission, @LoginName;
-- PRINT @sql2
END;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
END;
CLOSE cur_DBList;
DEALLOCATE cur_DBList;
END;
ELSE
EXECUTE sp_executesql @sql, N'@Principal sysname, @Role sysname, @Type nvarchar(30),
@ObjectName sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @Permission, @LoginName;
END;
END;
--=========================================================================
-- Database & object Permissions
IF NOT (SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1)
BEGIN
SET @ObjectList =
N'; WITH ObjectList AS (
SELECT NULL AS SchemaName ,
name ' + @Collation + ' AS name,
database_id AS id,
''DATABASE'' AS class_desc,
'''' AS class
FROM master.sys.databases
UNION ALL
SELECT SCHEMA_NAME(sys.all_objects.schema_id) ' + @Collation + N' AS SchemaName,
name ' + @Collation + N' AS name,
object_id AS id,
''OBJECT_OR_COLUMN'' AS class_desc,
''OBJECT'' AS class
FROM sys.all_objects
UNION ALL
SELECT name ' + @Collation + N' AS SchemaName,
NULL AS name,
schema_id AS id,
''SCHEMA'' AS class_desc,
''SCHEMA'' AS class
FROM sys.schemas
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
principal_id AS id,
''DATABASE_PRINCIPAL'' AS class_desc,
CASE type_desc
WHEN ''APPLICATION_ROLE'' THEN ''APPLICATION ROLE''
WHEN ''DATABASE_ROLE'' THEN ''ROLE''
ELSE ''USER'' END AS class
FROM sys.database_principals
UNION ALL
SELECT SCHEMA_NAME(schema_id) ' + @Collation + N' AS SchemaName,
name ' + @Collation + N' AS name,
xml_collection_id AS id,
''XML_SCHEMA_COLLECTION'' AS class_desc,
''XML SCHEMA COLLECTION'' AS class
FROM sys.xml_schema_collections
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
message_type_id AS id,
''MESSAGE_TYPE'' AS class_desc,
''MESSAGE TYPE'' AS class
FROM sys.service_message_types
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
assembly_id AS id,
''ASSEMBLY'' AS class_desc,
''ASSEMBLY'' AS class
FROM sys.assemblies
UNION ALL';
SET @ObjectList2 = N'
SELECT SCHEMA_NAME(sys.types.schema_id) ' + @Collation + N' AS SchemaName,
name ' + @Collation + N' AS name,
user_type_id AS id,
''TYPE'' AS class_desc,
''TYPE'' AS class
FROM sys.types
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
service_contract_id AS id,
''SERVICE_CONTRACT'' AS class_desc,
''CONTRACT'' AS class
FROM sys.service_contracts
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
service_id AS id,
''SERVICE'' AS class_desc,
''SERVICE'' AS class
FROM sys.services
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
remote_service_binding_id AS id,
''REMOTE_SERVICE_BINDING'' AS class_desc,
''REMOTE SERVICE BINDING'' AS class
FROM sys.remote_service_bindings
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
route_id AS id,
''ROUTE'' AS class_desc,
''ROUTE'' AS class
FROM sys.routes
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
fulltext_catalog_id AS id,
''FULLTEXT_CATALOG'' AS class_desc,
''FULLTEXT CATALOG'' AS class
FROM sys.fulltext_catalogs
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
symmetric_key_id AS id,
''SYMMETRIC_KEYS'' AS class_desc,
''SYMMETRIC KEY'' AS class
FROM sys.symmetric_keys
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
certificate_id AS id,
''CERTIFICATE'' AS class_desc,
''CERTIFICATE'' AS class
FROM sys.certificates
UNION ALL
SELECT NULL AS SchemaName,
name ' + @Collation + N' AS name,
asymmetric_key_id AS id,
''ASYMMETRIC_KEY'' AS class_desc,
''ASYMMETRIC KEY'' AS class
FROM sys.asymmetric_keys
) ' + NCHAR(13);
SET @sql =
N'SELECT ' + CASE WHEN @DBName = 'All' THEN N'@AllDBNames' ELSE N'N''' + @DBName + N'''' END + N' AS DBName,
Grantee.principal_id AS GranteePrincipalId, Grantee.name AS GranteeName, Grantor.name AS GrantorName,
Permission.class_desc, Permission.permission_name,
ObjectList.name + CASE WHEN Columns.name IS NOT NULL THEN '' ('' + Columns.name + '')'' ELSE '''' END AS ObjectName,
ObjectList.SchemaName,
Permission.state_desc,
CASE WHEN Grantee.is_fixed_role = 0 AND Grantee.name <> ''dbo'' THEN ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' + NCHAR(13) ELSE N'' END +
N' ''REVOKE '' +
CASE WHEN Permission.[state] = ''W'' THEN ''GRANT OPTION FOR '' ELSE '''' END +
'' '' + Permission.permission_name' + @Collation + N' +
CASE WHEN Permission.major_id <> 0 THEN '' ON '' +
ObjectList.class + ''::'' +
ISNULL(QUOTENAME(ObjectList.SchemaName),'''') +
CASE WHEN ObjectList.SchemaName + ObjectList.name IS NULL THEN '''' ELSE ''.'' END +
ISNULL(QUOTENAME(ObjectList.name),'''') + ISNULL('' (''+ QUOTENAME(Columns.name) + '')'','''')
' + @Collation + ' + '' '' ELSE '''' END +
'' FROM '' + QUOTENAME(' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'Grantee.name') + '' + @Collation + N') + ''; '' END AS RevokeScript,
CASE WHEN Grantee.is_fixed_role = 0 AND Grantee.name <> ''dbo'' THEN ' + NCHAR(13) +
CASE WHEN @DBName = 'All' THEN N' ''USE '' + QUOTENAME(@AllDBNames) + ''; '' + ' + NCHAR(13) ELSE N'' END +
N' CASE WHEN Permission.[state] = ''W'' THEN ''GRANT'' ELSE Permission.state_desc' + @Collation +
N' END +
'' '' + Permission.permission_name' + @Collation + N' +
CASE WHEN Permission.major_id <> 0 THEN '' ON '' +
ObjectList.class + ''::'' +
ISNULL(QUOTENAME(ObjectList.SchemaName),'''') +
CASE WHEN ObjectList.SchemaName + ObjectList.name IS NULL THEN '''' ELSE ''.'' END +
ISNULL(QUOTENAME(ObjectList.name),'''') + ISNULL('' (''+ QUOTENAME(Columns.name) + '')'','''')
' + @Collation + N' + '' '' ELSE '''' END +
'' TO '' + QUOTENAME(' + ISNULL('N'+QUOTENAME(@CopyTo,''''),'Grantee.name') + '' + @Collation + N') + '' '' +
CASE WHEN Permission.[state] = ''W'' THEN '' WITH GRANT OPTION '' ELSE '''' END +
'' AS ''+ QUOTENAME(Grantor.name' + @Collation + N')+'';'' END AS GrantScript
FROM sys.database_permissions Permission
JOIN sys.database_principals Grantee
ON Permission.grantee_principal_id = Grantee.principal_id
JOIN sys.database_principals Grantor
ON Permission.grantor_principal_id = Grantor.principal_id
LEFT OUTER JOIN ObjectList
ON Permission.major_id = ObjectList.id
AND Permission.class_desc = ObjectList.class_desc
LEFT OUTER JOIN sys.columns AS Columns
ON Permission.major_id = Columns.object_id
AND Permission.minor_id = Columns.column_id
WHERE 1=1 ';
IF LEN(ISNULL(@Principal,@Role)) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Grantee.name ' + @LikeOperator + N' N' + ISNULL(QUOTENAME(@Principal,''''),QUOTENAME(@Role,''''));
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Grantee.name ' + @LikeOperator + N' ISNULL(@Principal,@Role) ';
IF LEN(@Type) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Grantee.type ' + @LikeOperator + N' N' + QUOTENAME(@Type,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Grantee.type ' + @LikeOperator + N' @Type';
IF LEN(@ObjectName) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND ObjectList.name ' + @LikeOperator + N' N' + QUOTENAME(@ObjectName,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND ObjectList.name ' + @LikeOperator + N' @ObjectName ';
IF LEN(@Permission) > 0
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND Permission.permission_name ' + @LikeOperator + N' N' + QUOTENAME(@Permission,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND Permission.permission_name ' + @LikeOperator + N' @Permission';
IF LEN(@LoginName) > 0
BEGIN
SET @sql = @sql + NCHAR(13) +
N' AND EXISTS (SELECT 1
FROM sys.server_principals SrvPrincipals
WHERE SrvPrincipals.sid = Grantee.sid
AND Grantee.sid NOT IN (0x00, 0x01)
AND Grantee.type NOT IN (''R'') ' + NCHAR(13);
IF @Print = 1
SET @sql = @sql + NCHAR(13) + N' AND SrvPrincipals.name ' + @LikeOperator + N' N' + QUOTENAME(@LoginName,'''');
ELSE
SET @sql = @sql + NCHAR(13) + N' AND SrvPrincipals.name ' + @LikeOperator + N' @LoginName';
SET @sql = @sql + ')';
END;
IF @IncludeMSShipped = 0
SET @sql = @sql + NCHAR(13) + N' AND Grantee.is_fixed_role = 0 ' + NCHAR(13) +
' AND Grantee.name NOT IN (''dbo'',''public'',''INFORMATION_SCHEMA'',''guest'',''sys'') ';
IF @Print = 1
BEGIN
PRINT '-- Database & object Permissions';
PRINT CAST(@use AS NVARCHAR(MAX));
PRINT CAST(@ObjectList AS NVARCHAR(MAX));
PRINT CAST(@ObjectList2 AS NVARCHAR(MAX));
PRINT CAST(@sql AS NVARCHAR(MAX));
END;
ELSE
BEGIN
IF OBJECT_ID('tempdb..##DBPermissions') IS NOT NULL
DROP TABLE ##DBPermissions;
-- Create temp table to store the data in
CREATE TABLE ##DBPermissions (
[dbname] sysname NULL,
GranteePrincipalId INT NULL,
GranteeName sysname NULL,
GrantorName sysname NULL,
[class_desc] NVARCHAR(60) NULL,
[permission_name] NVARCHAR(128) NULL,
ObjectName sysname NULL,
SchemaName sysname NULL,
[state_desc] NVARCHAR(60) NULL,
RevokeScript NVARCHAR(MAX) NULL,
GrantScript NVARCHAR(MAX) NULL
);
-- Add insert statement to @sql
SET @sql = @use + @ObjectList + @ObjectList2 +
N'INSERT INTO ##DBPermissions ' + NCHAR(13) +
@sql;
IF @DBName = 'All'
BEGIN
-- Declare a READ_ONLY cursor to loop through the databases
DECLARE cur_DBList CURSOR
READ_ONLY
FOR SELECT [name] FROM [sys].[databases]
WHERE STATE IN (0,5)
AND [source_database_id] IS NULL
ORDER BY [name];
OPEN cur_DBList;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
SET @sql2 = 'USE ' + QUOTENAME(@AllDBNames) + ';' + NCHAR(13) + @sql;
EXECUTE sp_executesql @sql2,
N'@Principal sysname, @Role sysname, @Type nvarchar(30), @ObjectName sysname,
@AllDBNames sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @AllDBNames, @Permission, @LoginName;
-- PRINT @sql2
END;
FETCH NEXT FROM cur_DBList INTO @AllDBNames;
END;
CLOSE cur_DBList;
DEALLOCATE cur_DBList;
END;
ELSE
BEGIN
EXECUTE sp_executesql @sql, N'@Principal sysname, @Role sysname, @Type nvarchar(30),
@ObjectName sysname, @Permission sysname, @LoginName sysname',
@Principal, @Role, @Type, @ObjectName, @Permission, @LoginName;
END;
END;
END;
IF @Print <> 1
IF (SERVERPROPERTY('ProductVersion') >= '12' AND @ShowOrphans = 1)
IF @Output IN ('CreateOnly', 'DropOnly', 'ScriptOnly')
SELECT DropScript, CreateScript, CreateLogin, AlterUser
FROM ##DBPrincipals ORDER BY [dbname], DBPrincipal;
ELSE
SELECT [dbname], DBPrincipal, SrvPrincipal, TYPE, [type_desc], [default_schema_name],
[create_date], [modify_date], [is_fixed_role], RoleAuthorization, [sid],
DropScript, CreateScript, CreateLogin, AlterUser
FROM ##DBPrincipals ORDER BY [dbname], DBPrincipal;
ELSE
BEGIN
IF @Output = 'None'
PRINT '';
ELSE IF @Output = 'CreateOnly'
BEGIN
SELECT CreateScript FROM ##DBPrincipals WHERE CreateScript IS NOT NULL
UNION ALL
SELECT AddScript FROM ##DBRoles WHERE AddScript IS NOT NULL
UNION ALL
SELECT GrantScript FROM ##DBPermissions WHERE GrantScript IS NOT NULL;
END;
ELSE IF @Output = 'DropOnly'
BEGIN
SELECT DropScript FROM ##DBPrincipals WHERE DropScript IS NOT NULL
UNION ALL
SELECT DropScript FROM ##DBRoles WHERE DropScript IS NOT NULL
UNION ALL
SELECT RevokeScript FROM ##DBPermissions WHERE RevokeScript IS NOT NULL;
END;
ELSE IF @Output = 'ScriptOnly'
BEGIN
SELECT DropScript, CreateScript FROM ##DBPrincipals WHERE DropScript IS NOT NULL OR CreateScript IS NOT NULL
UNION ALL
SELECT DropScript, AddScript FROM ##DBRoles WHERE DropScript IS NOT NULL OR AddScript IS NOT NULL
UNION ALL
SELECT RevokeScript, GrantScript FROM ##DBPermissions WHERE RevokeScript IS NOT NULL OR GrantScript IS NOT NULL;
END;
ELSE IF @Output = 'Report'
BEGIN
SELECT [dbname], DBPrincipal, SrvPrincipal, TYPE, [type_desc],
STUFF((SELECT N', ' + ##DBRoles.RoleName
FROM ##DBRoles
WHERE ##DBPrincipals.[dbname] = ##DBRoles.[dbname]
AND ##DBPrincipals.DBPrincipalId = ##DBRoles.UserPrincipalId
ORDER BY ##DBRoles.RoleName
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)')
, 1, 2, '') AS RoleMembership,
STUFF((SELECT N', ' + ##DBPermissions.[state_desc] + N' ' + ##DBPermissions.[permission_name] + N' on ' +
COALESCE(N'OBJECT:'+##DBPermissions.SchemaName + N'.' + ##DBPermissions.ObjectName,
N'SCHEMA:'+##DBPermissions.SchemaName,
N'DATABASE:'+##DBPermissions.[dbname])
FROM ##DBPermissions
WHERE ##DBPrincipals.[dbname] = ##DBPermissions.[dbname]
AND ##DBPrincipals.DBPrincipalId = ##DBPermissions.GranteePrincipalId
ORDER BY ##DBPermissions.[state_desc], ISNULL(##DBPermissions.ObjectName, ##DBPermissions.[dbname]), ##DBPermissions.[permission_name]
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)')
, 1, 2, '') AS DirectPermissions
FROM ##DBPrincipals
ORDER BY [dbname], TYPE, DBPrincipal;
END;
ELSE -- 'Default' or no match
BEGIN
SELECT [dbname], DBPrincipal, SrvPrincipal, TYPE, [type_desc], [default_schema_name],
[create_date], [modify_date], [is_fixed_role], RoleAuthorization, [sid],
DropScript, CreateScript
FROM ##DBPrincipals ORDER BY [dbname], DBPrincipal;
IF LEN(@Role) > 0
SELECT [dbname], UserName, RoleName, DropScript, AddScript
FROM ##DBRoles ORDER BY [dbname], RoleName, UserName;
ELSE
SELECT [dbname], UserName, RoleName, DropScript, AddScript
FROM ##DBRoles ORDER BY [dbname], UserName, RoleName;
IF LEN(@ObjectName) > 0
SELECT [dbname], GranteeName, GrantorName, [class_desc], [permission_name], ObjectName,
SchemaName, [state_desc], RevokeScript, GrantScript
FROM ##DBPermissions ORDER BY [dbname], SchemaName, ObjectName, GranteeName, [permission_name];
ELSE
SELECT [dbname], GranteeName, GrantorName, [class_desc], [permission_name], ObjectName,
SchemaName, [state_desc], RevokeScript, GrantScript
FROM ##DBPermissions ORDER BY [dbname], GranteeName, SchemaName, ObjectName, [permission_name];
END;
IF @DropTempTables = 1
BEGIN
DROP TABLE ##DBPrincipals;
DROP TABLE ##DBRoles;
DROP TABLE ##DBPermissions;
END;
END;
GO
IF OBJECT_ID('tempdb..#logins')IS NOT NULL BEGIN;
DROP TABLE #logins;
END;
CREATE TABLE #logins ( [DBName] NVARCHAR(128), [DBPrincipal] NVARCHAR(128), [SrvPrincipal] NVARCHAR(128), [type] CHAR(1), [type_desc] NCHAR(60), [RoleMembership] NVARCHAR(MAX), [DirectPermissions] NVARCHAR(MAX) );
INSERT INTO [#logins] ([DBName],
[DBPrincipal],
[SrvPrincipal],
[type],
[type_desc],
[RoleMembership],
[DirectPermissions])
EXECUTE master.[dbo].sp_DBPermissions @DBName='ALL', @type='U', @Output='report';
INSERT INTO [#logins] ([DBName],
[DBPrincipal],
[SrvPrincipal],
[type],
[type_desc],
[RoleMembership],
[DirectPermissions])
EXECUTE master.[dbo].sp_DBPermissions @DBName='ALL', @type='S', @Output='report';
SELECT DISTINCT
'sql and ad logins' AS [description]
,[l].[DBPrincipal]
,[l].[SrvPrincipal]
,[l].[type]
--,[l].[type_desc]
--,[l].[RoleMembership]
--,[l].[DirectPermissions]
,STUFF(p.[perm],1,1,'') AS directPermissions
,STUFF(o.[dbName],1,1,'') AS dbNames
FROM [#logins] l
CROSS APPLY (
SELECT ','+[l2].[DBName]
FROM [#logins] l2
WHERE [l2].[DBPrincipal]=l.[DBPrincipal]
GROUP BY [l2].[DBName]
ORDER BY [l2].[DBName]
FOR XML PATH('')
) o([dbName])
CROSS APPLY (
SELECT ';'+[l2].[DirectPermissions]
FROM [#logins] l2
WHERE [l2].[DBPrincipal]=l.[DBPrincipal]
GROUP BY [l2].[DirectPermissions]
ORDER BY [l2].[DirectPermissions]
FOR XML PATH('')
) p(perm)
WHERE [l].[SrvPrincipal] IS NOT NULL
AND [l].[SrvPrincipal] NOT IN (
'##MS_PolicyEventProcessingLogin##'
,'##MS_PolicyTsqlExecutionLogin##'
)
AND [l].[DBPrincipal] NOT IN(
'dbo'
,'guest'
,'INFORMATION_SCHEMA'
,'sys'
)
ORDER BY [SrvPrincipal];
SELECT DISTINCT
'orphan logins' AS [description]
,[l].[DBPrincipal]
,[l].[SrvPrincipal]
,STUFF(o.[dbName],1,1,'') AS dbs
FROM [#logins] l
CROSS APPLY (
SELECT ','+[l2].[DBName]
FROM [#logins] l2
WHERE [l2].[DBPrincipal]=l.[DBPrincipal]
GROUP BY [l2].[DBName]
ORDER BY [l2].[DBName]
FOR XML PATH('')
) o([dbName])
WHERE [l].[DBPrincipal] IS NOT NULL
AND [l].[SrvPrincipal] IS NULL
AND [l].[DBPrincipal] NOT IN(
'dbo'
,'guest'
,'INFORMATION_SCHEMA'
,'sys'
,'MS_DataCollectorInternalUser'
)
ORDER BY [l].[DBPrincipal];