2011-06-10 6 views

Respuesta

24

Puede obtener lo que necesita con un script como el siguiente:

declare @RoleName varchar(50) = 'RoleName' 

declare @Script varchar(max) = 'CREATE ROLE ' + @RoleName + char(13) 
select @script = @script + 'GRANT ' + prm.permission_name + ' ON ' + OBJECT_NAME(major_id) + ' TO ' + rol.name + char(13) COLLATE Latin1_General_CI_AS 
from sys.database_permissions prm 
    join sys.database_principals rol on 
     prm.grantee_principal_id = rol.principal_id 
where rol.name = @RoleName 

print @script 
+1

tenga cuidado si su rol tiene una gran cantidad de permisos. Descubrí que el estudio de gestión sql limitará la cantidad de texto que puede imprimir en la pantalla. Cuando ejecuté esta consulta en mi base de datos solo recogió 151 estados de cuenta cuando realmente tenía 349. Simplemente tuve que eliminar el '@script = @script' + y dejar que los resultados se devuelvan como una cuadrícula. – Frank

+0

@Frank puede acceder a las opciones en Management Studio y cambiar la salida de texto predeterminada (resultados) a 8000 desde 256 – datagod

3

EN SSMS, haga clic derecho en el nodo de usuario/inicio de sesión/función y seleccione 'Script As' script este usuario/inicio de sesión/función en particular. Sin embargo, no puede establecer secuencias de comandos para la función de roles de esta manera.

Visual Studio con la opción 'Desarrollo de base de datos' y Red Gate SQL Compare pueden generar el script de cambio entre bases de datos, esto incluye usuarios, roles y membresía de roles.

Generado por los miembros de funciones VS se parece a esto:

EXECUTE sp_addrolemember @rolename = N'db_datareader', @membername = N'DOMAIN\User'; 

Si usted no tiene VS, puede escribir manualmente los, o crear una secuencia de comandos SQL para generar ellos.

Estoy seguro de que también debería haber una herramienta gratuita para hacer algo como esto, pero como no lo necesito ya que tengo Visual Studio, nunca lo busqué.

Editar: Me acabo de dar cuenta de que estoy respondiendo una pregunta incorrecta, usted está preguntando sobre el permiso de función y le estoy hablando acerca de la membresía de la función. Perdón por esto. Dejaré esta respuesta aquí en caso de que pueda ser útil para otra persona. La respuesta de Alex Aza se ve bien.

+1

cuando haga clic derecho sobre el papel y seleccione 'script como'' que genera sólo una línea 'CREATE ROLE [NombreRol ] AUTORIZACIÓN [dbo] ' Necesito obtener permisos de roles también –

+0

@Foster Geng: sí, lo sé. Yo personalmente uso Visual Studio para este tipo de personal. Genera los gustos de 'EXECUTE sp_addrolemember @rolename = N'db_datareader ', @membername = N'DOMAIN \ User';' –

0

Es un dolor, pero todo lo que estás buscando es en un par de puntos de vista del sistema: sys.database_permissions, sys.database_principals, y sys.database_role_members. La razón por la cual no es un tratamiento es porque el major_id y el minor_id en sys.database_permissions tienen diferentes significados basados ​​en la columna de la clase. Pero si sus permisos son relativamente simples, entonces esto podría no ser tan malo. Dale un vistazo y mira lo que puedes conseguir.

-1

Agregué una función de secuencia de comandos adicional al código anterior. Los guiones de fuera seleccione el papel y permisos por lo que sólo necesitan para ejecutar el resultado:

-- Update the RoleName with the name of your role 
DECLARE @RoleName VARCHAR(75) = 'RoleName' 

DECLARE @RoleTable TABLE ([GrantedBy] VARCHAR (50) NOT NULL, [Permission] VARCHAR (50) NOT NULL, [State] VARCHAR (50) NOT NULL) 
DECLARE @RoleScript VARCHAR(75) 

