Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Monday, 20 February 2012

A Script A Day - Day 12 - Granting Role Membership to All Principals


Today's script will grant membership in the db_owner fixed database role in all online read/writable user databases to all principals not in the sysadmin fixed server role.  I have found this script useful when setting up development servers where all developers are given this level of access.  This could however be modified to grant other permissions as required.  Have a look and a play ;)


/*
      -----------------------------------------------------------------
Grant membership in the db_owner fixed database role in all online read/writable user databases to all principals not in the sysadmin fixed server role
      -----------------------------------------------------------------
     
      For more SQL resources, check out SQLServer365.blogspot.co.uk

      -----------------------------------------------------------------

      You may alter this code for your own purposes.
      You may republish altered code as long as you give due credit.
      You must obtain prior permission before blogging this code.
 
      THIS CODE AND INFORMATION ARE PROVIDED "AS IS"
     
      -----------------------------------------------------------------
*/
-- Declare varibles
DECLARE @DatabaseName VARCHAR(255)
DECLARE @PrincipalName VARCHAR(255)
DECLARE @MinDBID INT
DECLARE @MaxDBID INT
DECLARE @MinPrincipalID INT
DECLARE @MaxPrincipalID INT
DECLARE @SQL VARCHAR(255)

-- Drop temporary tables if they exist
IF OBJECT_ID('tempDB.dbo.#Principal') IS NOT NULL
    DROP TABLE #Principal ;
IF OBJECT_ID('tempDB.dbo.#SysAdmin') IS NOT NULL
    DROP TABLE #SysAdmin ;
IF OBJECT_ID('tempDB.dbo.#DBOwner') IS NOT NULL
    DROP TABLE #DBOwner ;   
IF OBJECT_ID('tempDB.dbo.#Database') IS NOT NULL
    DROP TABLE #Database ;   
   
-- Create temporary tables
CREATE TABLE #Principal
    (
      ID INT IDENTITY(1, 1),
      PrincipalName VARCHAR(100)
    )
CREATE TABLE #SysAdmin
    (
      ID INT IDENTITY(1, 1),
      PrincipalName VARCHAR(100)
    )
CREATE TABLE #DBOwner
    (
      ID INT IDENTITY(1, 1),
      PrincipalName VARCHAR(100)
    )
CREATE TABLE #Database
    (
      ID INT IDENTITY(1, 1),
      DatabaseName VARCHAR(100)
    )
     
--Insert Online, Read/Writable database names into temporary table
IF EXISTS ( SELECT  name
            FROM    sys.databases
            WHERE   name NOT IN ( 'master', 'model', 'msdb', 'tempdb',
                                  'distribution', 'reports', 'reportserver',
                                  'reportservertempdb' )
                    AND DATABASEPROPERTYEX(name, 'Updateability') = 'READ_WRITE'
                    AND DATABASEPROPERTYEX(name, 'Status') = 'ONLINE' )
    BEGIN
        INSERT  INTO #Database ( DatabaseName )
                SELECT  name
                FROM    sys.databases
                WHERE   name NOT IN ( 'master', 'model', 'msdb', 'tempdb',
                                      'distribution', 'reports',
                                      'reportserver', 'reportservertempdb' )
                        AND DATABASEPROPERTYEX(name, 'Updateability') = 'READ_WRITE'
                        AND DATABASEPROPERTYEX(name, 'Status') = 'ONLINE'
    END
   
-- Get all server principals
IF EXISTS ( SELECT  sp.name
            FROM    sys.server_principals sp
            WHERE   sp.[type] IN ( 'U', 'G' )--Windows User or Group]
                    AND sp.[is_disabled] = 0
                    AND sp.[name] NOT IN ( 'NT AUTHORITY\SYSTEM',
                                           'NT SERVICE\MSSQLSERVER',
                                           'NT SERVICE\SQLSERVERAGENT' ) )
    BEGIN                                      
        INSERT  INTO #Principal ( PrincipalName )
                SELECT  sp.name
                FROM    sys.server_principals sp
                WHERE   sp.[type] IN ( 'U', 'G' )--Windows User or Group]
                        AND sp.[is_disabled] = 0
                        AND sp.[name] NOT IN ( 'NT AUTHORITY\SYSTEM',
                                               'NT SERVICE\MSSQLSERVER',
                                               'NT SERVICE\SQLSERVERAGENT' )
    END

