Technical Article

Script Login Roles Permissions in all DBSs

,

Populate @list variable with account(s) to script. Save output to recreate:Login, Password,Default DB,Server Roles,DB Access,DB Roles,DB Object Permissions

DB level permissions are scripted in all databases.

Can recreate a single login, or accepts comma delimted list of logins.

NOTE:
Stored procedures are created in Master, but are deleted

------------------------------------------------------------------------------------
-- Description: Provide a list of login(s) and create a script to recreate all login and user settings
--  Revision History
--  Date           Author            Revision Description
-- 10/19/2005   Terry Duffy Original (Expanded from MS code and code from Bradley Morris)
------------------------------------------------------------------------------------
--  Usage
-- Populate @list variable below with account(s),comma delimited list to script. 
-- Save output to recreate:Login,Default DB,Server Roles,DB Access,DB Roles,DB Object Permissions.
-- NOTE:
-- Stored procedures are created in Master, but are deleted
/*****************************Start Create needed procedures***************************/USE master
GO
IF OBJECT_ID ('usp_hexadecimal') IS NOT NULL
  DROP PROCEDURE usp_hexadecimal
GO

CREATE PROCEDURE usp_hexadecimal @binvalue varbinary(256),@hexvalue varchar(256) OUTPUT
AS
DECLARE @charvalue varchar(256)
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
GO

IF OBJECT_ID ('usp_help_revlogin') IS NOT NULL
  DROP PROCEDURE usp_help_revlogin 
GO

CREATE PROCEDURE usp_help_revlogin @login_name sysname = NULL 
AS
DECLARE @name    sysname
DECLARE @xstatus int
DECLARE @binpwd  varbinary (256)
DECLARE @txtpwd  sysname
DECLARE @tmpstr  varchar (256)
DECLARE @SID_varbinary varbinary(85)
DECLARE @SID_string varchar(256)

IF (@login_name IS NULL)
  DECLARE login_curs CURSOR FOR 
    SELECT 
sid, name, xstatus, password 
FROM 
master..sysxlogins 
  WHERE 
srvid IS NULL 
AND name <> 'sa'
ELSE
  DECLARE login_curs CURSOR FOR 
    SELECT 
sid, name, xstatus, password 
FROM 
master..sysxlogins 
    WHERE 
srvid IS NULL 
AND name = @login_name

OPEN login_curs 
FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd
IF (@@fetch_status = -1)
BEGIN
  PRINT 'No login(s) found.'
  CLOSE login_curs 
  DEALLOCATE login_curs 
  RETURN -1
END
SET @tmpstr = '/* usp_help_revlogin script ' 
--PRINT @tmpstr
SET @tmpstr = '** Generated ' 
  + CONVERT (varchar, GETDATE()) + ' on ' + @@SERVERNAME + ' */'
--PRINT @tmpstr
--PRINT ''
PRINT 'DECLARE @pwd sysname'
WHILE (@@fetch_status <> -1)
BEGIN
  IF (@@fetch_status <> -2)