INSERT INTO @RoleTable SELECT p2.[name], dbp.[permission_name], dbp.[state_desc] 
FROM [sys].[database_permissions] dbp LEFT JOIN [sys].[objects] so 
    ON dbp.[major_id] = so.[object_id] LEFT JOIN [sys].[database_principals] p 
    ON dbp.[grantee_principal_id] = p.[principal_id] LEFT JOIN [sys].[database_principals] p2 
    ON dbp.[grantor_principal_id] = p2.[principal_id] 
WHERE p.[name] = @RoleName 

SELECT 'USE [' + DB_NAME() + '] CREATE ROLE [' + @RoleName + ']' AS 'Create Role' 
SELECT 'USE [' + DB_NAME() + '] GRANT ' + [Permission] + ' ON SCHEMA::[' + [GrantedBy] + '] TO [' + @RoleName + ']' AS 'Add Permissions' 
FROM @RoleTable 
4

Este script genera comandos GRANT para sus papeles. Me gusta, que admite permisos leven columna. Tiene que ser adaptado a su necesidad (es decir, mejorar para bases de datos más complejas, concatenar declaraciones y ejecutar, incluir crear declaración para su función). Pero sólo para darle una idea:

SELECT 'GRANT ' + database_permissions.permission_name + ' ON ' + 
    CASE database_permissions.class_desc 
     WHEN 'SCHEMA' THEN schema_name(major_id) 
     WHEN 'OBJECT_OR_COLUMN' THEN 
      CASE WHEN minor_id = 0 THEN object_name(major_id) COLLATE Latin1_General_CI_AS_KS_WS 
      ELSE (SELECT object_name(object_id) + ' ('+ name + ')' 
        FROM sys.columns 
        WHERE object_id = database_permissions.major_id 
        AND column_id = database_permissions.minor_id) end 
     ELSE 'other' 
    END + 
    ' TO ' + database_principals.name COLLATE Latin1_General_CI_AS_KS_WS 
FROM sys.database_permissions 
JOIN sys.database_principals 
ON database_permissions.grantee_principal_id = database_principals.principal_id 
LEFT JOIN sys.objects --left because it is possible that it is a schema 
ON objects.object_id = database_permissions.major_id 
WHERE database_permissions.major_id > 0 
AND permission_name in ('SELECT','INSERT','UPDATE','DELETE') 
+0

¡un pequeño y agradable script! – mcfea

+0

cualquier forma de desentrañar el esquema para que pueda obtener "GRANT SELECT ON test.TABLE TO fooUser"? – mcfea

+0

Vi un esquema en mi respuesta. – mcfea

7

amplié sobre la respuesta de Mario Eis:

SELECT 'GRANT ' + database_permissions.permission_name + ' ON ' + CASE database_permissions.class_desc 
     WHEN 'SCHEMA' 
      THEN '[' + schema_name(major_id) + ']' 
     WHEN 'OBJECT_OR_COLUMN' 
      THEN CASE 
        WHEN minor_id = 0 
         THEN'['+OBJECT_SCHEMA_NAME(major_id) + '].' + '[' + object_name(major_id) + ']' COLLATE Latin1_General_CI_AS_KS_WS 
        ELSE (
          SELECT object_name(object_id) + ' (' + NAME + ')' 
          FROM sys.columns 
          WHERE object_id = database_permissions.major_id 
           AND column_id = database_permissions.minor_id 
          ) 
        END 
     ELSE 'other' 
     END + ' TO [' + database_principals.NAME + ']' COLLATE Latin1_General_CI_AS_KS_WS 
FROM sys.database_permissions 
JOIN sys.database_principals ON database_permissions.grantee_principal_id = database_principals.principal_id 
LEFT JOIN sys.objects --left because it is possible that it is a schema 
    ON objects.object_id = database_permissions.major_id 
WHERE database_permissions.major_id > 0 
    AND permission_name IN (
     'SELECT' 
     ,'INSERT' 
     ,'UPDATE' 
     ,'DELETE' 
     ,'EXECUTE' 
     ) 
+3

