Используйте RBAC с ABAC

Important

RBAC находится в общедоступной предварительной версии. ABAC общедоступен. На этой странице описывается, как они работают вместе.

Управление доступом на основе ролей (RBAC) и управление доступом на основе атрибутов (ABAC) в каталоге Unity являются дополнительными элементами управления, предназначенными для совместной работы. Они отвечают на различные вопросы:

  • RBAC определяет, под какой учётной записью пользователь действует в рамках сеанса. Пользователь принимает на себя роль, чтобы выполнять действия с правами доступа этой роли, а не со своими собственными. Используйте RBAC, чтобы назначить одному пользователю несколько отдельных наборов разрешений, между которыми он явно переключается, — например, разграничивая доступ между клиническими испытаниями, проектами или уровнями конфиденциальности.
  • ABAC контролирует, какие данные может видеть активный субъект, построчно или по столбцам. Политики связываются с данными с помощью управляемых тегов и применяются в зависимости от того, какая учетная запись выполняет запрос. Используйте ABAC для согласованной фильтрации или маскирования во многих таблицах, управляемых атрибутами данных.

RBAC задает активную идентичность для сеанса, а ABAC оценивает политики относительно этой идентичности. На этой странице рассматривается, как это взаимодействие проявляется на практике, поведение SQL-функций, связанных с идентификацией, и шаблоны их совместного использования.

Поведение функций идентификации при выполнении роли

Функции SQL Unity Catalog, связанные с идентификацией, используют активную идентичность сеанса, а не исходного аутентифицированного пользователя. Когда пользователь принимает на себя роль, активный идентификатор сеанса становится этой ролью:

Function Когда пользователь действует от имени своей учётной записи Когда пользователь принимает роль
current_user() Возвращает имя пользователя Возвращает имя предполагаемой роли
is_member(group) Возвращает true, если пользователь является участником группы (локальной для рабочей области группы или группы учетной записи, назначенной для рабочей области) Возвращается true только в том случае, если предполагаемая роль является членом group. Возвращает false для групп, участником которых является исходный пользователь, но не принятая роль.
is_account_group_member(group) Возвращает, true является ли пользователь членом группы уровня учетной записи. То же, что и is_member: возвращает true только на основе членства в группах принятой роли, а не исходного пользователя.

Политики ABAC, ссылающиеся на эти функции, оцениваются по отношению к принятой роли, а не к пользователю. Принятая роль — это активная удостоверяющая сущность для оценки политик ABAC, определения предоставленных прав в Unity Catalog и атрибуции событий аудита. В результате принятие роли изменяет поведение существующих политик и представлений, построенных на основе индивидуальной идентификации пользователей.

Note

Роль не является автоматически членом самой себя. Когда пользователь принимает на себя роль G, current_user() возвращает G, но is_member('G') и is_account_group_member('G') возвращают false, если только G не был явно добавлен в качестве собственного участника. Чтобы сопоставить предполагаемую роль в политике, сравнивайте с current_user(), а не проверяйте членство с помощью is_member или is_account_group_member.

Распространенные ошибки: представления безопасности на уровне строк, созданные на основе current_user()

Распространённый подход как для ABAC, так и для фильтров строк на уровне таблицы, заключается в фильтрации строк путём объединения с таблицей предоставления доступа (также называемой таблицей сопоставления или списком управления доступом), где ключом служит имя пользователя, возвращаемое current_user(). Рассмотрим пример.

CREATE OR REPLACE FUNCTION facility_filter(facility_id STRING)
RETURN EXISTS (
  SELECT 1
  FROM governance.user_facility_provisioning p
  WHERE p.user = current_user()
    AND p.facility_id = facility_id
);

Когда тот же пользователь принимает роль, current_user() больше не возвращает имя пользователя. Он возвращает имя роли. Поскольку роль отсутствует в таблице выделения прав, фильтр не возвращает ни одной строки, и пользователю кажется, что он теряет доступ к данным, к которым ему ранее был предоставлен доступ.

Добавьте роль в таблицу предоставления

Рассматривайте роль как еще один принципал в данных провизионирования: вставьте по одной строке для каждой роли с объектами инфраструктуры (или другими атрибутами), к которым роль должна иметь доступ. Затем фильтр проверяет, является ли активный субъект пользователем или принятой ролью.

