Database
 sql >> Base de Dados >  >> RDS >> Database

Exploração aprofundada da segurança em nível de linha

Introdução


As organizações estão cada vez mais preocupadas em como reduzir o custo de licenciamento de soluções de banco de dados usando a consolidação. Alguma consolidação pode ser obtida no SQL Server simplesmente aproveitando a relação um-para-muitos existente entre instâncias e bancos de dados. No entanto, há casos em que a solução exige que os dados sejam consolidados em uma tabela. Nesse caso, pode haver preocupações sobre como restringir o acesso aos dados.

A segurança em nível de linha foi introduzida no SQL Server 2016 como uma solução para cenários semelhantes aos acima. Ele permite que você restrinja o acesso a linhas em uma tabela com base nas condições definidas em uma Função com Valor de Tabela embutida chamada Função de Predicado . Quando uma Função de Predicado é aplicada a uma tabela de usuário contendo dados consolidados, o sistema pode ser configurado para retornar diferentes conjuntos de dados para diferentes usuários, dependendo de suas funções que, por sua vez, dependem de suas descrições de cargos ou departamentos, por exemplo.


Cenário


Construiremos um cenário simples para ilustrar esse conceito usando uma instituição financeira. Um banco decidiu consolidar as contas de todos os seus clientes em um único banco de dados e as Transações table é uma única tabela particionada contendo todas as transações, assim como Clientes mesa para armazenar todos os clientes do banco. O banco está localizado em vários países e também está em expansão. Cada país é identificado por um AffiliateID coluna. A empresa está estruturada de tal forma que o acesso às principais tabelas é restrito com base na antiguidade.

Identificar protegíveis


Precisaremos implementar uma solução de segurança em nível de linha que restrinja o acesso ao cliente e dados de transação com base em funções e uma política de segurança em nível de linha. Nosso primeiro passo é criar as tabelas necessárias. A Listagem 1 mostra o DDL para as tabelas-chave que testaremos. Todo o banco de dados usado para este teste pode ser baixado aqui.
Listing 1 – Core Tables in West African Commercial Bank Database;
-- Customers;
create table Customers
(CustID int identity (1000,1) not null Primary Key
,FirstName varchar(100)
,LastName varchar(100)
,PhoneNo bigint
,ContactAddress varchar(4000)
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,AccountNo1 bigint
,AccountNo2 bigint
,AccountNo3 bigint
,AccountNo1Curr char (3)
,AccountNo2Curr char (3)
,AccountNo3Curr char (3)
)
GO

-- Transactions;
create table Transactions
(TranID int identity (1000,1) not null 
,AcctID int foreign key references Accounts (AcctID)
,TranDate datetime 
,TranAmt money
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,primary key (TranID,TranDate))
ON PartSch (TranDate)

-- Transaction_History;
create table Transaction_History
(TranID int identity (1000,1) not null 
,AcctID int foreign key references Accounts (AcctID)
,TranDate datetime 
,TranAmt money
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,primary key (TranID,TranDate))
ON PartSch (TranDate)

Em seguida, criamos um conjunto de tabelas que podemos usar para identificar a equipe. Nesta configuração, cada equipe tem um ScopeID que determina até que ponto ele ou ela pode visualizar ou manipular dados:
  1. Nacional – Um funcionário só pode manipular dados no país do funcionário (onde ele trabalha)
  2. Regional – Um funcionário só pode manipular dados na região do funcionário (por exemplo, África Ocidental)
  3. Global – Um funcionário pode manipular dados em qualquer país onde o banco tenha uma agência

Cada escopo é atribuído à equipe com base em sua designação. O escopo de um gerente de grupo é Global , o escopo de um Country Manager é Regional e o escopo de um Executivo é Nacional . A maneira tradicional de restringir o acesso aos dados geralmente é o uso de funções e permissões. Atribuir permissões a uma função e, posteriormente, atribuir a função a um usuário significa que o usuário tem as permissões associadas a essa função para todo o conjunto de dados na tabela em questão. A segurança em nível de linha nos dá a oportunidade de fazer algo mais granular:restringir as permissões SELECT/UPDATE/DELETE do usuário a um subconjunto do conjunto de dados na tabela (controle de acesso refinado).