Gracias, utilicé esta opción, y como solo necesitaba esto para un cierto rol, lo vi al final de la cláusula WHERE de su script: AND database_principals.NAME = 'RoleNameHere' –

+2

Si agrega "AS PermStatement" hasta el final de la cláusula SELECT y "ORDER BY PermStatement" después de la cláusula WHERE los resultados se ordenarán alfabéticamente. Esto no afecta la funcionalidad en absoluto, pero ayudará si está tratando de comparar permisos para un rol en dos versiones diferentes de la misma base de datos. –

+0

No olvide crear el rol primero si desea modificar uno específico que aún no existe: CREATE ROLE [rolename] –

3

He hecho un script bastante completa que no sólo guiones de fuera todos los permisos, sino también toda la membresía y poner glaseado en el pastel formatea la salida para copiar/pegar fácilmente en una nueva ventana de consulta. He publicado la secuencia de comandos para my blog y actualizarlo de vez en cuando, pero a continuación es la versión actual que se debe cubrir la mayoría de las bases:

/******************************************************************** 
*                 * 
* Author: John Eisbrener           * 
* Script Purpose: Script out Database Role Definition    * 
* Notes: Please report any bugs to http://www.dbaeyes.com/   * 
*                 * 
********************************************************************/ 
DECLARE @roleName VARCHAR(255) 
SET @roleName = 'DatabaseRoleName' 

-- Script out the Role 
DECLARE @roleDesc VARCHAR(MAX), @crlf VARCHAR(2) 
SET @crlf = CHAR(13) + CHAR(10) 
SET @roleDesc = 'CREATE ROLE [' + @roleName + ']' + @crlf + 'GO' + @crlf + @crlf 

SELECT @roleDesc = @roleDesc + 
     CASE dp.state 
      WHEN 'D' THEN 'DENY ' 
      WHEN 'G' THEN 'GRANT ' 
      WHEN 'R' THEN 'REVOKE ' 
      WHEN 'W' THEN 'GRANT ' 
     END + 
     dp.permission_name + ' ' + 
     CASE dp.class 
      WHEN 0 THEN '' 
      WHEN 1 THEN --table or column subset on the table 
       CASE WHEN dp.major_id < 0 THEN 
        + 'ON [sys].[' + OBJECT_NAME(dp.major_id) + '] ' 
       ELSE 
        + 'ON [' + 
        (SELECT SCHEMA_NAME(schema_id) + '].[' + name FROM sys.objects WHERE object_id = dp.major_id) 
         + -- optionally concatenate column names 
        CASE WHEN MAX(dp.minor_id) > 0 
         THEN '] ([' + REPLACE(
             (SELECT name + '], [' 
             FROM sys.columns 
             WHERE object_id = dp.major_id 
              AND column_id IN (SELECT minor_id 
                   FROM sys.database_permissions 
                   WHERE major_id = dp.major_id 
                   AND USER_NAME(grantee_principal_id) IN (@roleName) 
                  ) 
             FOR XML PATH('') 
             ) --replace final square bracket pair 
            + '])', ', []', '') 
         ELSE ']' 
        END + ' ' 
       END 
      WHEN 3 THEN 'ON SCHEMA::[' + SCHEMA_NAME(dp.major_id) + '] ' 
      WHEN 4 THEN 'ON ' + (SELECT RIGHT(type_desc, 4) + '::[' + name FROM sys.database_principals WHERE principal_id = dp.major_id) + '] ' 
      WHEN 5 THEN 'ON ASSEMBLY::[' + (SELECT name FROM sys.assemblies WHERE assembly_id = dp.major_id) + '] ' 
      WHEN 6 THEN 'ON TYPE::[' + (SELECT name FROM sys.types WHERE user_type_id = dp.major_id) + '] ' 
      WHEN 10 THEN 'ON XML SCHEMA COLLECTION::[' + (SELECT SCHEMA_NAME(schema_id) + '.' + name FROM sys.xml_schema_collections WHERE xml_collection_id = dp.major_id) + '] ' 
      WHEN 15 THEN 'ON MESSAGE TYPE::[' + (SELECT name FROM sys.service_message_types WHERE message_type_id = dp.major_id) + '] ' 
      WHEN 16 THEN 'ON CONTRACT::[' + (SELECT name FROM sys.service_contracts WHERE service_contract_id = dp.major_id) + '] ' 
      WHEN 17 THEN 'ON SERVICE::[' + (SELECT name FROM sys.services WHERE service_id = dp.major_id) + '] ' 
      WHEN 18 THEN 'ON REMOTE SERVICE BINDING::[' + (SELECT name FROM sys.remote_service_bindings WHERE remote_service_binding_id = dp.major_id) + '] ' 
      WHEN 19 THEN 'ON ROUTE::[' + (SELECT name FROM sys.routes WHERE route_id = dp.major_id) + '] ' 
      WHEN 23 THEN 'ON FULLTEXT CATALOG::[' + (SELECT name FROM sys.fulltext_catalogs WHERE fulltext_catalog_id = dp.major_id) + '] ' 
      WHEN 24 THEN 'ON SYMMETRIC KEY::[' + (SELECT name FROM sys.symmetric_keys WHERE symmetric_key_id = dp.major_id) + '] ' 
      WHEN 25 THEN 'ON CERTIFICATE::[' + (SELECT name FROM sys.certificates WHERE certificate_id = dp.major_id) + '] ' 
      WHEN 26 THEN 'ON ASYMMETRIC KEY::[' + (SELECT name FROM sys.asymmetric_keys WHERE asymmetric_key_id = dp.major_id) + '] ' 
     END COLLATE SQL_Latin1_General_CP1_CI_AS 
     + 'TO [' + @roleName + ']' + 
     CASE dp.state WHEN 'W' THEN ' WITH GRANT OPTION' ELSE '' END + @crlf 
