SQL Server: conceder acesso de seleção a um usuário em uma exibição e não em suas tabelas

11

Eu tenho uma instância do SQL Server 2012 com alguns bancos de dados. Em um deles, criei uma visualização que seleciona tabelas em mais de um banco de dados.

Desejo que um usuário possa selecionar essa exibição, mas não deve selecionar suas tabelas. A visualização foi criada exatamente porque o usuário não pode selecionar as tabelas.

Eu li /programming/368414/grant-select-on-a-view-not-base-table e http://msdn.microsoft.com/en-us/library/ms188676. aspx e ainda não está funcionando.

Se eu fizer um GRANT SELECT TABLE TO USERem todas as tabelas, o usuário poderá selecionar a visualização. Mas se eu revogar alguma tabela, ela falhará.

Esse deve ser um procedimento fácil, mas estou tendo problemas para fazê-lo funcionar. Já vi isso acontecer antes (o proprietário de uma instância me deu acesso a uma exibição e não o fez a suas tabelas), mas não consigo fazê-lo ou encontrar alguém que saiba como.

Alguém poderia me fornecer um tutorial sobre como fazê-lo, ou um exemplo de código?


Quando o usuário SELECTsa visualização, recebo a mensagem:

A permissão SELECT foi negada no objeto <TABLE>, banco de dados <DB>, esquema dbo.

Se eu conceder a seleção a essa tabela, a mensagem de erro altera o nome da tabela para outra tabela que a exibição lê.

Hikari
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White 9

Respostas:

21

Se você deseja que os usuários selecionem a partir da visualização, por que você está concedendo à tabela? Por "revogar", você quer dizer revogar / negar explicitamente? Negar substituirá a concessão, portanto, o problema é seu ... você deve conseguir isso adicionando concessão à exibição e não fazendo nada nas tabelas.

Aqui está um exemplo rápido em SELECTque não foi concedido explicitamente na tabela, mas foi exibido. O usuário pode selecionar na visualização, mas não na tabela.

CREATE USER foo WITHOUT LOGIN;
GO
CREATE TABLE dbo.a(id INT);
CREATE TABLE dbo.b(id INT);
GO
CREATE VIEW dbo.v 
AS 
  SELECT a.id FROM a INNER JOIN b ON a.id = b.id;
GO
GRANT SELECT ON dbo.v TO foo;
GO
EXECUTE AS USER = N'foo';
GO
-- works:
SELECT id FROM dbo.v;
GO
-- Msg 229, SELECT denied:
SELECT id FROM dbo.a;
GO
REVERT;

Observe que isso pressupõe fooque não foram concedidos privilégios elevados por meio de permissões explícitas no esquema ou banco de dados, ou por meio de associação de função ou grupo.

Como você está usando tabelas em vários bancos de dados (desculpe, eu perdi o final da primeira frase inicialmente), você também pode precisar de concessões explícitas nas tabelas no banco de dados em que a exibição não existe. Para evitar conceder seleção às tabelas, você pode criar uma visualização em cada banco de dados e depois ingressar nas visualizações.

Crie dois bancos de dados e um logon:

CREATE DATABASE d1;
GO
CREATE DATABASE d2;
GO
USE [master];
GO
CREATE LOGIN blat WITH PASSWORD = 'x', CHECK_POLICY = OFF;
GO

No banco de dados d1, crie um usuário e crie uma tabela e uma visualização simples nessa tabela. Conceda a seleção ao usuário apenas na visualização:

USE d1;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t1(id INT);
GO
CREATE VIEW dbo.v1
AS
  SELECT id FROM dbo.t1;
GO
GRANT SELECT ON dbo.v1 TO blat;
GO

Agora, no segundo banco de dados, crie o usuário e crie outra tabela e uma exibição que une essa tabela à exibição d1. Conceda a seleção apenas para a visualização.

USE d2;
GO
CREATE USER blat FROM LOGIN blat;
GO
CREATE TABLE dbo.t2(id INT);
GO
CREATE VIEW dbo.v2
AS
  SELECT v1.id FROM dbo.t2 
    INNER JOIN d1.dbo.v1 AS v1
    ON t2.id = v1.id;
GO
GRANT SELECT ON dbo.v2 TO blat;
GO

Agora inicie uma nova janela de consulta e altere as credenciais para o logon blat( EXECUTE ASnão funciona aqui). Em seguida, execute o seguinte no contexto de qualquer banco de dados e deve funcionar bem:

SELECT id FROM d1.dbo.v2;

Ambos devem gerar erros de mensagem 229:

SELECT id FROM d1.dbo.t1;
GO
SELECT id FROM d2.dbo.t2;

Resultados:

Msg 229, Nível 14, Estado 5, Linha 1
A permissão SELECT foi negada no objeto 't1', banco de dados 'd1', esquema 'dbo'.
Msg 229, Nível 14, Estado 5, Linha 3
A permissão SELECT foi negada no objeto 't2', banco de dados 'd2', esquema 'dbo'.

Aaron Bertrand
fonte
1

Resposta do wiki da comunidade adicionada originalmente à pergunta por seu autor:

Isto é o que eu fiz:

  1. Criou uma visualização no DB A, juntando todas as tabelas nela.
  2. SELECTAcesso concedido ao usuário nessa visualização e NÃO a nenhuma de suas tabelas. O usuário conseguiu consultar a visualização e não as tabelas.
  3. Criou uma visualização no DB B, unindo tabelas neste DB juntamente com a visualização no DB A.
  4. SELECTAcesso concedido ao usuário nesta segunda exibição e também NÃO a nenhuma tabela. O usuário conseguiu consultar esta visualização final e ver os dados.

Eu acho estranho uma visão ser capaz de consultar tabelas em seu banco de dados que o usuário não tem acesso direto, mas é incapaz de fazê-lo em tabelas de outro banco de dados. Pelo menos funcionou.

user126897
fonte