Banco de Dados

15 mai, 2019

SQL Server – Permissões para utilizar OLE Automation

Publicidade

Fala, pessoal!

Neste artigo bem simples e rápido, quero compartilhar com vocês quais as permissões para utilizar OLE Automation, um recurso do SQL Server que permite utilizar DLLs e APIs do Windows através de chamadas de Stored Procedures para realizar diversas tarefas dentro do banco de dados, como operações com arquivos, utilizar expressões regulares (RegExp), e até mesmo realizar requisições Web.

Introdução

Como eu já havia comentado no artigo “Introdução ao SQL CLR (Common Language Runtime) no SQL Server“, o grande problema do OLE Automation é que, ao ser habilitado, qualquer usuário (com permissão) pode criar qualquer coisa, uma vez que os comandos não são gerenciados e são executados dentro do processo do SQL Server.

Em caso de falha de vazamento de memória (o que não é tão incomum), a instância pode ser parada, pois o processo do SQL Server é fechado automaticamente pelo sistema operacional.

Além disso, é difícil encontrar uma documentação precisa sobre OLE Automation e é bem complexo criar rotinas utilizando esse recurso.

Por esse motivo, recomendo a substituição de rotinas OLE Automation por packages do SSIS e, caso não seja possível, rotinas utilizando SQLCLR, conforme já descrevo as vantagens no artigo já citado.

Permissões para utilizar OLE Automation

Caso você realmente tenha alguma necessidade bem específica que exija o uso de OLE Automation (e você não quer utilizar o SQLCLR), você já deve ter lido na documentação da Microsoft e em vários outros portais brasileiros e americanos, que indicam que, para utilizar as procedures do OLE Automation (sp_OA*), você deve obrigatoriamente pertencer à server role sysadmin, correto?

E aí você tem que liberar permissão de sysadmin para o usuário poder criar os objetos ou acaba negando essa solicitação, né?

Versão em inglês:

Versão em português:

Todas as páginas da documentação dessas procedures sp_OA* possuem esse mesmo requisito de permissão (sysadmin).

Mas e se eu te falar que isso não é verdade e é muito fácil provar isso?

O primeiro passo para isso é habilitar o OLE Automation na instância:

sp_configure 'Advanced Options', 1
GO

RECONFIGURE
GO

sp_configure 'Ole Automation Procedures', 1
GO

RECONFIGURE
GO

Caso você não faça isso, irá se deparar com a seguinte mensagem de erro:

Msg 15281, Level 16, State 1, Procedure sp_OACreate, Line 1 [Batch Start Line 0] SQL Server blocked access to procedure ‘sys.sp_OACreate’ of component ‘Ole Automation Procedures’ because this component is turned off as part of the security configuration for this server.

A system administrator can enable the use of ‘Ole Automation Procedures’ by using sp_configure. For more information about enabling ‘Ole Automation Procedures’, search for ‘Ole Automation Procedures’ in SQL Server Books Online.

Agora vamos criar um novo usuário para testar se conseguimos utilizar o OLE Automation sem estar na server role sysadmin:

USE [master]
GO

CREATE LOGIN [teste_OA] WITH PASSWORD='123', CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF, DEFAULT_DATABASE=[master]
GO

CREATE USER [teste_OA] FOR LOGIN [teste_OA]
GO

E agora, conectado com o usuário teste_OA, vamos tentar tentar utilizar o OLE Automation com o código abaixo:

DECLARE @strArquivo VARCHAR(255) = 'C:\Senha muito importante.txt'

DECLARE
    @hr INT,
    @objFileSystem INT,
    @objFile INT,
    @ErrorObject INT,
    @ErrorMessage VARCHAR(255),
    @Path VARCHAR(255),--
    @ShortPath VARCHAR(255),
    @Type VARCHAR(100),
    @DateCreated DATETIME,
    @DateLastAccessed DATETIME,
    @DateLastModified DATETIME,
    @Attributes INT,
    @size INT

 
SET NOCOUNT ON
 
SELECT
    @hr = 0,
    @ErrorMessage = 'opening the file system object '
    
EXEC @hr = sp_OACreate
    'Scripting.FileSystemObject',
    @objFileSystem OUT
        
IF @hr = 0
    SELECT
        @ErrorMessage = 'accessing the file ''' + @strArquivo + '''',
        @ErrorObject = @objFileSystem
    
IF @hr = 0
    EXEC @hr = sp_OAMethod
        @objFileSystem,
        'GetFile',
        @objFile OUT,
        @strArquivo
            
IF @hr = 0
    SELECT
        @ErrorMessage = 'getting the attributes of ''' + @strArquivo + '''',
        @ErrorObject = @objFile
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'Path',
        @Path OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'ShortPath',
        @ShortPath OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'Type',
        @Type OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'DateCreated',
        @DateCreated OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'DateLastAccessed',
        @DateLastAccessed OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'DateLastModified',
        @DateLastModified OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'Attributes',
        @Attributes OUT
            
IF @hr = 0
    EXEC @hr = sp_OAGetProperty
        @objFile,
        'size',
        @size OUT
 
 
IF @hr <> 0
BEGIN
    DECLARE
        @Source VARCHAR(255),
        @Description VARCHAR(255),
        @Helpfile VARCHAR(255),
        @HelpID INT
   
    EXECUTE sp_OAGetErrorInfo
        @ErrorObject,
        @Source OUTPUT,
        @Description OUTPUT,
        @Helpfile OUTPUT,
        @HelpID OUTPUT
 
    SELECT
        @ErrorMessage = 'Error whilst ' + @ErrorMessage + ', ' + @Description
            
    RAISERROR (@ErrorMessage,16,1)
        
END
    

EXEC sp_OADestroy
    @objFileSystem
        
EXEC sp_OADestroy
    @objFile
        
SELECT
    [Path] = @Path,
    [ShortPath] = @ShortPath,
    [Type] = @Type,
    [DateCreated] = @DateCreated,
    [DateLastAccessed] = @DateLastAccessed,
    [DateLastModified] = @DateLastModified,
    [Attributes] = @Attributes,
    [Size] = @size

Ao tentar executar, recebemos a seguinte mensagem:

Msg 229, Level 14, State 5, Procedure sp_OACreate, Line 1 [Batch Start Line 0] The EXECUTE permission was denied on the object ‘sp_OACreate’, database ‘mssqlsystemresource’, schema ‘sys’.

Pois bem, para resolver esse problema de permissão é muito simples e não exige que o usuário esteja na role sysadmin:

USE [master]
GO

GRANT EXECUTE ON sys.sp_OACreate TO [teste_OA]
GRANT EXECUTE ON sys.sp_OADestroy TO [teste_OA]
GRANT EXECUTE ON sys.sp_OAGetErrorInfo TO [teste_OA]
GRANT EXECUTE ON sys.sp_OAGetProperty TO [teste_OA]
GRANT EXECUTE ON sys.sp_OAMethod TO [teste_OA]
GRANT EXECUTE ON sys.sp_OASetProperty TO [teste_OA]
GRANT EXECUTE ON sys.sp_OAStop TO [teste_OA]

E agora, tentando executar novamente o script acima:

Sucesso! Conseguimos executar o script OLE Automation normalmente, apenas com as permissões necessárias.

Espero que tenham gostado deste artigo.

Até a próxima!

PS: fiquem tranquilos, vou enviar uma solicitação de correção da documentação.

Documentação Corrigida – “Mãe, tô na Globo!”