Сценарии совместного использования

Ниже приведены примеры того, как клиенты используют RBAC и ABAC вместе для решения реальных проблем управления доступом. Это начальные точки, а не исчерпывающие рецепты.

Построчные фильтры для каждого проекта с привязкой к предполагаемой роли

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

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

Настройка:

  • Таблицы под clinical_trials.* имеют столбец project_id, помеченный ключом project тега governed.
  • Каждому проекту соответствует роль доступа с названием role-<project> (например, role-alpha, role-beta).
  • У пользователей есть разрешение Assume только на использование ролей в проектах, над которыми они работают.

UDF-фильтр строк:

CREATE FUNCTION project_match(project_id STRING) RETURNS BOOLEAN
DETERMINISTIC
RETURN current_user() = CONCAT('role-', project_id);

Политика:

CREATE POLICY per_project_row_filter
ON CATALOG clinical_trials
ROW FILTER project_match
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('project') AS project
USING COLUMNS (project);

Этот UDF сопоставляет активный идентификатор со значением тега project в каждой строке, поэтому условия, нацеленные на субъекты безопасности, такие как TO / EXCEPT, не позволяют выразить такую связь — они нацелены на субъекты безопасности, а не на содержимое строк. Как объясняется в руководстве по нацеливанию на субъекты безопасности, для простого ограничения области действия по субъекту безопасности предпочтительно использовать TO / EXCEPT, а функции идентификации внутри UDF следует оставлять для таких случаев, как этот, когда одно правило зависит и от активного субъекта безопасности, и от содержимого строки.

Отдельная политика охватывает каждый проект: USING COLUMNS (project) передает значение тега project каждой строки в UDF, поэтому для каждого проекта не требуется отдельная политика. Общую форму этого метода — управление доступом на уровне строк с помощью таблицы сопоставления вместо сопоставления имён ролей — см. в Использование таблиц сопоставления для динамического управления доступом.

Поведение:

  • Пользователь, при использовании своей идентичности пользователя, не видит ни одной строки ни в одной clinical_trials таблице. current_user() возвращает имя пользователя, которое никогда не соответствует шаблону role-* именования. Это предусмотренный запрет по умолчанию.
  • Пользователь, принимающий role-alpha, видит только те строки, где project_id равно alpha. При переключении на role-beta отображаемые данные заменяются без повторного запроса чего-либо ещё.

Маскирование персональных данных ослаблено для пользователей, выступающих в назначенной роли

По умолчанию столбцы с персональными данными (SSN, адрес электронной почты, номер телефона) отображаются в скрытом виде для всех пользователей. Чтобы увидеть исходные значения, пользователь должен явно взять на себя специально назначенную роль, имеющую доступ к PII. Журналы аудита фиксируют событие принятия роли, поэтому фраза «мне нужно было посмотреть реальные персональные данные (PII)» становится явным действием, подлежащим аудиту, а не неявным постоянным разрешением.

Настройка:

  • Конфиденциальные столбцы помечены ключом pii (допустимые значения, например ssn, email, phone).
  • Пользователям, имеющим разрешение на просмотр необработанных персональных данных, предоставляется возможность Assume для роли доступа с именем role-pii-cleared.

UDF для маскирования столбцов (статическая — политика определяет, для каких субъектов применять маскирование):

CREATE FUNCTION mask_pii(val STRING) RETURNS STRING
DETERMINISTIC
RETURN '***';

Политика:

CREATE POLICY pii_default_mask
ON CATALOG customer_data
COLUMN MASK mask_pii
TO `account users`
EXCEPT `role-pii-cleared`
FOR TABLES
MATCH COLUMNS has_tag('pii') AS pii_col
ON COLUMN pii_col;

Условие EXCEPT полностью исключает role-pii-cleared из политики, поэтому UDF никогда не вызывается, когда эта роль является активной идентичностью. Общие рекомендации по нацеливанию на участников с помощью TO / EXCEPT см. в разделе Предпочитайте TO/EXCEPT для нацеливания на участников.

