Scripting un rol de aplicación con una contraseña hash

8

Necesito escribir una función de aplicación con una contraseña hash, para poder copiarla de una base de datos a otra.

Considere el siguiente código de ejemplo, que usa un Rol de aplicación para proporcionar acceso elevado a un usuario no confiable:

USE tempdb;

CREATE LOGIN LimitedLogin
WITH PASSWORD = 'Password1'
    , CHECK_POLICY = OFF
    , CHECK_EXPIRATION = OFF;

CREATE USER LimitedLogin
FOR LOGIN LimitedLogin
WITH DEFAULT_SCHEMA = dbo;

CREATE APPLICATION ROLE MyAppRole
WITH PASSWORD = 'Password2'
    , DEFAULT_SCHEMA = dbo;

EXEC sp_addrolemember @rolename = 'db_datareader'
    , @membername = 'MyAppRole';

CREATE TABLE dbo.Numbers
(
    [Number] int CONSTRAINT PK_Numbers 
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1) NOT NULL
);

INSERT INTO dbo.Numbers
VALUES (1)
    , (2);

GO

Una vez que creamos la configuración de prueba en tempdb, podemos iniciar sesión como [LimitedLogin]usuario y ejecutar lo siguiente:

-- login as [LimitedLogin]

USE tempdb;

SELECT *
FROM dbo.Numbers;

Se devuelve el siguiente error, como se esperaba:

Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'Numbers'
    , database 'Test', schema 'dbo'.

Sin embargo, una vez que ejecutamos sp_setapprolecon la contraseña apropiada, podemos ver los resultados deseados de la dbo.Numberstabla:

DECLARE @cookie VARBINARY(8000);
EXEC sp_setapprole @rolename = 'MyAppRole'
    , @password = 'Password2'
    , @fCreateCookie = 1
    , @cookie = @cookie OUT;
SELECT @cookie;

SELECT TOP(10) *
FROM dbo.Numbers;

EXEC sp_unsetapprole @cookie = @cookie;

Me gustaría poder automatizar la creación del rol de la aplicación mediante una secuencia de comandos desde una base de datos de origen para aplicarla a una base de datos de destino. Puedo realizar la mayoría de eso fácilmente al:

SELECT 'CREATE APPLICATION ROLE ' + QUOTENAME(dp.name) + '
WITH PASSWORD = ''xxxx''
    , DEFAULT_SCHEMA = ' + QUOTENAME(dp.default_schema_name) + ';'
FROM sys.database_principals dp
WHERE dp.type_desc = 'APPLICATION_ROLE';

Sin embargo, realmente me gustaría poder tener la contraseña hash en el script, algo así como:

CREATE APPLICATION ROLE [MyAppRole]
WITH PASSWORD = 0x12345678 HASHED
    , DEFAULT_SCHEMA = [dbo];

es posible? Presumiblemente, la versión hash de la contraseña del rol de la aplicación se almacena en algún lugar de la base de datos.

Usando la funcionalidad "script to ->" de SQL Server Management Studio, el rol de la aplicación se escribe con una nueva contraseña, como:

/****** Object:  ApplicationRole [MyAppRole]    Script Date: 9/22/2015 10:18:12 AM ******/
/* To avoid disclosure of passwords, the password is generated in script. */
declare @idx as int
declare @randomPwd as nvarchar(64)
declare @rnd as float
select @idx = 0
select @randomPwd = N''
select @rnd = rand((@@CPU_BUSY % 100) + ((@@IDLE % 100) * 100) + 
       (DATEPART(ss, GETDATE()) * 10000) + ((cast(DATEPART(ms, GETDATE()) as int) % 100) * 1000000))
while @idx < 64
begin
   select @randomPwd = @randomPwd + char((cast((@rnd * 83) as int) + 43))
   select @idx = @idx + 1
select @rnd = rand()
end
declare @statement nvarchar(4000)
select @statement = N'CREATE APPLICATION ROLE [MyAppRole] WITH DEFAULT_SCHEMA = [dbo], ' + N'PASSWORD = N' + QUOTENAME(@randomPwd,'''')
EXEC dbo.sp_executesql @statement
GO

Claramente, eso no es útil en mi caso, aunque proporciona un método interesante para generar contraseñas aleatorias.


Basado en las respuestas hasta ahora, he creado una sugerencia de Connect para agregar soporte para esto al producto:

Max Vernon
fuente

Respuestas:

6

Puede conectarse utilizando el DAC ( Conexión de administrador dedicada ) y extraer la passwordcolumna de sys.sysowners. Primero, conéctese usando:

ADMIN:Server\Instance

Entonces:

SELECT password_hash = [password]
  FROM sys.sysowners
  WHERE name = N'MyAppRole';

Esta vista solo es visible cuando se usa el DAC, y la columna no está expuesta en la vista principal que es visible ( sys.database_principals). Tenga cuidado con el DAC, por supuesto.

Dicho todo esto, esto no te ayuda. CREATE APPLICATION ROLEes muy diferente de CREATE LOGIN, ya que no puede proporcionar una contraseña hash , solo texto sin formato. Y ni siquiera piense en la ingeniería inversa del valor hash, porque las versiones modernas de SQL Server utilizan métodos elaborados para cifrar una contraseña. De hecho, si prueba esto usted mismo, verá que se crea un hash diferente cada vez, incluso en la misma declaración:

SELECT PWDENCRYPT(N'foo'), PWDENCRYPT(N'foo');

Resultados (en mi máquina, esta vez), señalando que los suyos variarán:

0x0200185968C35F22AF70...   0x0200D6C77A1D84A8467F...

Entonces, recomendaría:

  1. Almacenar la contraseña de la aplicación en el control de origen en algún lugar, o en cualquier lugar donde almacene otras contraseñas del sistema actualmente, y usarla para generar el script para implementar las funciones de la aplicación en otro servidor (o controlar el CREATE APPLICATION ROLEscript completo en el origen ); o,
  2. Usar roles regulares en lugar de roles de aplicación.
Aaron Bertrand
fuente
1

No hay nada en la sintaxis que lo haga posible.

CREATE APPLICATION ROLE(Transact-SQL) - Libros en línea

Puede solucionar esto creando la aprobación en una base de datos de plantilla y haciendo que el script lo restaure. Una implementación (Dynamics NAV) crea una aprobación en el código y almacena la contraseña de rol de aplicación cifrada en una tabla en la base de datos, haciendo que el cliente descifre la contraseña de rol.

Spörri
fuente