BEGIN
    PRINT ''
    SET @tmpstr = '-- Login: ' + @name
    PRINT @tmpstr 
    IF (@xstatus & 4) = 4
    BEGIN -- NT authenticated account/group
      IF (@xstatus & 1) = 1
      BEGIN -- NT login is denied access
        SET @tmpstr = 'EXEC master..sp_denylogin ''' + @name + ''''
        PRINT @tmpstr 
      END
      ELSE 
BEGIN -- NT login has access
        SET @tmpstr = 'EXEC master..sp_grantlogin ''' + @name + ''''
        PRINT @tmpstr 
      END
    END
    ELSE 
BEGIN -- SQL Server authentication
      IF (@binpwd IS NOT NULL)
      BEGIN -- Non-null password
        EXEC usp_hexadecimal @binpwd, @txtpwd OUT
        IF (@xstatus & 2048) = 2048
          SET @tmpstr = 'SET @pwd = CONVERT (varchar(256), ' + @txtpwd + ')'
        ELSE
          SET @tmpstr = 'SET @pwd = CONVERT (varbinary(256), ' + @txtpwd + ')'
        PRINT @tmpstr

EXEC usp_hexadecimal @SID_varbinary,@SID_string OUT
        SET @tmpstr = 'EXEC master..sp_addlogin ''' + @name 
          + ''', @pwd, @sid = ' + @SID_string + ', @encryptopt = '
      END
      ELSE 
BEGIN 
        -- Null password
EXEC usp_hexadecimal @SID_varbinary,@SID_string OUT
        SET @tmpstr = 'EXEC master..sp_addlogin ''' + @name 
          + ''', NULL, @sid = ' + @SID_string + ', @encryptopt = '
      END
      
IF (@xstatus & 2048) = 2048
        -- login upgraded from 6.5
        SET @tmpstr = @tmpstr + '''skip_encryption_old''' 
      ELSE 
        SET @tmpstr = @tmpstr + '''skip_encryption'''
      PRINT @tmpstr 
END
END
FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd
END


CLOSE login_curs 
DEALLOCATE login_curs 
RETURN 0
GO
/*****************************End Create needed procedures***************************/SET NOCOUNT ON
Declare 
@List varchar(8000),
@DatabaseUserName [sysname],
@DatabaseUserID [smallint],
@ServerUserName [sysname],
@RoleName [varchar](8000),
@ObjectID [int],
@ObjectName [varchar](261),
@DB_Name sysname,
@cmd varchar(8000),
@count int
set @List = 'test1234,mytest,corporate\tduffy'
set @List = @List + ',' 

Create Table ##DB_USERs
(
Name sysname,
DatabaseUserID smallint,
ServerUserName sysname
)

Create Table ##DB_Roles
(
Name sysname
)


CREATE TABLE ##sysobjects (
[name] [sysname] NULL ,
[id] [int] NULL ,
[xtype] [char] (2) NULL ,
[uid] [smallint] NULL ,
[info] [smallint] NULL ,
[status] [int] NULL ,
[base_schema_ver] [int] NULL ,
[replinfo] [int] NULL ,
[parent_obj] [int] NULL ,
[crdate] [datetime] NULL ,
[ftcatid] [smallint] NULL ,
[schema_ver] int NULL ,
[stats_schema_ver] int NULL ,
[type] char(2) NULL ,
[userstat] smallint NULL ,
[sysstat] smallint NULL ,
[indexdel] smallint NULL ,
[refdate] datetime null,
[version] int NULL ,
[deltrig] int NULL ,
[instrig] int NULL ,
[updtrig] int NULL ,
[seltrig] int NULL ,
[category] int NULL ,
[cache] smallint NULL ,
) 

CREATE TABLE ##sysprotects (
[id] [int] NOT NULL ,
[uid] [smallint] NOT NULL ,
[action] [tinyint] NOT NULL ,
[protecttype] [tinyint] NOT NULL ,
[columns] [varbinary] (4000) NULL ,
[grantor] [smallint] NOT NULL 
)

CREATE TABLE ##SRV_Roles 
(
SERVERROLE VARCHAR(100),
MEMBERNAME VARCHAR(100),
MEMBERSID  VARBINARY (85)
)
/*Loop thru file_list*/while @List <> '' 
Begin
set @DatabaseUserName  = left( @List, charindex( ',', @List ) - 1 )  
Print '--*************Begin ' + @DatabaseUserName + ' ************************************'
Print '--********Begin Script the Login ********************************************************'
/*Script login with password*/Execute usp_help_revlogin  @DatabaseUserName
Print 'GO'

/*Script default database*/Select @cmd = 'EXEC [MASTER].[DBO].[SP_DEFAULTDB] [' + @DatabaseUserName + '],[' + RTRIM(DBNAME) + ']' + char(13) + 'GO' 
  FROM [MASTER].[DBO].[SYSLOGINS]
WHERE LOGINNAME = @DatabaseUserName
Print '--Assign Default Database'
Print @CMD


/*GET SERVER ROLES INTO TEMPORARY TABLE*/SET @CMD = '[MASTER].[DBO].[SP_HELPSRVROLEMEMBER]'
INSERT INTO ##SRV_Roles EXEC (@CMD)

Set @CMD = ''
Select @CMD = @CMD + 'EXEC sp_addsrvrolemember  @loginame = ' +  char(39) + MemberName +  char(39) + ', @rolename = ' +  char(39) +  ServerRole +   char(39) + char(13) + 'GO' + char(13)
from  ##SRV_Roles where MemberName = @DatabaseUserName
Print '--Assign Server Roles'
Print @CMD
Delete ##SRV_Roles
Print '--********End Script the Login *********************************************************'
Print ''

/*Get a table with dbs where login has access*/set @DB_Name = ''
Select 
@DB_Name = min(name)
from 
master..sysdatabases
where 
name > @DB_Name
While @DB_Name is not null
Begin
Set @cmd = 
'insert ##DB_USERs
SELECT '
+ char(39) + @DB_Name + char(39) + ',' + 
'u.[uid],
l.[loginname]
FROM '
+ @DB_Name + '.[dbo].[sysusers] u
INNER JOIN [master].[dbo].[syslogins] l
ON u.[sid] = l.[sid]
WHERE 
u.[name] = ' + char(39) + @DatabaseUserName + char(39)
Exec (@cmd)
Select 
@DB_Name = min(name) 
from 
master..sysdatabases
where 
name > @DB_Name
End

/*Add users/roles/object permissions to databases*/set @DB_Name = ''
Select 
@DB_Name = min(name)
from 
##DB_USERs
where 
name > @DB_Name
While @DB_Name is not null
Begin
Print '/************Begin Database ' + @DB_Name + ' ****************/'
select @ServerUserName = ServerUserName,@DatabaseUserID = DatabaseUserID  from ##DB_USERs where name = @DB_Name
Set @cmd = 
'USE [' + @DB_Name + ']' + CHAR(13) +
'EXEC [sp_grantdbaccess]' + CHAR(13) +
    CHAR(9) + '@loginame = ''' + @ServerUserName + ''',' + CHAR(13) +
CHAR(9) + '@name_in_db = ''' + @DatabaseUserName + '''' + CHAR(13) +
'GO' 
Print '--Add user to databases'
Print @cmd

/*Populate roles for this user*/Select @cmd = 
'Insert ##DB_Roles
Select name
FROM '
+ @DB_Name + '.[dbo].[sysusers]
WHERE
[uid] IN (SELECT [groupuid] FROM ' +  @DB_Name + '.[dbo].[sysmembers] WHERE [memberuid] = ' + cast(@DatabaseUserID as varchar(25)) + ')'
--Print @cmd
Exec (@cmd)

/*Add user to roles*/Set @cmd = ''
Select @cmd = isnull(@cmd,'') +  'EXEC [sp_addrolemember]' + CHAR(13) +
CHAR(9) + '@rolename = ''' + Name + ''',' + CHAR(13) +
CHAR(9) + '@membername = ''' + @DatabaseUserName + ''''+ CHAR(13) +
'GO' + CHAR(13)
from ##DB_Roles
if len(@cmd) > 0
Print '--Add user to role(s)'
Print @cmd

Delete ##DB_Roles

/*Object Permissions*/set @count = 0
Select @cmd = 
'Insert ##sysobjects Select * FROM ' + @DB_Name + '.[dbo].[sysobjects]'
Exec (@cmd)
Select @cmd = 
'Insert ##sysprotects Select * FROM ' + @DB_Name + '.[dbo].[sysprotects]'
Exec (@cmd)

DECLARE _sysobjects CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
SELECT 
DISTINCT([##sysobjects].[id]), '[' + USER_NAME([##sysobjects].[uid]) + '].[' + [##sysobjects].[name] + ']'
FROM 
[dbo].[##sysprotects]
INNER JOIN [dbo].[##sysobjects]
ON [##sysprotects].[id] = [##sysobjects].[id]
WHERE 
[##sysprotects].[uid] = @DatabaseUserID
OPEN _sysobjects
FETCH NEXT FROM _sysobjects INTO @ObjectID, @ObjectName
WHILE @@FETCH_STATUS = 0
BEGIN
if @count = 0
Begin
Print '--Assign Object Level Permissions'
set @count = 1
End
SET @cmd = ''
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 205)
SET @cmd = @cmd + 'SELECT,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 205)
SET @cmd = @cmd + 'INSERT,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 205)
SET @cmd = @cmd + 'UPDATE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 205)
SET @cmd = @cmd + 'DELETE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 205)
SET @cmd = @cmd + 'EXECUTE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 205)
SET @cmd = @cmd + 'REFERENCES,'
IF LEN(@cmd) > 0
BEGIN
IF RIGHT(@cmd, 1) = ','
SET @cmd = LEFT(@cmd, LEN(@cmd) - 1)
SET @cmd = 'GRANT' + CHAR(13) +
CHAR(9) + @cmd + CHAR(13) +
CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +
CHAR(9) + 'TO ' + @DatabaseUserName
PRINT @cmd + CHAR(13) + 'GO'
END
SET @cmd = ''
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 206)
SET @cmd = @cmd + 'SELECT,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 206)
SET @cmd = @cmd + 'INSERT,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 206)
SET @cmd = @cmd + 'UPDATE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 206)
SET @cmd = @cmd + 'DELETE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 206)
SET @cmd = @cmd + 'EXECUTE,'
IF EXISTS(SELECT * FROM [dbo].[##sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 206)
SET @cmd = @cmd + 'REFERENCES,'
IF LEN(@cmd) > 0
BEGIN
IF RIGHT(@cmd, 1) = ','
SET @cmd = LEFT(@cmd, LEN(@cmd) - 1)
SET @cmd = 'DENY' + CHAR(13) +
CHAR(9) + @cmd + CHAR(13) +
CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +
CHAR(9) + 'TO ' + @DatabaseUserName
PRINT @cmd + CHAR(13) + 'GO'
END
FETCH NEXT FROM _sysobjects INTO @ObjectID, @ObjectName
END
CLOSE _sysobjects
DEALLOCATE _sysobjects

Delete ##sysobjects
Delete ##sysprotects


Print '/************End Database ' + @DB_Name + ' ****************/'
/*next db*/Select 
@DB_Name = min(name)
from 
##DB_USERs
where 
name > @DB_Name
End
Print '--*************End ' + @DatabaseUserName + ' ************************************'
Print ''
/*Parse the list down*/set @List = right( @List, datalength( @List  ) - charindex( ',', @List ) ) 
/*Clear data for the last user*/Delete ##DB_USERs 
End
/*Clean up*/Drop table ##DB_USERs

Drop table ##DB_Roles
Drop table ##sysobjects
Drop table ##sysprotects
Drop table ##SRV_Roles

use master
Drop procedure usp_help_revlogin
Drop procedure usp_hexadecimal

Rate

Share

Share

Rate