Fig. 1. StaffScope e Tabelas de Staff

Funções e usuários do banco de dados

A Listagem 2 mostra os usuários e funções que precisamos criar para prosseguir com nossa solução. A idéia é que haja uma relação entre a equipe armazenada nas tabelas de usuários Staff e StaffScope e os Database Principals que essas equipes eventualmente usarão para acessar os dados. Observe a coluna na Fig. 1 chamada DBUserID . Esta coluna é preenchida usando a função DATABASE_PRINCIPAL_ID (consulte a Listagem 2)
Listing 2 – Staff, Database User IDs and Roles

-- Populate Staff Table
use WACB
go
insert into Staff values ('John','Edu',DATABASE_PRINCIPAL_ID(),'Manager','233205678493','2','Accra, Ghana','EGH');
insert into Staff values ('Margaret','Harrison',DATABASE_PRINCIPAL_ID(),'Group Manager','2348030006574','3','Lagos, Nigeria','ENG');
insert into Staff values ('Edward','Antwi',DATABASE_PRINCIPAL_ID(),'Executive','22824567493','1','Lome, Togo','ETG');
insert into Staff values ('Barbara','Orji',DATABASE_PRINCIPAL_ID(),'Executive','22424567493','1','Abuja, Nigeria','ENG');
GO

-- Create Database User IDs for Staff
create user jedu without login;
create user mharrison without login;
create user eantwi without login;
create user borji without login;

-- Associate Database Principal IDs with Staff
update staff set DBUserID=DATABASE_PRINCIPAL_ID(concat(left(firstname,1),lastname));


-- Create Database Roles
create role [National] ;
create role [Regional] ;
create role [Global] ;

-- Grant Permissions on Desired Tables to Database Roles
grant select on customers to [National];
grant select, update on customers to Regional;
grant select, update on customers to Global;
grant select on Transactions to Regional, Global;
grant select on Transaction_History to Regional, Global;
grant update on Transactions to Global;


-- Grant Database Roles to Database Users Associated with Staff
alter role [National] add member eantwi;
alter role [National] add member borji;
alter role [Regional] add member jedu;
alter role [Global] add member mharrison;


Até agora, em resumo, o que fizemos foi:
  1. Crie/identifique as tabelas que precisamos proteger
  2. Crie tabelas que indiquem os critérios que usaremos para restringir o acesso aos dados no nível da linha (Escopo)
  3. Funções de banco de dados criadas e usuários aos quais aplicaremos restrições
  4. Acesso restrito às tabelas principais ("Segurança em nível de tabela") usando funções e permissões

Função de previsão e política de segurança

Até agora, temos o que podemos chamar de Segurança em Nível de Tabela implementado usando funções e permissões. Agora queremos ir mais fundo. Queremos que dois principais que tenham privilégios SELECT em uma tabela possam consultar a tabela, mas vejam conjuntos de dados diferentes com base nas condições que configuramos. Listagem 3 nos mostra como conseguimos isso.
Listing 3 - Implement Row Level Security

-- Create Predicate Function
create schema rls;
go

create function rls.AccessPredicate (@AffiliateID char(3))
returns table
with schemabinding
as
return select 1 as access 
from dbo.Staff as s 
join dbo.StaffScope ss on s.ScopeID=ss.ScopeID 
join dbo.Affiliates a on s.AffiliateID=a.AffiliateID
where (
IS_MEMBER('National')=1
and s.DBUserID=DATABASE_PRINCIPAL_ID()
and @AffiliateID=s.AffiliateID
)
OR
(
IS_MEMBER('Regional')=1
and @AffiliateID in (select a.AffiliateID from dbo.Affiliates where Region='West Africa')
)
OR
(
IS_MEMBER('Global')=1
);
GO

-- Create Security Policy
create security policy rls.dataSecurityPol
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Customers,
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transactions,
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Customers after update,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transactions after update,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History after update;
GO

