Scripting SQL Server permissions

前端 未结 9 2160
轮回少年
轮回少年 2021-01-30 02:58

I want to copy all the permission I\'ve set on stored procedures and other stuff from my development database to my production database. It\'s incredibly cumbersome, not to ment

9条回答
  •  情书的邮戳
    2021-01-30 03:58

    Our version:

    SET NOCOUNT ON
    
    DECLARE @message NVARCHAR(MAX)
    
    -- GENERATE LOGINS CREATE SCRIPT
    
    
    USE [master]
    
    -- creating accessory procedure
    
    IF EXISTS (SELECT 1 FROM    sys.objects WHERE   object_id = OBJECT_ID(N'sp_hexadecimal') AND type IN ( N'P', N'PC' )) 
    DROP PROCEDURE [dbo].[sp_hexadecimal]
    EXEC('
    CREATE PROCEDURE [dbo].[sp_hexadecimal]
        @binvalue varbinary(256),
        @hexvalue varchar (514) OUTPUT
    AS
    DECLARE @charvalue varchar (514)
    DECLARE @i int
    DECLARE @length int
    DECLARE @hexstring char(16)
    SELECT @charvalue = ''0x''
    SELECT @i = 1
    SELECT @length = DATALENGTH (@binvalue)
    SELECT @hexstring = ''0123456789ABCDEF''
    WHILE (@i <= @length)
    BEGIN
      DECLARE @tempint int
      DECLARE @firstint int
      DECLARE @secondint int
      SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
      SELECT @firstint = FLOOR(@tempint/16)
      SELECT @secondint = @tempint - (@firstint*16)
      SELECT @charvalue = @charvalue +
        SUBSTRING(@hexstring, @firstint+1, 1) +
        SUBSTRING(@hexstring, @secondint+1, 1)
      SELECT @i = @i + 1
    END
    
    SELECT @hexvalue = @charvalue')
    
    SET @message = '-- CREATE LOGINS' + CHAR(13) + CHAR(13) +'USE [master]' + CHAR(13)
    
    DECLARE @name sysname
    DECLARE @type varchar (1)
    DECLARE @hasaccess int
    DECLARE @denylogin int
    DECLARE @is_disabled int
    DECLARE @PWD_varbinary  varbinary (256)
    DECLARE @PWD_string  varchar (514)
    DECLARE @SID_varbinary varbinary (85)
    DECLARE @SID_string varchar (514)
    DECLARE @tmpstr  NVARCHAR(MAX)
    DECLARE @is_policy_checked varchar (3)
    DECLARE @is_expiration_checked varchar (3)
    
    DECLARE @defaultdb sysname
    
    DECLARE login_curs CURSOR FOR
          SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM 
    sys.server_principals p LEFT JOIN sys.syslogins l
          ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name <> 'sa'
    
    OPEN login_curs
    
    FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin
    IF (@@fetch_status = -1)
    BEGIN
      PRINT 'No login(s) found.'
      CLOSE login_curs
      DEALLOCATE login_curs
    END
    
    WHILE (@@fetch_status <> -1)
    BEGIN
      IF (@@fetch_status <> -2)
      BEGIN
    
        IF (@type IN ( 'G', 'U'))
        BEGIN -- NT authenticated account/group
    
          SET @tmpstr = 'IF NOT EXISTS (SELECT loginname FROM master.dbo.syslogins WHERE name = ''' + @name + ''' AND dbname = ''' + @defaultdb + ''')' + CHAR(13) +
                        'BEGIN TRY' + CHAR(13) +
                        '   CREATE LOGIN ' + QUOTENAME( @name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']'
    
        END
        ELSE BEGIN -- SQL Server authentication
            -- obtain password and sid
                SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, 'PasswordHash' ) AS varbinary (256) )
            EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT
            EXEC sp_hexadecimal @SID_varbinary,@SID_string OUT
    
            -- obtain password policy state
            SELECT @is_policy_checked = CASE is_policy_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name
            SELECT @is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name
    
                SET @tmpstr = 'IF NOT EXISTS (SELECT loginname FROM master.dbo.syslogins WHERE name = ''' + @name + ''' AND dbname = ''' + @defaultdb + ''')' + CHAR(13) +
                        'BEGIN TRY' + CHAR(13) +
                        '   CREATE LOGIN ' + QUOTENAME( @name ) + ' WITH PASSWORD = ' + @PWD_string + ' HASHED, SID = ' + @SID_string + ', DEFAULT_DATABASE = [' + @defaultdb + ']'
    
            IF ( @is_policy_checked IS NOT NULL )
            BEGIN
              SET @tmpstr = @tmpstr + ', CHECK_POLICY = ' + @is_policy_checked
            END
            IF ( @is_expiration_checked IS NOT NULL )
            BEGIN
              SET @tmpstr = @tmpstr + ', CHECK_EXPIRATION = ' + @is_expiration_checked
            END
        END
        IF (@denylogin = 1)
        BEGIN -- login is denied access
          SET @tmpstr = @tmpstr + '; DENY CONNECT SQL TO ' + QUOTENAME( @name )
        END
        ELSE IF (@hasaccess = 0)
        BEGIN -- login exists but does not have access
          SET @tmpstr = @tmpstr + '; REVOKE CONNECT SQL TO ' + QUOTENAME( @name )
        END
        IF (@is_disabled = 1)
        BEGIN -- login is disabled
          SET @tmpstr = @tmpstr + '; ALTER LOGIN ' + QUOTENAME( @name ) + ' DISABLE'
        END
    
        SET @tmpstr = @tmpstr + CHAR(13) + 'END TRY' + CHAR(13) + 'BEGIN CATCH' + CHAR(13) + 'END CATCH'
    
        SET @message = @message + CHAR(13) + @tmpstr
    
      END
    
      FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin
       END
    CLOSE login_curs
    DEALLOCATE login_curs
    
    --removing accessory procedure
    
    DROP PROCEDURE [dbo].[sp_hexadecimal]
    
    
    -- GENERATE SERVER PERMISSIONS
    USE [master]
    
    DECLARE @ServerPrincipal SYSNAME
    DECLARE @PrincipalType SYSNAME 
    DECLARE @PermissionName SYSNAME
    DECLARE @StateDesc SYSNAME
    
    SET @message = @message + CHAR(13) + CHAR(13) + '-- CREATE SERVER PERMISSIONS' + CHAR(13) + CHAR(13) +'USE [master]' + CHAR(13)
    
    DECLARE server_permissions_curs CURSOR FOR
    SELECT
      [srvprin].[name] [server_principal], 
      [srvprin].[type_desc] [principal_type], 
      [srvperm].[permission_name], 
      [srvperm].[state_desc]  
    FROM [sys].[server_permissions] srvperm 
      INNER JOIN [sys].[server_principals] srvprin 
        ON [srvperm].[grantee_principal_id] = [srvprin].[principal_id] 
    WHERE [srvprin].[type] IN ('S', 'U', 'G') AND [srvprin].name NOT IN ('sa', 'dbo', 'information_schema', 'sys')
    ORDER BY [server_principal], [permission_name]; 
    
    OPEN server_permissions_curs
    
    FETCH NEXT FROM server_permissions_curs INTO @ServerPrincipal, @PrincipalType, @PermissionName, @StateDesc 
    
    WHILE (@@fetch_status <> -1)
    BEGIN
    
        SET @message = @message + CHAR(13) + 'BEGIN TRY' + CHAR(13) + 
                        @StateDesc + N' ' + @PermissionName + N' TO ' + QUOTENAME(@ServerPrincipal) + 
                        + CHAR(13) + 'END TRY' + CHAR(13) + 'BEGIN CATCH' + CHAR(13) + 'END CATCH'
    
        FETCH NEXT FROM server_permissions_curs INTO @ServerPrincipal, @PrincipalType, @PermissionName, @StateDesc 
    END
    CLOSE server_permissions_curs
    DEALLOCATE server_permissions_curs
    
    --GENERATE USERS AND PERMISSION SCRIPT FOR EVERY DATABASE
    
    SET @message = @message + CHAR(13) + CHAR(13) + N'--ENUMERATE DATABASES'
    
    DECLARE @databases TABLE (
        DatabaseName SYSNAME,
        DatabaseSize INT,
        Remarks SYSNAME NULL
    )
    
    INSERT INTO
    @databases EXEC sp_databases
    
    DECLARE @DatabaseName SYSNAME
    
    
    DECLARE database_curs CURSOR FOR
    SELECT DatabaseName FROM @databases WHERE DatabaseName IN (N'${DatabaseName}')
    
    OPEN database_curs
    
    FETCH NEXT FROM database_curs INTO @DatabaseName
    WHILE (@@fetch_status <> -1)
    BEGIN
    
        SET @tmpStr = 
    
        N'USE ' + QUOTENAME(@DatabaseName) + '
    
        DECLARE @tmpstr  NVARCHAR(MAX)
    
        SET @messageOut = CHAR(13) + CHAR(13) + ''USE ' + QUOTENAME(@DatabaseName) + ''' + CHAR(13)
    
        -- GENERATE USERS SCRIPT 
    
        SET @messageOut = @messageOut + CHAR(13) + ''-- CREATE USERS '' + CHAR(13)
    
        DECLARE @users TABLE (
        UserName SYSNAME Null,  
        RoleName SYSNAME Null,  
        LoginName SYSNAME Null, 
        DefDBName SYSNAME Null, 
        DefSchemaName SYSNAME Null, 
        UserID INT Null,    
        [SID] varbinary(85) Null
        )
    
        INSERT INTO
        @users   EXEC sp_helpuser
    
        DECLARE @UserName SYSNAME
        DECLARE @LoginName SYSNAME 
        DECLARE @DefSchemaName SYSNAME
    
        DECLARE user_curs CURSOR FOR
        SELECT UserName, LoginName, DefSchemaName FROM @users
    
        OPEN user_curs
    
        FETCH NEXT FROM user_curs INTO @UserName, @LoginName, @DefSchemaName
        WHILE (@@fetch_status <> -1)
        BEGIN
    
            SET @messageOut = @messageOut + CHAR(13) + 
                            ''IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = N''''''+ @UserName +'''''')''
                            + CHAR(13) + ''BEGIN TRY'' + CHAR(13) + 
                            ''  CREATE USER '' + QUOTENAME(@UserName)
    
            IF (@LoginName IS NOT NULL)
                SET @messageOut = @messageOut + '' FOR LOGIN '' + QUOTENAME(@LoginName)
            ELSE
                SET @messageOut = @messageOut + '' WITHOUT LOGIN''  
    
            IF (@DefSchemaName IS NOT NULL)
                SET @messageOut = @messageOut + '' WITH DEFAULT_SCHEMA = ''  + QUOTENAME(@DefSchemaName)
    
            SET @messageOut = @messageOut + CHAR(13) + ''END TRY'' + CHAR(13) + ''BEGIN CATCH'' + CHAR(13) + ''END CATCH''
    
            FETCH NEXT FROM user_curs INTO @UserName, @LoginName, @DefSchemaName
        END
        CLOSE user_curs
        DEALLOCATE user_curs
    
        -- GENERATE ROLES
    
        SET @messageOut = @messageOut + CHAR(13) + CHAR(13) + ''-- CREATE ROLES '' + CHAR(13)
    
        SELECT @messageOut = @messageOut + CHAR(13) + ''BEGIN TRY'' + CHAR(13) + 
                            N''EXEC sp_addrolemember N''''''+ rp.name +'''''', N''''''+ mp.name +''''''''
                            + CHAR(13) + ''END TRY'' + CHAR(13) + ''BEGIN CATCH'' + CHAR(13) + ''END CATCH''
        FROM sys.database_role_members drm
        join sys.database_principals rp ON (drm.role_principal_id = rp.principal_id)
        join sys.database_principals mp ON (drm.member_principal_id = mp.principal_id)
        WHERE mp.name NOT IN (N''dbo'')
    
    
        -- GENERATE PERMISSIONS
    
        SET @messageOut = @messageOut + CHAR(13) + CHAR(13) + ''-- CREATE PERMISSIONS '' + CHAR(13)
    
        SELECT @messageOut = @messageOut + CHAR(13) + ''BEGIN TRY'' + CHAR(13) + 
                            ''  GRANT '' + dp.permission_name collate latin1_general_cs_as +
                            '' ON '' + QUOTENAME(s.name) + ''.'' + QUOTENAME(o.name) + '' TO '' + QUOTENAME(dpr.name)  +
                            + CHAR(13) + ''END TRY'' + CHAR(13) + ''BEGIN CATCH'' + CHAR(13) + ''END CATCH''
        FROM sys.database_permissions AS dp
        INNER JOIN sys.objects AS o ON dp.major_id=o.object_id
        INNER JOIN sys.schemas AS s ON o.schema_id = s.schema_id
        INNER JOIN sys.database_principals AS dpr ON dp.grantee_principal_id=dpr.principal_id
        WHERE dpr.name NOT IN (''public'',''guest'')'
    
        EXECUTE sp_executesql @tmpStr, N'@messageOut NVARCHAR(MAX) OUTPUT', @messageOut = @tmpstr OUTPUT
    
        SET @message = @message + @tmpStr
    
        FETCH NEXT FROM database_curs INTO @DatabaseName
    END
    CLOSE database_curs
    DEALLOCATE database_curs
    
    SELECT @message
    

提交回复
热议问题