-- Get all principals who are members of the sysadmin fixed server role   
IF EXISTS ( SELECT  sp.name
            FROM    sys.server_role_members srm
                    INNER JOIN sys.server_principals sp ON sp.principal_id = srm.member_principal_id
            WHERE   sp.[type] IN ( 'U', 'G' )--Windows User or Group]
                    AND sp.[is_disabled] = 0
                    AND srm.role_principal_id = 3 --sysadmin
                    AND sp.[name] NOT IN ( 'NT AUTHORITY\SYSTEM',
                                           'NT SERVICE\MSSQLSERVER',
                                           'NT SERVICE\SQLSERVERAGENT' ) )
    BEGIN                                                                                  
        INSERT  INTO #SysAdmin ( PrincipalName )
                SELECT  sp.name
                FROM    sys.server_role_members srm
                        INNER JOIN sys.server_principals sp ON sp.principal_id = srm.member_principal_id
                WHERE   sp.[type] IN ( 'U', 'G' )--Windows User or Group]
                        AND sp.[is_disabled] = 0
                        AND srm.role_principal_id = 3 --sysadmin
                        AND sp.[name] NOT IN ( 'NT AUTHORITY\SYSTEM',
                                               'NT SERVICE\MSSQLSERVER',
                                               'NT SERVICE\SQLSERVERAGENT' )
    END

