Время прочтения: 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.