Безопасность на уровне строк

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

Безопасность на уровне строк (RLS) упрощает проектирование и кодирование безопасности. Это позволяет применять ограничения доступа к строкам данных в приложении. Например, ограничьте доступ пользователей к строкам, относящимся к их отделу, или ограничьте доступ клиентов только к данным, относящимся к их компании.

Логика ограничения находится на уровне базы данных, а не на отдалении от данных на другом уровне приложения. Система баз данных применяет ограничения доступа при каждой попытке доступа к данным с любого уровня. Эта логика делает систему безопасности более надежной и надежной за счет уменьшения контактной зоны системы безопасности.

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

  • Предоставление доступа только к строкам, которые соответствуют некоторым критериям
  • Анонимизация данных в некоторых столбцах
  • Все вышеперечисленное

Примечание

Если для таблицы включена политика RLS, доступ полностью заменяется запросом RLS, определенным в таблице. Ограничение доступа применяется ко всем пользователям, включая администраторов баз данных и создателя RLS. Запрос RLS должен явно включать определения для всех типов пользователей, которым требуется предоставить доступ.

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

Совет

Эти функции часто полезны для row_level_security запросов:

Ограничения

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

Примеры

Ограничение доступа к таблице Sales

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

Sales | where SalesPersonAadUser == current_principal()

Вы также можете замаскировать адрес электронной почты:

Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"

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

let UserToCountryMapping = datatable(User:string, Country:string)
[
  "john@domain.com", "USA",
  "anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))

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

let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData

Предоставление различных данных членам разных групп Microsoft Entra

Если у вас есть несколько Microsoft Entra групп и вы хотите, чтобы члены каждой группы видели разные подмножества данных, используйте эту структуру для запроса RLS.

Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
        (current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
        (current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)

Применение одной и той же функции RLS к нескольким таблицам

Сначала определите функцию, которая получает имя таблицы в качестве строкового параметра и ссылается на таблицу table() с помощью оператора .

Пример:

.create-or-alter function RLSForCustomersTables(TableName: string) {
    table(TableName)
    | ...
}

Затем настройте RLS для нескольких таблиц следующим образом:

.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"

Создание ошибки при несанкционированном доступе

Если вы хотите, чтобы неавторизованные пользователи таблицы получали ошибку, а не возвращали пустую таблицу, используйте функцию assert() . В следующем примере показано, как создать эту ошибку в функции RLS:

.create-or-alter function RLSForCustomersTables() {
    MyTable
    | where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}

Этот подход можно объединить с другими примерами. Например, вы можете отображать разные результаты для пользователей в разных группах Microsoft Entra и выдавать ошибку для всех остальных пользователей.

Управление разрешениями для баз данных подписчиков

Политика RLS, настроенная в рабочей базе данных, также вступит в силу в базах данных подписчиков. Вы не можете настроить различные политики RLS в рабочей базе данных и базах данных подписчиков. Однако вы можете использовать функцию current_cluster_endpoint() в запросе RLS для достижения того же эффекта, что и разные запросы RLS в таблицах подписчиков.

Пример:

.create-or-alter function RLSForCustomersTables() {
    let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
    let DataForProductionCluster = TempTable | where IsProductionCluster;
    let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
    union DataForProductionCluster, DataForFollowerClusters
}

Примечание

Приведенная выше функция RLS не влияет на производительность запросов в кластере лидера. Влияние на производительность запросов в кластерах подписчиков будет зависеть только от сложности DataForFollowerClusters.

Другие варианты использования

  • Сотрудник службы поддержки колл-центра может идентифицировать абонентов по нескольким цифрам их номера социального страхования. Это число не должно быть полностью предоставлено сотруднику службы поддержки. К таблице можно применить политику RLS, чтобы скрыть все, кроме последних четырех цифр номера социального страхования, в результирующем наборе любого запроса.
  • Настройте политику RLS, которая маскирует персональные данные и позволяет разработчикам запрашивать рабочие среды для устранения неполадок, не нарушая нормативные требования.
  • Больница может задать политику RLS, которая позволяет медсестрам просматривать строки данных только для своих пациентов.
  • Банк может установить политику RLS, чтобы ограничить доступ к строкам финансовых данных на основе бизнес-подразделения или роли сотрудника.
  • Мультитенантное приложение может хранить данные из нескольких клиентов в одном наборе таблиц (что эффективно). Они будут использовать политику RLS для принудительного логического разделения строк данных каждого клиента от строк каждого другого клиента, чтобы каждый клиент видел только свои строки данных.

Влияние на производительность запросов

Если для таблицы включена политика RLS, это может повлиять на производительность запросов, которые обращаются к этой таблице. Доступ к таблице будет заменен запросом RLS, определенным в этой таблице. Влияние запроса RLS на производительность обычно состоит из двух частей:

  • Проверки членства в Microsoft Entra ID: проверки эффективны. Вы можете проверка членство в десятках или даже сотнях групп, не влияя на производительность запросов.
  • Фильтры, соединения и другие операции, применяемые к данным: влияние зависит от сложности запроса

Пример:

let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData

Если пользователь не является частью some_group@domain.com, то IsRestrictedUser оценивается как false. Вычислимый запрос аналогичен следующему:

let AllData = MyTable;           // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData       // this will just return AllData, as PartialData is empty

Аналогичным образом, если IsRestrictedUser вычисляется trueзначение , будет оцениваться только запрос PartialData для .

Повышение производительности запросов при использовании RLS

Влияние на производительность при приеме

Это не влияет на производительность приема.