Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описывается, как сторонние разработчики подсистемы могут интегрироваться с безопасностью OneLake для запроса данных из OneLake при применении безопасности на уровне строк (RLS) и безопасности на уровне столбцов (CLS). Интеграция использует модель авторизованного модуля, где модуль считывает данные непосредственно из OneLake и применяет политики безопасности в собственном вычислительном слое.
Замечание
Эта функция является частью предварительной версии и предоставляется только для оценки и разработки. Он может изменяться на основе отзывов и не рекомендуется для производственного использования.
Обзор
Безопасность OneLake определяет детализированные политики управления доступом, включая безопасность на уровне таблиц, строк и столбцов, единожды в OneLake. Подсистемы Fabric, такие как Spark и конечная точка SQL-аналитики, применяют эти политики во время выполнения запроса. Тем не менее, OneLake обеспечивает соблюдение более точной политики контроля доступа независимо от способа доступа к данным. В результате неавторизованные внешние запросы на чтение файлов из OneLake блокируются, чтобы предотвратить утечку данных.
Модель авторизованной модели двигателя решает эту проблему. Вы регистрируете выделенное удостоверение (субъект-службу или управляемое удостоверение), которое имеет полный доступ на чтение к данным, а также может считывать метаданные безопасности. Ваш движок использует это удостоверение для:
- Прочитать необработанные файлы данных из OneLake.
- Получите действующие политики безопасности для данного пользователя, вызвав авторизованный доступ для основного API.
- Примените возвращаемые фильтры строк и столбцов в собственном слое выполнения запроса.
- Возвращает только разрешенные данные пользователю.
Такой подход дает вашему движку полный контроль над планированием запросов и кэшированием, при этом поддерживая соблюдение безопасности в соответствии с тем, как это обеспечивается движками Fabric, и передавая контроль над авторизацией в руки пользователя.
Необходимые условия
Прежде чем начать интеграцию, убедитесь, что у вас есть следующее:
- Учётная запись службы Microsoft Entra или управляемое удостоверение, которые использует движок для доступа к OneLake. Поддерживаются только удостоверения Microsoft Entra.
- Роль Участника рабочей группы (или выше) для удостоверения подсистемы в целевой рабочей области. Это дает удостоверению необходимые привилегии для чтения файлов данных и метаданных безопасности из OneLake.
- Элемент Fabric (lakehouse, зеркальная база данных или зеркальный каталог) с включенной безопасностью OneLake.
- Роли безопасности OneLake , настроенные для элемента с любыми политиками RLS или CLS, которые необходимо применить.
- Идентификатор движка должен иметь неограниченный доступ для чтения к таблицам, из которых он считывает данные. Если политики RLS или CLS применяются к идентификатору самого ядра, API-вызовы возвращают ошибки.
Architecture
На следующей схеме показан поток авторизации высокого уровня для интеграции авторизованного модуля.
┌──────────────┐ ┌──────────────────┐ ┌───────────┐
│ End user │──1──▶│ 3rd-party engine │──2──▶│ OneLake │
│ (query) │ │(service principal)│◀──3──│ (data + │
│ │◀──6──│ │──4──▶│ security)│
└──────────────┘ └──────────────────┘ └───────────┘
- Конечный пользователь отправляет запрос стороннему обработчику.
- Идентификация движка проходит аутентификацию в OneLake и читает исходные файлы данных (Delta parquet) с помощью интерфейса API OneLake.
- OneLake возвращает запрошенные данные.
- Движок вызывает
principalAccessAPI, передает идентификатор объекта пользователя Microsoft Entra, чтобы получить актуальные права доступа пользователя. - Модуль применяет возвращенные фильтры доступа (доступ к таблицам, предикаты RLS, списки столбцов CLS) к данным в собственном вычислительном слое.
- Движок возвращает только отфильтрованные результаты, разрешенные конечному пользователю.
Шаг 1. Настройка идентификатора движка
Вашему механизму требуется удостоверение Microsoft Entra, которое OneLake распознает и доверяет. Идентификатор считывает файлы данных и метаданные безопасности от имени вашего движка.
Создайте или определите учетную запись службы или управляемую идентификацию в Microsoft Entra ID для вашего движка. Для получения дополнительной информации см. Объекты приложения и учетной записи службы в Microsoft Entra ID.
Добавьте идентификатор в роль участника рабочей области. На портале Fabric перейдите к параметрам рабочей области и добавьте учетную запись службы в роль участника. Это гарантирует личность:
- Доступ на чтение ко всем файлам данных в OneLake для элементов в этом рабочем пространстве.
- Предоставление доступа к метаданным роли безопасности OneLake через API движков с авторизацией.
Дополнительные сведения о ролях рабочей области см. в разделе "Роли в рабочих областях".
Убедитесь, что идентификатор имеет неограниченный доступ. Идентификатор движка должен иметь полный доступ на чтение к каждой таблице, которую он запрашивает. Если какая-либо роль безопасности OneLake применяет ограничения RLS или CLS к идентификации движка, чтение данных и вызов API завершаются ошибкой. Рекомендуется не добавлять идентификацию движка в роли безопасности OneLake, содержащие ограничения RLS или CLS.
Это важно
Вы можете отозвать доступ движка в любое время, удалив его из роли рабочей области. Отмена доступа вступает в силу примерно через 2 минуты.
Шаг 2. Чтение данных из OneLake
С настроенной идентификацией движка ваш движок может считывать файлы данных непосредственно из OneLake с помощью стандартных совместимых API Azure Data Lake Storage (ADLS) Gen2.
Данные OneLake доступны по адресу:
https://onelake.dfs.fabric.microsoft.com/{workspaceId}/{itemId}/Tables/{schema}/{tableName}/
Движок выполняет аутентификацию с помощью токена-носителя, полученного через поток учетных данных клиента Microsoft Entra OAuth 2.0. Используйте область ресурсов OneLake https://storage.azure.com/.default при запросе токена.
Пример. Проверка подлинности и чтение данных (Python)
from azure.identity import ClientSecretCredential
from azure.storage.filedatalake import DataLakeServiceClient
tenant_id = "<your-tenant-id>"
client_id = "<your-service-principal-client-id>"
client_secret = "<your-service-principal-secret>"
credential = ClientSecretCredential(tenant_id, client_id, client_secret)
service_client = DataLakeServiceClient(
account_url="https://onelake.dfs.fabric.microsoft.com",
credential=credential
)
# Access a specific item in a workspace
file_system_client = service_client.get_file_system_client("<workspace-id>")
directory_client = file_system_client.get_directory_client("<item-id>/Tables/dbo/Customers")
# List and read Delta parquet files
for path in directory_client.get_paths():
if path.name.endswith(".parquet"):
file_client = file_system_client.get_file_client(path.name)
downloaded = file_client.download_file()
data = downloaded.readall()
# Process the parquet data with your engine
Дополнительные сведения об API OneLake см. в статье OneLake access with API.
Шаг 3. Получение эффективного доступа пользователя
После чтения необработанных данных подсистема должна определить, что может видеть запрашивающий пользователь. Вызовите API получения авторизованного доступа для субъекта, чтобы определить эффективный доступ пользователя к элементу.
Конечная точка API
GET https://onelake.dfs.fabric.microsoft.com/v1.0/workspaces/{workspaceId}/artifacts/{artifactId}/securityPolicy/principalAccess
Текст запроса
{
"aadObjectId": "<end-user-entra-object-id>",
"inputPath": "Tables",
"maxResults": 500 //optional, default is 500
}
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| aadObjectId | струна | Да | Идентификатор объекта Microsoft Entra конечного пользователя, доступ к которому требуется проверить. |
| путь ввода | струна | Да |
Tables или Files. Возвращает доступ пользователя для указанного раздела элемента. Для большинства обработчиков запросов будет использоваться TablesinputPath. |
| токен продолжения | струна | Нет | Используется для получения следующих результатов, когда объем набора результатов превышает maxResults. |
| максимальные результаты | целое число | Нет | Максимальное количество элементов на страницу. Значение по умолчанию — 500. |
Пример ответа (только RLS)
{
"identityETag": "3fc4dc476ded773e4cf43936190bf20fa9480a077b25edc0b4bbe247112542f6",
"metadataETag": "\"eyJhciI6IlwiMHg4R...\"",
"value": [
{
"path": "Tables/dbo/Customers",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Customers] WHERE [customerId] = '123'",
"effect": "Permit"
},
{
"path": "Tables/dbo/Employees",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Employees] WHERE [address] = '123'",
"effect": "Permit"
},
{
"path": "Tables/dbo/EmployeeTerritories",
"access": ["Read"],
"effect": "Permit"
}
]
}
Пример ответа (RLS и CLS)
При настройке безопасности на уровне столбцов в таблице ответ содержит columns массив, который содержит только столбцы, к которым пользователь может получить доступ. Столбцы, не присутствующие в этом массиве, скрыты от пользователя.
{
"identityETag": "79372bc169b00882d9abec3d404032131e96bc406e15c6766514723021e153eb",
"metadataETag": "\"eyJhciI6IlwiMHg4R...\"",
"value": [
{
"path": "Tables/dbo/Customers",
"access": ["Read"],
"columns": [
{
"name": "address",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "city",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "contactTitle",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "country",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "fax",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "phone",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "postalCode",
"columnEffect": "Permit",
"columnAction": ["Read"]
},
{
"name": "region",
"columnEffect": "Permit",
"columnAction": ["Read"]
}
],
"rows": "SELECT * FROM [dbo].[Customers] WHERE [customerID] = 'ALFKI'",
"effect": "Permit"
},
{
"path": "Tables/dbo/Employees",
"access": ["Read"],
"rows": "SELECT * FROM [dbo].[Employees] WHERE [address] = '123'",
"effect": "Permit"
}
]
}
Общие сведения об ответе
Ответ содержит массив PrincipalAccessEntry объектов, каждый из которых представляет таблицу, к ней у пользователя есть доступ. Таблицы, не присутствующих в ответе, недоступны пользователю.
| Поле | Тип | Описание |
|---|---|---|
path |
струна | Путь к таблице, к которому пользователь может получить доступ, например Tables/dbo/Customers. |
access |
строка[] | Массив предоставленных типов доступа. Поддерживается только Read. |
columns |
object[] | Массив объектов столбцов, к который пользователь может получить доступ. Каждый объект содержит name (имя столбца), columnEffect (Permit) и columnAction (["Read"]). Если это поле отсутствует, clS не применяется и все столбцы разрешены. Если они присутствуют, необходимо вернуть только перечисленные столбцы. |
rows |
струна | Инструкция T-SQL SELECT , представляющая фильтр безопасности на уровне строк. Пользователю следует вернуть только строки, соответствующие этому предикату. Если это поле отсутствует, RLS не применяется, и все строки разрешены. |
effect |
струна | Тип эффекта. В настоящее время всегда Permit. |
Это важно
Поле rows содержит выражение T-SQL, которое модуль должен анализировать и применять в качестве предиката фильтра. Выражение использует SELECT * FROM [schema].[table] WHERE ... формат. Движок должен извлечь WHERE условие и применить его к возвращаемым данным.
ETags для кэширования
Ответ включает два значения ETag, которые обеспечивают эффективное кэширование:
-
identityETag: представляет текущее состояние удостоверений пользователя и членства в группах. Кэшируйте результат доступа пользователя и повторно используйте его до тех пор, пока этот ETag не изменится. -
metadataETag: представляет текущее состояние конфигурации безопасности элемента. Кэшируйте метаданные ролей и повторно используйте их до тех пор, пока этот ETag не изменится.
Используйте эти ETags с заголовком If-None-Match запроса, чтобы избежать повторного получения неизмененных данных. Это повышает производительность для кэшей с несколькими пользователями.
Пример: Получение эффективного доступа (Python)
import requests
# Get a token for the OneLake DFS endpoint
token = credential.get_token("https://storage.azure.com/.default").token
workspace_id = "<workspace-id>"
artifact_id = "<artifact-id>"
user_object_id = "<end-user-entra-object-id>"
url = (
f"https://onelake.dfs.fabric.microsoft.com/v1.0/"
f"workspaces/{workspace_id}/artifacts/{artifact_id}/"
f"securityPolicy/principalAccess"
)
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
body = {
"aadObjectId": user_object_id,
"inputPath": "Tables"
}
response = requests.get(url, headers=headers, json=body)
access_data = response.json()
# The response contains the user's effective access
for entry in access_data["value"]:
print(f"Table: {entry['path']}, Access: {entry['access']}")
if "columns" in entry:
col_names = [col["name"] for col in entry["columns"]]
print(f" CLS permitted columns: {col_names}")
if "rows" in entry:
print(f" RLS filter: {entry['rows']}")
Шаг 4. Применение фильтров безопасности
После получения эффективного доступа пользователя ваш движок должен применить политики безопасности к данным перед возвратом результатов. Этот шаг является критически важным— ваш движок отвечает за надлежащее применение политик.
Фильтрация на уровне таблицы
Возвращает только данные из таблиц, которые отображаются в ответе principalAccess . Если таблица не указана, пользователь не имеет доступа к ней, и данные не должны быть возвращены.
# Build a set of accessible tables for the user
accessible_tables = {entry["path"] for entry in access_data["value"]}
# Before returning query results, verify the table is accessible
def is_table_accessible(table_path: str) -> bool:
return table_path in accessible_tables
Фильтрация безопасности на уровне строк
rows Если поле присутствует в записи доступа, подсистема должна проанализировать предикат T-SQL и применить его в качестве фильтра к данным таблицы. Значение rows — это SELECT оператор с WHERE условием, определяющим, какие строки может видеть пользователь.
Это важно
Если ваш обработчик не может анализировать инструкции SQL, то запросы к таблицам со свойством rows, которое не допускает значения NULL, должны завершаться ошибкой и не возвращать данные. Это гарантирует, что пользователи получают доступ только к тому, что им разрешено видеть.
Например, следующий фильтр RLS:
SELECT * FROM [dbo].[Customers] WHERE [customerId] = '123' UNION SELECT * FROM [dbo].[Customers] WHERE [customerID] = 'ALFKI'
Подсистема должна извлечь предикаты и применить их для фильтрации данных:
import sqlparse
def extract_rls_predicates(rls_expression: str) -> list:
"""
Parse the RLS T-SQL expression and extract WHERE clause predicates.
The expression may contain UNION of multiple SELECT statements.
"""
predicates = []
statements = rls_expression.split(" UNION ")
for stmt in statements:
parsed = sqlparse.parse(stmt)[0]
where_seen = False
where_clause = []
for token in parsed.tokens:
if where_seen:
where_clause.append(str(token).strip())
if token.ttype is sqlparse.tokens.Keyword and token.value.upper() == "WHERE":
where_seen = True
if where_clause:
predicates.append(" ".join(where_clause))
return predicates
def apply_rls_filter(dataframe, access_entry: dict):
"""Apply RLS filtering to a dataframe based on the access entry."""
if "rows" not in access_entry:
return dataframe # No RLS, return all rows
predicates = extract_rls_predicates(access_entry["rows"])
# Combine predicates with OR (UNION semantic)
combined_filter = " OR ".join(f"({p})" for p in predicates)
return dataframe.filter(combined_filter)
Это важно
rows Если поле отсутствует в записи доступа, RLS не применяется к этой таблице, а все строки должны быть возвращены. Когда поле присутствует, ваш движок должен фильтровать данные. Возврат нефильтрованных данных для таблицы с RLS является нарушением безопасности.
Фильтрация безопасности на уровне столбцов
Если CLS настроен на таблице, principalAccess ответ содержит columns массив, который явно перечисляет столбцы, к которым пользователь имеет доступ. Каждый объект столбца содержит следующее:
| Недвижимость | Тип | Описание |
|---|---|---|
name |
струна | Имя столбца (с учетом регистра). |
columnEffect |
струна | Эффект, примененный к столбцу. В настоящее время всегда Permit. |
columnAction |
строка[] | Действия, разрешенные в столбце. Поддерживается только Read. |
columns Если поле отсутствует в записи доступа, clS не применяется, а все столбцы в таблице разрешены.
columns Если поле присутствует, подсистема должна возвращать только перечисленные столбцы.
def get_permitted_columns(access_entry: dict) -> list | None:
"""
Return the list of permitted column names for a table.
Returns None if no CLS applies (all columns are permitted).
"""
if "columns" not in access_entry:
return None # No CLS, all columns are permitted
return [
col["name"]
for col in access_entry["columns"]
if col.get("columnEffect") == "Permit"
and "Read" in col.get("columnAction", [])
]
def apply_cls_filter(dataframe, access_entry: dict):
"""Apply CLS filtering to a dataframe based on the access entry."""
permitted_columns = get_permitted_columns(access_entry)
if permitted_columns is None:
return dataframe # No CLS, return all columns
# Only keep columns that are in the permitted list
return dataframe.select(permitted_columns)
Это важно
Когда поле columns отсутствует в записи доступа, CLS не применяется, и все столбцы должны быть возвращены. При наличии поля движок должен возвращать только перечисленные столбцы. Возврат скрытых столбцов является нарушением безопасности.
Обработка таблиц без доступа
Если пользователь запрашивает таблицу, которая не отображается в ответе principalAccess , обработчик должен запретить доступ. Не возвращайтесь к возврату нефильтрованных данных.
def query_table(table_path: str, user_access: dict):
"""Query a table with OneLake security enforcement."""
# Find the user's access entry for this table
entry = next(
(e for e in user_access["value"] if e["path"] == table_path),
None
)
if entry is None:
raise PermissionError(
f"Access denied: user doesn't have permission to access {table_path}"
)
# Read the data from OneLake
data = read_table_from_onelake(table_path)
# Apply column-level security
data = apply_cls_filter(data, entry)
# Apply row-level security
data = apply_rls_filter(data, entry)
return data
Шаг 5. Обработка кэширования и обнаружения изменений
Для интеграций промышленного уровня, особенно для механизмов с кэшами данных для нескольких пользователей, необходимо обрабатывать изменения в политике безопасности и членстве пользователей в группах.
Метаданные безопасности кэша
Используйте значения identityETag и metadataETag из ответа principalAccess, чтобы определить, когда информация о безопасности из кэша устарела.
-
identityETag: изменяется при обновлении сведений о членстве пользователя в группах или свойств его удостоверения. Кэшируйте эффективный доступ пользователя, в который включен(userId, identityETag)ключ. -
metadataETag: изменяется при обновлении ролей или политик безопасности OneLake в элементе. Определения ролей кэша, ключ которых сделан на основе(artifactId, metadataETag).
Опрос изменений
Периодически опрашивать principalAccess API для обнаружения изменений. API следует провести опрос перед выполнением запроса, чтобы убедиться, что ничего не изменилось, а не напрямую обслуживать результаты из кэша. Используйте заголовок If-None-Match с ранее полученным ETag, чтобы сократить использование пропускной способности.
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"If-None-Match": f'"{cached_etag}"'
}
response = requests.get(url, headers=headers, json=body)
if response.status_code == 304:
# Security hasn't changed, use cached data
pass
elif response.status_code == 200:
# Security has changed, update cache
new_access_data = response.json()
update_cache(user_id, new_access_data)
Рассмотрение задержек
- Распространение изменений в определениях ролей безопасности OneLake занимает примерно 5 минут.
- Изменения членства в группах пользователей в Microsoft Entra ID занимают около 1 часа, чтобы отразиться в OneLake.
- Некоторые подсистемы Fabric имеют собственный уровень кэширования, поэтому может потребоваться дополнительное время.
Спроектируйте интервал опроса и срок жизни кэша соответствующим образом. Рекомендуемый подход заключается в том, чтобы опрашивать каждые 5 минут изменения в метаданных безопасности и обновлять пользовательский доступ при каждом запросе или с более коротким интервалом.
Шаг 6. Обработка разбиения на страницы
principalAccess API поддерживает разбиение на страницы для элементов со многими таблицами. Если ответ содержит больше записей, чем maxResults, ответ содержит .continuationToken
all_entries = []
continuation_token = None
while True:
body = {
"aadObjectId": user_object_id,
"inputPath": "Tables",
"maxResults": 500
}
if continuation_token:
body["continuationToken"] = continuation_token
response = requests.get(url, headers=headers, json=body)
data = response.json()
all_entries.extend(data["value"])
# Check for continuation token in response
continuation_token = data.get("continuationToken")
if not continuation_token:
break
Обработка ошибок
Обработка следующих сценариев ошибок в интеграции:
| Состояние HTTP | Код ошибки | Описание | Рекомендуемое действие |
|---|---|---|---|
| 200 | - | Успех. | Обработайте ответ. |
| 404 | Элемент не найден | Рабочая область или объект не существует, или идентификатор механизма не имеет доступа. | Проверьте идентификатор рабочей области и идентификатор артефакта. Убедитесь, что идентификатор обработчика имеет доступ к участнику рабочей области. |
| 412 | Ошибка предварительного условия | Указанный ETag не соответствует текущему ресурсу ETag If-Match . |
Перезапросите ресурс без заголовка If-Match, чтобы получить последнюю версию ETag. |
| 429 | - | Превышено ограничение скорости. | Дождитесь длительности, указанной в заголовке Retry-After , прежде чем повторить попытку. |
Рекомендации по обеспечению безопасности
Чтобы обеспечить безопасную интеграцию, следуйте приведенным ниже рекомендациям.
- Защитите идентификационные данные движка. Субъект-служба имеет повышенный доступ к данным в OneLake. Безопасное хранение учетных данных с помощью таких служб, как Azure Key Vault.
- Не предоставляйте необработанные данные конечным пользователям. Всегда применяйте фильтры безопасности, возвращаемые
principalAccessAPI, прежде чем возвращать все данные. Пропуск принудительного применения является нарушением безопасности. - Тщательно проверьте предикаты RLS. Синтаксический анализ и точное применение предикатов предложения T-SQL
WHERE. Неправильный анализ может привести к утечке данных. Если возникает ошибка синтаксического анализа или неуверенное сопоставление синтаксиса, завершите запрос с ошибкой синтаксического анализа RLS, а не показывайте пользователю частичные или небезопасные результаты. - Обработать отсутствующие таблицы как отказ в доступе. Если таблица отсутствует в ответе API, пользователь не имеет доступа. Никогда не возвращайтесь к нефильтрованным данным, безопасность OneLake всегда использует запрет по умолчанию.
- Аудит доступа. Журнал действий пользователей, обращающихся к таблицам, и какие политики безопасности применялись для соответствия требованиям и устранения неполадок.
- Опрос изменений безопасности. Используйте ETags для быстрого обнаружения изменений и обновления кэшированных политик.
Ограничения
-
principalAccessAPI находится в предварительной версии и может изменяться на основе отзывов. - Сегодня поддерживаются только
Readтип доступа иPermitэффект. - Идентификационные данные двигателя должны иметь неограниченный доступ к корневой системе. Если RLS или CLS применяются к идентификатору движка, вызовы API не проходят успешно.
- Предикаты RLS используют синтаксис T-SQL. Ваш движок отвечает за синтаксический анализ и правильное применение предикатов.
- Изменения политики безопасности занимают около 5 минут для распространения. Изменения членства в группах пользователей занимают около 1 часа.
Связанный контент
- Получите авторизованный доступ к основному API
- Общие сведения об интеграции безопасности OneLake
- Справочник по интеграции безопасности OneLake
- модель контроля доступа безопасности OneLake
- Безопасность на уровне строк в OneLake
- Безопасность на уровне столбцов в OneLake
- Начните работу с безопасностью OneLake