FROM sys.database_permissions dp 
WHERE USER_NAME(dp.grantee_principal_id) IN (@roleName) 
GROUP BY dp.state, dp.major_id, dp.permission_name, dp.class 

SELECT @roleDesc = @roleDesc + 'GO' + @crlf + @crlf 

-- Display users within Role. Code stubbed by Joe Spivey 
SELECT @roleDesc = @roleDesc + 'EXECUTE sp_AddRoleMember ''' + roles.name + ''', ''' + users.name + '''' + @crlf 
FROM sys.database_principals users 
     INNER JOIN sys.database_role_members link 
      ON link.member_principal_id = users.principal_id 
     INNER JOIN sys.database_principals roles 
      ON roles.principal_id = link.role_principal_id 
WHERE roles.name = @roleName 

-- PRINT out in blocks of up to 8000 based on last \r\n 
DECLARE @printCur INT 
SET @printCur = 8000 

WHILE LEN(@roleDesc) > 8000 
BEGIN 
    -- Reverse first 8000 characters and look for first lf cr (reversed crlf) as delimiter 
    SET @printCur = 8000 - CHARINDEX(CHAR(10) + CHAR(13), REVERSE(SUBSTRING(@roleDesc, 0, 8000))) 

    PRINT LEFT(@roleDesc, @printCur) 
    SELECT @roleDesc = RIGHT(@roleDesc, LEN(@roleDesc) - @printCur) 
END 

PRINT @RoleDesc + 'GO' 

Es de destacar que es posible que encuentre una situación en la que el sistema sp_addrolemember sp agrega usuario (s) a la base de datos que no estaba allí previamente.En este caso, aunque se agreguen los usuarios, NO se les otorga el permiso CONEXIÓN, y cualquier intento de conexión realizado por dicho usuario o grupo generará un error de inicio de sesión de usuario. Para corregir este problema, es necesario ejecutar el siguiente por cada nuevo usuario/grupo dentro de la db:

USE [DatabaseName] 
GO 
GRANT CONNECT TO [Login/GroupName] 
GO 
Cuestiones relacionadas