Definindo permissões de usuário para diferentes esquemas do SQL Server

16

Preciso limitar o acesso a um usuário específico, mas ele ainda precisa ver os dados nas tabelas pertencentes ao dbo.

Estou tentando fazer o seguinte:

  1. esquema dbo funciona como normalmente, tem acesso a tudo
  2. schema1 schema tem acesso apenas aos objetos schema1
  3. se uma exibição de esquema1 ou procedimento armazenado acessar dados em tabelas pertencentes ao dbo, a cadeia de permissões adequadamente
  4. o usuário1 tem acesso ao esquema1 e nada mais; exceto no caso de # 3

Aqui está o que eu tentei:

  1. Crie um usuário user1 mapeado para um logon de teste com uma senha aleatória
  2. Criou algumas tabelas no esquema dbo com alguns dados de teste
  3. Criou um esquema schema1
  4. Criou um schema1.get_profiles que seleciona uma visualização chamada schema1.profiles que acessa dados em dbo.people, dbo.taglinks e dbo.tags

No entanto, usando a seguinte instrução enquanto estiver logado como usuário1:

EXEC get_profiles 1

resulta em:

The SELECT permission was denied on the object 'tags', database 'schema_test', schema 'dbo'.

Eu tentei WITH EXECUTE AS OWNERe não consigo começar a entender como o "encadeamento de propriedade" deve funcionar.

Eu também tentei

GRANT EXECUTE ON SCHEMA::schema1 TO user1
GRANT INSERT ON SCHEMA::schema1 TO user1
GRANT SELECT ON SCHEMA::schema1 TO user1
GRANT UPDATE ON SCHEMA::schema1 TO user1
GRANT VIEW DEFINITION ON SCHEMA::schema1 TO user1

mas recebo o seguinte erro (apesar de ser um usuário com acesso no nível dbo):

Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.

O que eu preciso é do usuário1 para poder acessar os dados através dos procedimentos armazenados que eu forneço, e nada mais.

Além disso, pretende-se, eventualmente, viver em um banco de dados existente do SQL Azure, mas estou testando primeiro um banco de dados fictício local.

Julia McGuigan
fonte
Consulte a minha resposta: Como ocultar o esquema do usuário Deixe-me saber se você precisa de mais esclarecimentos.
Kin Shah
1
Isso parece ter ficado mais claro para mim. Eu acho que o problema foi que eu tinha o proprietário do Schema1 definido como User1, em vez de dbo. Eu configurei o Schema1 como pertencente ao Usuário1, adaptei e segui a pergunta e consegui fazer algo funcionar. Você pode propor uma resposta para a pergunta, se quiser. Obrigado!
Julia McGuigan
Fico feliz que isso te ajudou.
Kin Shah

Respostas:

17

O conceito básico é usar permissões de esquema GRANT / DENY . Você pode gerenciar permissões com eficiência, criando uma função e adicionando membros a ela.

Abaixo está um exemplo que o explicará em detalhes

use master
go
--Create Logins
CREATE LOGIN UserA WITH Password='UserA123';
go
CREATE LOGIN UserB WITH Password='UserB123';

use AdventureWorks2008R2
go
--Create Database Users
CREATE USER UserA;
go
CREATE USER UserB;
go
--Create the Test Schemas
CREATE SCHEMA SchemaA AUTHORIZATION UserA
go
CREATE SCHEMA SchemaB AUTHORIZATION UserB
go

-- create test tables
create table schemaA.TableA (fname char(5))
go
insert into schemaA.TableA (fname) values ('Kin-A')
go

create table SchemaB.TableB (fname char(5))
go
insert into SchemaB.TableB (fname) values ('Kin-B')
go

Agora teste:

--Test for UserA in SchemaA
EXEC('select * from schemaA.TableA') AS USER = 'UserA'
go
--Kin-A

-- Test for UserB in SchemaB == this should fail
EXEC('select * from SchemaB.TableB') AS USER = 'UserA'
go
--Msg 229, Level 14, State 5, Line 1
--The SELECT permission was denied on the object 'TableB', database 'AdventureWorks2008R2', schema 'SchemaB'.

Agora crie procedimentos armazenados:

CREATE PROCEDURE SchemaB.proc_SelectUserB
AS
    select * from schemaA.TableA;
go
create procedure schemaA.proc_SchemaA
as 
    select * from schemaA.TableA

Agora conceda permissões de execução ao usuário A no SP do schemaB

GRANT EXECUTE ON OBJECT::[SchemaB].[proc_SelectUserB] TO [UserA] 
go

Teste .. para ver se o UsuárioA é capaz de executar o SP a partir do schemaB. Isto vai passar

EXECUTE AS LOGIN='UserA';
    Exec SchemaB.proc_SelectUserB;
    revert;
go
--- Kin-A

Mas o UsuárioA não poderá ver dados do SchemaB

EXECUTE AS LOGIN='UserA';
    select * from SchemaB.TableB
revert;
go

--- Msg 229, Level 14, State 5, Line 3
--- The SELECT permission was denied on the object 'TableB', database 'AdventureWorks2008R2', schema 'SchemaB'.

Como alternativa, você pode usar o DATABASE ROLE e apenas adicionar usuários a ele para obter melhor gerenciamento de permissões:

EXEC sp_addrole 'SchemaBUsesSchemaAProc'
go
EXEC sp_addrolemember 'SchemaBUsesSchemaAProc','UserA';
go

A instrução abaixo garantirá que o UsuárioA possa ver o esquemaA e NÃO o esquemaB. O bom é que você pode adicionar usuários à SchemaBUsesSchemaAProcfunção e eles herdarão todas as permissões concedidas a essa função.

GRANT SELECT ON SCHEMA::SchemaA TO SchemaBUsesSchemaAProc;
go

Se você deseja apenas permitir que o UsuárioA execute SPs pertencentes ao SchemaB, a instrução abaixo fará o trabalho:

GRANT EXECUTE ON OBJECT::[SchemaB].[proc_SelectUserB] TO [SchemaBUsesSchemaAProc] 
go

Dessa forma, o Usuário A não pode ver as tabelas do SchemaB, mas ainda pode executar procs do SchemaB.

Abaixo, explicaremos a hierarquia de permissões :

insira a descrição da imagem aqui

Kin Shah
fonte
2
Apenas para reiterar, é importante que os dois esquemas sejam de propriedade do mesmo usuário. Essa era a questão principal que eu estava tendo.
Julia McGuigan