Время прочтения: 4 мин.

Иногда возникает необходимость ограничения доступа ряду сотрудников к определенной информации, хранящейся в базе банных. Я предлагаю познакомиться с одной из функций SQL Server, которая позволяет контролировать доступ к уровню строк в таблице базы данных в зависимости от пользователя, выполняющего запрос.

Безопасность на уровне строк (Row-Level Security, RLS) ограничивает пользователей таким образом, чтобы они могли работать исключительно с теми данными, к которым у них имеется доступ. Кроме того, данная функция не дает возможности пользователям вставлять, обновлять или удалять данные, доступ к которым запрещен.

Давайте рассмотрим, как можно использовать функцию Row-Level Security на примере условной таблицы, назовем ее ObjectCheck, в которой отражена информация об объектах аудита, сроках начала и завершения проверок и т.д.

Перед нами поставлена задача: каждый пользователь базы данных должен получить доступ к данным, относящимся только к нему, без доступа к проверкам, назначенным другим сотрудникам.

Для выполнения примера создадим трех пользователей базы данных:

create user Ivanovii without login;
create user PetrovPP without login;
create user SidorovSS without login;

 предоставим доступ SELECT к таблице ObjectCheck для этих пользователей:

grant select on ObjectCheck to Ivanovii;
grant select on ObjectCheck to PetrovPP;
grant select on ObjectCheck to SidorovSS;

Кроме того, желательно создать отдельную схему для объектов базы данных Row-Level Security:

create schema rs;
GO

Ограничение доступа к данным с использованием Row-Level Security достигается путем определения предиката безопасности (Security predicate) как функции, которая ограничивает строки на основе логики фильтрации, которая вызывается и применяется политикой безопасности (Security Policy), созданной с помощью T-SQL оператора  CREATE SECURITY POLICY, и работает как контейнер предикатов.

Давайте выполним настройку функции безопасности на уровне строк для таблицы ObjectCheck.

Создаем функцию, зависящую от пользователей, вошедших в систему, чтобы была возможность фильтровать пользователей и проверять их доступы к данным:

create function rs.fn_secureData(@Username as sysname)
returns table
with schemabinding
as
return select 1 as 'secureObjectCheck' 
where @Username = User_Name();

Создадим политику безопасности в таблице ObjectCheck, используя ранее созданную функцию предиката:

create security policy Object_Check
add filter predicate rs.fn_secureData(User)   
on dbo.ObjectCheck
with (state = on);

Теперь защита на уровне строк настроена и готова к фильтрации доступа к данным в таблице ObjectCheck.

Так, если выполнить запрос, указав пользователя Ivanovii:

execute as user = 'Ivanovii';
select * from ObjectCheck; 
revert;

то запрос вернет только две записи, связанные с пользователем Ivanovii:

Аналогичный результат будет возвращен при запросе данных из таблицы ObjectCheck пользователями PetrovPP и SidorovSS:

execute as user = 'PetrovPP';
select * from ObjectCheck;   
revert;
execute as user = 'SidorovSS';
select * from ObjectCheck;   
revert;

Из приведенных примеров видно, что функция безопасности на уровне строк может использоваться для фильтрации данных, которые может видеть каждый пользователь, в зависимости от критериев фильтрации, определенных в функции предиката.

Если необходимо прекратить использование функции безопасности rs.fn_SecureData, то можно отключить политику безопасности Object_Check с помощью инструкции ALTER SECURITY POLICY:

alter security policy Object_Check with (state = off)

Затем выполнить запрос DROP для удаления функции и политики безопасности:

drop security policy Object_Check
drop function rs.fn_secureData

Теперь безопасность на уровне строк полностью удалена из таблицы Object_Check.

Можно легко добавлять предикаты и критерии фильтрации, подходящие для определенных ситуаций, однако, слишком сложные предикаты ухудшают производительность базы данных, поскольку предикат будет проверяться каждый раз при выполнении доступа к данным. Более подробно ознакомиться с Row-Level Security можно на сайте Microsoft.