-- Only interested in principals which arn't members of sysadmin
DELETE  FROM #Principal
WHERE   PrincipalName IN ( SELECT   PrincipalName
                           FROM     #SysAdmin )
-- Set variables for loop
SELECT  @MinDBID = MIN(ID),
        @MaxDBID = MAX(ID)
FROM    #Database

-- Begin loop
WHILE @MinDBID <= @MaxDBID
    BEGIN
            -- Get DatabaseName
        SELECT  @DatabaseName = DatabaseName
        FROM    #Database
        WHERE   ID = @MinDBID
           
            -- Empty table ready for next database
        TRUNCATE TABLE #DBOwner
       
            -- Get all principals who are members of the db_owner fixed database role   
        IF EXISTS ( SELECT  u.name AS Principal
                    FROM    sys.database_role_members drm
                            INNER JOIN sys.database_principals dp ON dp.principal_id = drm.role_principal_id
                            INNER JOIN sysusers u ON u.uid = drm.member_principal_id
                    WHERE   dp.name = 'db_owner'
                            AND dp.name <> 'dbo'
                            AND u.isntuser = 0 )
            BEGIN
                INSERT  INTO #DBOwner ( PrincipalName )
                        SELECT  u.name AS Principal
                        FROM    sys.database_role_members drm
                                INNER JOIN sys.database_principals dp ON dp.principal_id = drm.role_principal_id
                                INNER JOIN sysusers u ON u.uid = drm.member_principal_id
                        WHERE   dp.name = 'db_owner'
                                AND dp.name <> 'dbo'
                                AND u.isntuser = 0
            END

            -- Set Variables for loop
        SELECT  @MinPrincipalID = MIN(ID),
                @MaxPrincipalID = MAX(ID)
        FROM    #Principal

            -- Begin loop
        WHILE @MinPrincipalID <= @MaxPrincipalID
            BEGIN
                        -- Get DatabaseName
                SELECT  @PrincipalName = PrincipalName
                FROM    #Principal
                WHERE   ID = @MinPrincipalID
               
                -- Build up SQL string
                SET @SQL = 'USE ' + @DatabaseName + ';' + 'EXEC sp_addrolemember N''db_owner'', N''' + @PrincipalName + ''''
               
                -- Grant membership in db_owner fixed database role
                EXEC (@SQL)  
                       
                        -- Get next Principal ID
                SET @MinPrincipalID = @MinPrincipalID + 1
            END
       
        -- Get next Database ID
            SET @MinDBID = @MinDBID + 1
           
    END

Enjoy!

Chris

A Script A Day - Day 11 - User Permissions By Database

Today's script will return you permissions granted to a user for every online database.  The script uses EXECUTE AS so you will need permission to impersonate the user and  also uses the fn_my_permissions function so is limited by its functionality.  I have used this script to hunt down what I think are security problems caused by permissions being granted to an individual rather than a group.

/*
      -----------------------------------------------------------------
      User Permissions By Database
      -----------------------------------------------------------------
     
      For more SQL resources, check out SQLServer365.blogspot.co.uk

      -----------------------------------------------------------------

      You may alter this code for your own purposes.
      You may republish altered code as long as you give due credit.
      You must obtain prior permission before blogging this code.
 
      THIS CODE AND INFORMATION ARE PROVIDED "AS IS"
     
      -----------------------------------------------------------------
*/
-- Declare variables
DECLARE
      @intMinLoop INT
      ,@intMaxLoop INT
      ,@strSQL VARCHAR(1000)
      ,@strDatabasename VARCHAR(100)
      ,@strUser VARCHAR(1000)

-- Create table variable
DECLARE @tmpDBtable TABLE
      (
      AutoID INT IDENTITY (1,1)
      ,Databasename VARCHAR(500)
      )

-- SET the User
SET @strUser = 'domain\user' --or for a sql user SET @strUser = 'user'

-- INSERT the database names
INSERT INTO @tmpDBTable
SELECT NAME FROM master.dbo.sysdatabases
WHERE   DATABASEPROPERTYEX(name, 'Status') = 'ONLINE'

-- Setup loop control
SELECT
      @intMinLoop = MIN(autoID)
      ,@intMaxLoop = MAX(autoID)
FROM
      @tmpDBTable

-- Get permissions
WHILE @intMinLoop <= @intMaxLoop
BEGIN
      SELECT @strDatabasename = Databasename FROM @tmpDBTable WHERE @intMinLoop = AutoID
      SELECT @strSQL =
            'USE ['+@strDatabasename+'];
            EXECUTE AS USER = '''+@strUser+''';
            SELECT
            '''+@strDatabasename+''' as DatabaseName
            ,*
            FROM fn_my_permissions(NULL,''Database'');
            REVERT;'
      BEGIN TRY  
            EXEC (@strSQL)
      END TRY
      BEGIN CATCH
            SELECT @@ERROR, ERROR_MESSAGE()
      END CATCH
     
      SET @intMinLoop = @intMinLoop+1
END  

Enjoy!

Chris

Sunday, 5 February 2012

A Script A Day - Day 5 - Database Owner Permissions

Today's script will list all principals with membership in the db_owner fixed database role.


/*
      -----------------------------------------------------------------
      Database Owner Permissions
      -----------------------------------------------------------------
     
      For more SQL resources, check out SQLServer365.blogspot.co.uk

      -----------------------------------------------------------------

      You may alter this code for your own purposes.
      You may republish altered code as long as you give due credit.
      You must obtain prior permission before blogging this code.
 
      THIS CODE AND INFORMATION ARE PROVIDED "AS IS"
     
      -----------------------------------------------------------------
*/
IF OBJECT_ID('tempdb..#tmp') IS NULL
    CREATE TABLE #tmp
        (
          Principal VARCHAR(250),
          DatabaseName VARCHAR(250)
        );
GO   
EXEC sp_Msforeachdb 'use [?];
INSERT #tmp SELECT  u.name AS Principal, db_name() AS DatabaseName
FROM sys.database_role_members drm
INNER JOIN sys.database_principals dp ON dp.principal_id = drm.role_principal_id
INNER JOIN sysusers u ON u.uid = drm.member_principal_id
WHERE dp.name = ''db_owner''
AND dp.name <> ''dbo'' AND u.isntuser = 0';
GO
SELECT  Principal,
        DatabaseName
FROM    #tmp
WHERE Principal != 'dbo';
GO
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
    DROP TABLE #tmp;
GO


Enjoy!


Chris