-- Alter Security Policy
alter security policy rls.dataSecurityPol
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History after update;
GO

A função de predicado define as condições que devem ser atendidas para que um principal veja um subconjunto dos dados interessantes. Nesta função, existem três condições:
  1. O usuário do banco de dados da equipe é membro do National função e o AffiliateID corresponde ao da equipe OU
  2. O usuário do banco de dados da equipe é membro da Regional função e o AffiliateID corresponde à lista de AffiliateID 's pertencentes à Região da África Ocidental OU
  3. O usuário do banco de dados da equipe é membro da Global

Isso implica que um membro do Global função vê todos os dados simplesmente porque ele ou ela pertence a essa função. No entanto, os membros das outras duas funções devem atender a critérios adicionais que fazem fronteira com os AffiliateIDs .

Para que a função seja útil, aplique isso às tabelas como predicados FILTER ou BLOCK. Os predicados FILTER restringem o que o principal pode ver, enquanto os predicados BLOCK garantem que o principal não possa manipular nenhum dado fora do que é apresentado a ele pelas restrições definidas na função. Uma Política de Segurança é um contêiner no qual especificamos os predicados FILTER e BLOCK para todas as tabelas que nos interessam. Dê uma olhada na Listagem 3 novamente.

Um aspecto muito interessante desta abordagem é a modularidade. Podemos aplicar os predicados a tabelas adicionais na Política de Segurança sem afetar as tabelas definidas existentes, podemos adicionar novos principais de banco de dados (Staff) criando usuários de banco de dados e concedendo a eles as funções apropriadas. Quando ocorre movimento de equipe, podemos atualizar as atribuições de função e assim por diante.

Testar a implementação

Agora que terminamos, podemos representar os principais do banco de dados para determinar se temos os resultados esperados usando o código da Listagem 4. Antes de analisarmos isso, vamos ver as funções associadas a cada equipe e seus afiliados na Figura 2.



Fig. 2. Lista de trabalhadores


Listing 4 – Testing the Implementation

select * from Customers;
execute ('select * from Customers') as user='eantwi';
execute ('select * from Customers') as user='borji';
execute ('select * from Customers') as user='jedu';
execute ('select * from Customers') as user='mharrison';


Na primeira linha, consulto os Clientes tabela como um administrador de sistema, mas não recebo LINHAS. Significando que mesmo um administrador não pode substituir os efeitos do RLS sem representação.



Fig. 4. SysAdmin não vê linhas

Barbara e Edward são ambos Executivos e pertencem ao Escopo Nacional, mas trabalham em países diferentes para que vejam os Clientes associados às suas respectivas afiliadas. (Consulte os nomes dos funcionários na Fig. 1).



Fig. 5. Executivos veem as linhas de seus afiliados

John e Margaret são gerentes de país e de grupo. Eles pertencem à Regional e Global Escopos respectivamente. John vê dados da África Ocidental, enquanto Margaret vê dados de todas as regiões.



Fig. 6. Os gerentes veem as linhas de sua região

Os resultados são os mesmos para todas as outras tabelas às quais a Política de Segurança foi aplicada. Observe que, sem permissões nas Transações tabela, a segurança em nível de linha não tem valor.



Fig. 7. Sem permissões SELECT em Transações Tabela
Listing 5 – Permissions on Transactions Table
grant select on dbo.Transactions to [National];



Fig. 8. Transações Tabela vista pelos executivos

Conclusão

A segurança em nível de linha é um método poderoso de explorar o recurso de controle de acesso refinado do SQL Server. O uso desse recurso requer que você esteja executando o SQL Server 2016 ou superior. Como o nome indica, o objetivo é restringir o acesso a linhas dentro de uma tabela usando consultas complexas depois de cuidar da “segurança no nível da tabela”. Os cenários em que esse recurso pode ser aplicado são infinitos, portanto, é muito útil para uma ampla variedade de ambientes. Faça bem em explorar e ver o que ele pode fazer por você.

Referências

Isakov, V. (2018). Exam Ref 70-764 Administrando uma infraestrutura de banco de dados SQL . Pearson Education

Segurança em nível de linha