sql >> Base de Datos >  >> RDS >> Database

Exploración en profundidad de la seguridad a nivel de fila

Introducción

Las organizaciones están cada vez más preocupadas por cómo reducir el costo de las licencias de las soluciones de bases de datos mediante la consolidación. Se puede lograr cierta consolidación en SQL Server simplemente aprovechando la relación uno a muchos existente entre las instancias y las bases de datos. Sin embargo, hay casos en los que la solución exige que los datos se consoliden en una tabla. En tal caso, puede haber dudas sobre cómo restringir el acceso a los datos.

Row Level Security se introdujo en SQL Server 2016 como una solución para escenarios similares a los anteriores. Le permite restringir el acceso a las filas de una tabla en función de las condiciones definidas en una función de valor de tabla en línea denominada función de predicado . Cuando se aplica una función de predicado a una tabla de usuarios que contiene datos consolidados, el sistema se puede configurar para devolver diferentes conjuntos de datos a diferentes usuarios según sus roles, lo que a su vez depende de sus descripciones de trabajo o departamentos, por ejemplo.

Escenario

Construiremos un escenario simple para ilustrar este concepto usando una institución financiera. Un banco ha decidido consolidar las cuentas de todos sus clientes en una única base de datos y las Transacciones la tabla es una única tabla particionada que contiene todas las transacciones, al igual que los Clientes tabla para almacenar todos los clientes del banco. El banco está ubicado en varios países y también se está expandiendo. Cada país se identifica con un AffiliateID columna. La empresa está estructurada de tal manera que el acceso a las mesas clave está restringido en función de la antigüedad.

Identificar elementos asegurables

Tendremos que implementar una solución de seguridad de nivel de fila que restrinja el acceso a los datos del cliente y de la transacción según los roles y una política de seguridad de nivel de fila. Nuestro primer paso es crear las tablas requeridas. El Listado 1 muestra el DDL para las tablas clave que probaremos. La base de datos completa utilizada para esta prueba se puede descargar desde aquí.

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)

Luego creamos un conjunto de tablas que podemos usar para identificar al personal. En esta configuración, cada personal tiene un ScopeID que determina hasta qué punto él o ella puede ver o manipular datos:

  1. Nacional – Un miembro del personal solo puede manipular datos en el país del miembro del personal (donde él o ella trabaja)
  2. Regional – Un miembro del personal solo puede manipular datos en la región del miembro del personal (por ejemplo, África Occidental)
  3. Global – Un miembro del personal puede manipular datos en cualquier país donde el banco tendrá una sucursal

Cada ámbito se asigna al personal en función de su designación. El alcance de un Administrador de grupo es Global , el alcance de un Country Manager es Regional y el ámbito de un Ejecutivo es Nacional . La forma tradicional de restringir el acceso a los datos suele ser el uso de roles y permisos. Asignar permisos a un rol y luego asignar el rol a un usuario significa que el usuario tiene los permisos asociados con ese rol para todo el conjunto de datos en la tabla en cuestión. La seguridad de nivel de fila nos brinda la oportunidad de hacer algo más granular:restringir los permisos SELECCIONAR/ACTUALIZAR/ELIMINAR del usuario a un subconjunto del conjunto de datos en la tabla (control de acceso detallado).

Fig. 1. StaffScope y tablas de pentagrama

Roles y usuarios de la base de datos

