Friday, May 27, 2011

Script Out DB Users & Roles/Permissions

Recently at work we were asked to provide a “clean-seed” restore of a database. Basically the database table/schema structures but without any data. The cleanseed templates we have are from the past and they do not include the DB users which were to be retained. So we needed to script out all the users and roles/permissions associated with the users. To do this a fairly simple script will be used which utilizes cursors to give us a T-SQL Statement to create each user which we can run in its entirity on the new clean seed database...

DECLARE @DatabaseUserName [sysname]

SET NOCOUNT ON

DECLARE

@errStatement [varchar](8000),

@msgStatement [varchar](8000),

@DatabaseUserID [smallint],

@ServerUserName [sysname],

@RoleName [varchar](8000),

@ObjectID [int],

@ObjectName [varchar](261)

------------------UserList Cursor---------------------------------------------------------

PRINT '-----------------------------------------------------------------------------------'

DECLARE _Users CURSOR LOCAL FORWARD_ONLY READ_ONLY

FOR

SELECT

[sysusers].[uid],

[sysusers].[name],

[master].[dbo].[syslogins].[loginname]

FROM [dbo].[sysusers]

INNER JOIN [master].[dbo].[syslogins]

ON [sysusers].[sid] = [master].[dbo].[syslogins].[sid]

WHERE [sysusers].[name] NOT IN ('dbo','guest','INFORMATION_SCHEMA','sys')

OPEN _Users

FETCH NEXT FROM _Users INTO @DatabaseUserID, @DatabaseUserName, @ServerUserName

WHILE @@FETCH_STATUS = 0

BEGIN

--------------------Create User Statement-----------------------------------------------------

BEGIN

SET @msgStatement = '--Create User: ' + @DatabaseUserName

PRINT @msgStatement

SET @msgStatement =

'CREATE USER [' + @DatabaseUserName + '] FOR LOGIN [' + @ServerUserName + ']'

+ CHAR(13)

PRINT @msgStatement

----------------------Cursor: add member to roles-------------------------------------------------

SET @msgStatement = '--Add Roles'

PRINT @msgStatement

DECLARE _sysusers CURSOR LOCAL FORWARD_ONLY READ_ONLY

FOR

SELECT

[name]

FROM [dbo].[sysusers]

WHERE

[uid] IN

(

SELECT

[groupuid]

FROM [dbo].[sysmembers]

WHERE [memberuid] = @DatabaseUserID

)

OPEN _sysusers FETCH NEXT FROM _sysusers INTO @RoleName

WHILE @@FETCH_STATUS = 0

BEGIN

SET @msgStatement = 'EXEC [sp_addrolemember]' + CHAR(13) +

CHAR(9) + '@rolename = ' + '''' + @RoleName + '''' + ',' + CHAR(13) +

CHAR(9) + '@membername = ' + '''' + @DatabaseUserName + ''''

PRINT @msgStatement

FETCH NEXT FROM _sysusers

INTO @RoleName

END

CLOSE _sysusers

DEALLOCATE _sysusers

----------------------Object Specific Permissions--------------------------------------------------

SET @msgStatement = CHAR(13) + '--Set Object Specific Permissions'

PRINT @msgStatement

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

SET @msgStatement = ''

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'SELECT,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'INSERT,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'UPDATE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'DELETE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'EXECUTE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 205)

SET @msgStatement = @msgStatement + 'REFERENCES,'

IF LEN(@msgStatement) > 0

BEGIN

IF RIGHT(@msgStatement, 1) = ','

SET @msgStatement = LEFT(@msgStatement, LEN(@msgStatement) -1)

SET @msgStatement = 'GRANT' + CHAR(13) +

CHAR(9) + @msgStatement + CHAR(13) +

CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +

CHAR(9) + 'TO ' + @DatabaseUserName

PRINT @msgStatement

END

SET @msgStatement = ''

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 193 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'SELECT,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 195 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'INSERT,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 197 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'UPDATE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 196 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'DELETE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 224 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'EXECUTE,'

IF EXISTS(SELECT * FROM [dbo].[sysprotects] WHERE [id] = @ObjectID AND [uid] = @DatabaseUserID AND [action] = 26 AND [protecttype] = 206)

SET @msgStatement = @msgStatement + 'REFERENCES,'

IF LEN(@msgStatement) > 0

BEGIN

IF RIGHT(@msgStatement, 1) = ','

SET @msgStatement = LEFT(@msgStatement, LEN(@msgStatement) -1)

SET @msgStatement = 'DENY' + CHAR(13) +

CHAR(9) + @msgStatement + CHAR(13) +

CHAR(9) + 'ON ' + @ObjectName + CHAR(13) +

CHAR(9) + 'TO ' + @DatabaseUserName

PRINT @msgStatement

END

FETCH NEXT FROM _sysobjects

INTO @ObjectID, @ObjectName

END

CLOSE _sysobjects

DEALLOCATE _sysobjects

END

PRINT '-----------------------------------------------------------------------------------'

FETCH NEXT FROM _Users INTO @DatabaseUserID, @DatabaseUserName, @ServerUserName

END

CLOSE _Users

DEALLOCATE _Users

Below this portion shows an example of what the script will produce. A similar statement would get created for each user in the database you ran the script in...

--Create User: LANAKeac1

CREATE USER [LANAKeac1] FOR LOGIN [LANAKeac]

--Add Roles

EXEC [sp_addrolemember]

@rolename = 'db_datareader',

@membername = 'LANAKeac1'

EXEC [sp_addrolemember]

@rolename = 'db_datawriter',

@membername = 'LANAKeac1'

--Set Object Specific Permissions

GRANT

SELECT,INSERT

ON [dbo].[CustTr]

TO LANAKeac1

No comments:

Post a Comment