Ustawianie uprawnień użytkownika dla różnych schematów SQL Server

16

Muszę ograniczyć dostęp do konkretnego użytkownika, ale nadal muszą widzieć dane w tabelach należących do dbo.

Próbuję wykonać następujące czynności:

  1. Schemat dbo działa tak, jak normalnie, ma dostęp do wszystkiego
  2. Schemat Schemat ma dostęp tylko do obiektów schematu 1
  3. jeśli widok schematu1 lub procedura składowana uzyskuje dostęp do danych w tabelach należących do dbo, łańcuch uprawnień odpowiednio
  4. użytkownik1 ma dostęp do schematu1 i nic więcej; z wyjątkiem przypadku # 3

Oto, co próbowałem:

  1. Utwórz użytkownika user1 zamapowanego na testowy login z losowym hasłem
  2. Utworzono kilka tabel w schemacie dbo z niektórymi danymi testowymi
  3. Utworzono schemat schematu 1
  4. Utworzono schema1.get_profiles, który wybiera z widoku o nazwie schema1.profiles, który uzyskuje dostęp do danych w dbo.people, dbo.taglinks i dbo.tags

Jednak przy użyciu następującej instrukcji podczas logowania jako użytkownik1:

EXEC get_profiles 1

prowadzi do:

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

Próbowałem WITH EXECUTE AS OWNERi nie mogę zrozumieć, jak powinno działać „łańcuchowanie własności”.

Próbowałem też

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

ale pojawia się następujący błąd (pomimo tego, że jestem użytkownikiem z dostępem na poziomie dbo):

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

To, czego potrzebuję, to użytkownik1, aby móc uzyskać dostęp do danych za pośrednictwem procedur składowanych, które im daję, i nic więcej.

Ponadto ma to ostatecznie za zadanie istnieć w istniejącej bazie danych SQL Azure, ale najpierw testuję lokalną bazę danych.

Julia McGuigan
źródło
Zobacz moją odpowiedź: Jak ukryć schemat przed użytkownikiem Daj mi znać, jeśli potrzebujesz dodatkowych wyjaśnień.
Kin Shah,
1
To wydaje mi się bardziej zrozumiałe. Myślę, że problem polegał na tym, że miałem właściciela Schema1 ustawionego na User1, zamiast dbo. Ustawiłem Schema1 na własność User1, dostosowałem i podążyłem za pytaniem, i udało mi się uzyskać coś działającego. Jeśli chcesz, możesz zaproponować odpowiedź na pytanie. Dzięki!
Julia McGuigan
Cieszę się, że to ci pomogło.
Kin Shah,

Odpowiedzi:

17

Podstawową koncepcją jest użycie uprawnień schematu GRANT / DENY . Możesz skutecznie zarządzać uprawnieniami, tworząc rolę, a następnie dodając do niej członków.

Poniżej znajduje się przykład, który szczegółowo Cię wyjaśni

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

Teraz przetestuj:

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

Teraz utwórz Procedury przechowywane:

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

Teraz udziel uprawnienia użytkownikowi A w SP schemaB

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

Przetestuj to .., aby sprawdzić, czy UserA jest w stanie uruchomić SP ze schematuB. To przejdzie

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

Ale Użytkownik nie będzie mógł zobaczyć danych ze 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'.

Alternatywnie możesz użyć DATABASE ROLE i po prostu dodać do niej użytkowników, aby lepiej zarządzać uprawnieniami:

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

Poniższe stwierdzenie upewni się, że UserA będzie w stanie zobaczyć schemat A, a NIE schemat. Dobrą rzeczą jest to, że możesz po prostu dodać użytkowników do SchemaBUsesSchemaAProcroli, a oni odziedziczą wszystkie uprawnienia nadane tej roli.

GRANT SELECT ON SCHEMA::SchemaA TO SchemaBUsesSchemaAProc;
go

Jeśli chcesz zezwolić UserA na wykonywanie SP, które są własnością SchemaB, poniższe polecenie wykona zadanie:

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

W ten sposób UserA nie widzi tabel SchemaB, ale nadal może wykonywać procy z SchemaB.

Poniżej wyjaśni hierarchię uprawnień :

wprowadź opis zdjęcia tutaj

Kin Shah
źródło
2
Dla przypomnienia ważne jest, aby oba schematy były własnością tego samego użytkownika. To był główny problem, który miałem.
Julia McGuigan,