El Listado 2 muestra los usuarios y roles que tenemos que crear para continuar con nuestra solución. La idea es que exista una relación entre el personal almacenado en las tablas de usuario Staff y StaffScope y los principales de la base de datos que este personal usará eventualmente para acceder a los datos. Observe la columna en la Fig. 1 llamada DBUserID . Esta columna se completa con la función DATABASE_PRINCIPAL_ID (consulte el Listado 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;

Hasta ahora en resumen lo que hemos hecho es:

  1. Crear/identificar las tablas que necesitamos proteger
  2. Cree tablas que indiquen los criterios que usaremos para restringir el acceso a los datos a nivel de fila (Ámbito)
  3. Roles de base de datos creados y usuarios a los que aplicaremos restricciones
  4. Acceso restringido a las tablas centrales ("Seguridad a nivel de tabla") usando roles y permisos

Función de predicción y política de seguridad

Hasta ahora tenemos implementado lo que podemos llamar seguridad de nivel de tabla mediante roles y permisos. Ahora queremos ir más profundo. Queremos que dos principales que tengan privilegios SELECT en una tabla puedan consultar la tabla pero ver diferentes conjuntos de datos según las condiciones que configuramos. Listado 3 nos muestra cómo logramos esto.

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

La función de predicado define las condiciones que se deben cumplir para que un principal vea un subconjunto de los datos interesantes. En esta función, hay tres condiciones:

  1. El usuario de la base de datos del Staff es miembro de la Nacional rol y el AffiliateID coincide con el del personal O
  2. El usuario de la base de datos del Staff es miembro de la Regional rol y el AffiliateID coincide con la lista de AffiliateID Pertenece a la Región de África Occidental O
  3. El usuario de la base de datos de Staff es miembro de Global

Esto implica que un miembro de Global rol ve todos los datos simplemente porque él o ella pertenece a ese rol. Sin embargo, los miembros de los otros dos roles deben cumplir criterios adicionales que bordean los AffiliateIDs. .

Para que la función sea útil, aplique esto a las tablas como predicados de FILTRO o predicados de BLOQUEO. Los predicados FILTER restringen lo que el principal puede ver, mientras que los predicados BLOCK aseguran que el principal no pueda manipular ningún dato fuera de lo que le presentan las restricciones definidas en la función. Una política de seguridad es un contenedor en el que especificamos los predicados FILTER y BLOCK para todas las tablas que nos interesan. Eche un vistazo al Listado 3 de nuevo.

Un aspecto muy interesante de este enfoque es la modularidad. Podemos aplicar los predicados a tablas adicionales en la Política de seguridad sin afectar las tablas definidas existentes, podemos agregar nuevos principales de base de datos (Personal) creando usuarios de base de datos y otorgándoles los roles apropiados. Cuando se produce un movimiento de personal, podemos actualizar las asignaciones de funciones, etc.

Prueba de la implementación

Entonces, ahora que hemos terminado, podemos suplantar a los principales de la base de datos para determinar si tenemos los resultados esperados usando el código del Listado 4. Antes de ver eso, veamos los roles asociados con cada personal y sus afiliados en la Fig. 2.

Fig. 2. Lista de personal

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

En la primera línea, consulto los Clientes tabla como administrador de sistemas, pero no obtengo FILAS. Lo que significa que incluso un administrador no puede anular los efectos de RLS sin suplantación.

Fig. 4. SysAdmin no ve filas

Barbara y Edward ambos son Ejecutivos y pertenecen al Ámbito Nacional pero trabajan en diferentes países por lo que ven a los Clientes asociados a sus respectivas filiales. (Consulte los nombres del personal en la Fig. 1).

Fig. 5. Los ejecutivos ven las filas de sus afiliados

John y Margaret son Gerentes de País y Grupo. Pertenecen a la Regional y Global alcances respectivamente. John ve los datos de África Occidental, mientras que Margaret ve los datos de todas las regiones.

Fig. 6. Los gerentes ven las filas de su región

Los resultados son los mismos para todas las demás tablas a las que se ha aplicado la política de seguridad. Observe que sin permisos sobre las Transacciones la seguridad de nivel de fila no tiene valor.

Fig. 7. Sin permisos SELECT en Transacciones Mesa

Listing 5 – Permissions on Transactions Table
grant select on dbo.Transactions to [National];

Fig. 8. Transacciones Mesa vista por los ejecutivos

Conclusión

Row Level Security es un método poderoso para explotar la capacidad de control de acceso de grano fino de SQL Server. El uso de esta función requiere que esté ejecutando SQL Server 2016 o superior. Como su nombre lo indica, el objetivo es restringir el acceso a las filas dentro de una tabla mediante consultas complejas después de haberse ocupado de la "seguridad a nivel de tabla". Los escenarios en los que se puede aplicar esta capacidad son infinitos, por lo que es muy útil para una amplia gama de entornos. Haga bien en explorar y ver lo que puede hacer por usted.

Referencias

Isakov, V. (2018). Referencia de examen 70-764 Administración de una infraestructura de base de datos SQL . Educación Pearson

Seguridad a nivel de fila