Script de uma função de aplicativo com uma senha com hash

8

Preciso criar um script para uma função de aplicativo com uma senha com hash, para copiá-la de um banco de dados para outro.

Considere o seguinte código de exemplo, que usa uma Função de Aplicativo para fornecer acesso elevado a um usuário não confiável:

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

Depois de criar a configuração de teste no tempdb, podemos fazer login como [LimitedLogin]usuário e executar o seguinte:

-- login as [LimitedLogin]

USE tempdb;

SELECT *
FROM dbo.Numbers;

O seguinte erro é retornado, conforme o esperado:

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

No entanto, uma vez executada a sp_setapprolesenha apropriada, podemos ver os resultados desejados da dbo.Numberstabela:

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;

Eu gostaria de poder automatizar a criação da Função de Aplicativo criando um script de um banco de dados de origem para ser aplicado a um banco de dados de destino. Eu posso facilmente executar a maioria disso:

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';

No entanto, eu realmente gostaria de poder ter a senha com hash no script, algo como:

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

Isso é possível? Presumivelmente, a versão em hash da senha da função de aplicativo está armazenada em algum lugar do banco de dados.

Usando a funcionalidade "script para ->" do SQL Server Management Studio, a Função do Aplicativo é escrita com uma nova senha, 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, isso não é útil no meu caso, embora ele forneça um método interessante de gerar senhas aleatórias.


Com base nas respostas até agora, criei uma sugestão do Connect para adicionar suporte para isso no produto:

Max Vernon
fonte

Respostas:

6

Você pode conectar-se usando o DAC ( Dedicated Administrator Connection ) e puxar a passwordcoluna de sys.sysowners. Primeiro, conecte-se usando:

ADMIN:Server\Instance

Então:

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

Essa exibição é visível apenas ao usar o DAC, e a coluna não é exposta na exibição pai que é visível ( sys.database_principals). Por favor, tenha cuidado com o CAD, é claro.

Dito isto, isso não ajuda. CREATE APPLICATION ROLEé muito diferente CREATE LOGIN, pois você não pode fornecer uma senha com hash , apenas texto simples. E nem pense em engenharia reversa do valor de hash, porque as versões modernas do SQL Server usam métodos elaborados para criptografar uma senha. De fato, se você tentar isso sozinho, verá que um hash diferente é criado toda vez, mesmo na mesma declaração:

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

Resultados (na minha máquina, desta vez), observando que os seus variarão:

0x0200185968C35F22AF70...   0x0200D6C77A1D84A8467F...

Então, eu recomendaria:

  1. Armazenando a senha do aplicativo no controle de origem em algum lugar ou onde quer que você armazene outras senhas do sistema atualmente, e usando isso para gerar o script para implantar as funções de aplicativo em outro servidor (ou na origem controlar o CREATE APPLICATION ROLEscript inteiro ); ou,
  2. Usando funções regulares em vez de funções de aplicativo.
Aaron Bertrand
fonte
1

Não há nada na sintaxe que torne isso possível

CREATE APPLICATION ROLE(Transact-SQL) - Manuais Online

Você pode contornar isso ao criar o approle em um banco de dados de modelos e fazer com que o script restaure isso. Uma implementação (Dynamics NAV) cria uma aprovação no código e armazena a senha da função de aplicativo criptografada em uma tabela no banco de dados, fazendo com que o cliente descriptografe a senha da função.

Spörri
fonte