Поведение:

  • Пользователь, действующий от имени своей учетной записи, видит *** в каждом столбце PII. Это состояние по умолчанию для всех, включая пользователей, у которых есть разрешение Assume на role-pii-cleared.
  • После предположения role-pii-clearedполитика больше не применяется к сеансу, а тот же пользователь видит необработанные значения.
  • Записи журнала аудита для записи сеанса identity_metadata.run_as = role-pii-cleared, чтобы проверяющие могли точно видеть, когда PII были деанонимизированы и кем.

Политики уровня чувствительности, различающиеся в зависимости от принятой роли

Данные классифицируются по уровням конфиденциальности (internal, confidential, restricted). Каждому уровню соответствует определённая роль доступа, при этом restricted также подразумевает доступ к confidential и internal. Одна UDF-функция фильтрации строк управляет видимостью строк, сравнивая уровень доступа каждой строки с принятой ролью пользователя.

Настройка:

  • Таблицы имеют sensitivity_level столбец, помеченный ключом sensitivity (допустимые значения: internal, confidential, restricted).
  • Три роли доступа: role-sens-internal, role-sens-confidential, role-sens-restricted.

UDF фильтра строк:

CREATE FUNCTION sensitivity_allowed(row_sensitivity STRING) RETURNS BOOLEAN
DETERMINISTIC
RETURN CASE
  WHEN current_user() = 'role-sens-restricted' THEN TRUE
  WHEN current_user() = 'role-sens-confidential' THEN row_sensitivity IN ('internal', 'confidential')
  WHEN current_user() = 'role-sens-internal' THEN row_sensitivity = 'internal'
  ELSE FALSE
END;

Политика:

CREATE POLICY sensitivity_filter
ON CATALOG corp_data
ROW FILTER sensitivity_allowed
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('sensitivity') AS sens
USING COLUMNS (sens);

Поскольку роль не является членом самой себя, этот UDF сравнивает current_user() с каждым именем роли, а не проверяет членство с помощью is_account_group_member(). См. примечание выше о том, почему тесты членства не соответствуют предполагаемой роли. См. аспекты производительности для политик фильтрации строк и маскирования столбцов, чтобы узнать о характеристиках производительности функций идентичности в пользовательских функциях.

Поведение:

  • Пользователь, действующий от имени своей учетной записи, не видит ни одной строки. Ветка ELSE FALSE соответствует любому значению, которое не относится ни к одной из трёх ролей. Как и в приведённом выше примере на уровне проекта, здесь подразумевается запрет по умолчанию.
  • Предположим, что role-sens-internal отображает только internal строк.
  • Предположим, что role-sens-confidential отображает строки internal и confidential.
  • Предполагая, что role-sens-restricted отображает все строки.

Пользователи предполагают, что для сеанса требуется самый высокий уровень; Фильтр автоматически исключает все, что выше этого уровня, не требуя, чтобы пользователь знал, какие таблицы содержат классификации.

Проверка указания авторства

Как при вычислении политик ABAC, так и базовые запросы учитывают атрибуцию RBAC run_as / run_by. В записях журнала аудита identity_metadata.run_by указывается как пользователь, проходящий аутентификацию, а identity_metadata.run_as — как принятая роль, независимо от того, какие политики ABAC применялись при оценке. См. справочник по системе журнала аудита для полной схемы журнала аудита.

Дальнейшие действия

  • Исключительный доступ к модели: Применяйте шаблоны для настройки исключительного доступа с помощью локальной группы учетной записи или группы, синхронизированной из Microsoft Entra ID. См. эксклюзивный доступ к модели.
  • Переключение ролей. Предположим, что роль используется с помощью коммутатора ролей, кластеров выделенного режима доступа, интерфейса командной строки, API или сторонних средств бизнес-аналитики. См. раздел "Переключение ролей".
  • Управление разрешениями на принятие роли: предоставьте группе или отзовите у неё разрешение на принятие роли, чтобы пользователи могли принять соответствующую роль. См. статью "Управление разрешениями для группы".
  • Ознакомьтесь с основными понятиями ABAC: узнайте, как работают управляемые теги, политики и оценка политики. См. раздел "Управление доступом на основе атрибутов" в каталоге Unity.