Включение детального контроля доступа с RBAC на уровне строк в Milvus
Почему контроль доступа важен в современных системах данных
Контроль доступа — одна из самых актуальных задач в современном управлении данными, особенно для предприятий. По мере роста организаций, особенно в средах с множеством отделов и ролей, критически важны как надежная безопасность, так и беспрепятственный доступ. Давайте рассмотрим два примера, где контроль доступа особенно важен.
Здравоохранение: баланс между конфиденциальностью и сотрудничеством
В секторе здравоохранения организации должны защищать конфиденциальность пациентов, одновременно способствуя сотрудничеству между медицинскими специалистами. Представьте врача, которому нужен полный доступ к медицинским записям пациента, чтобы поставить точный диагноз и составить план лечения. Однако этот врач не должен иметь возможности получать доступ к записям пациентов, которых он не лечит. Чтобы удовлетворить эту потребность, необходим детализированный контроль доступа, гарантирующий, что только уполномоченный медицинский персонал может просматривать конфиденциальные данные пациентов. Такой уровень контроля помогает организациям соблюдать строгие нормативные требования, такие как HIPAA, одновременно защищая конфиденциальность.
Финансы: защита конфиденциальных данных
Финансовая отрасль сталкивается с аналогичными проблемами, когда речь идет о контроле доступа. Банки и финансовые учреждения обрабатывают огромные объемы конфиденциальных данных — данные счетов, истории транзакций, кредитные рейтинги и т. д. Эти данные часто преобразуются в векторы и хранятся в векторной базе данных, такой как Milvus, для выявления мошенничества, анализа рисков и персонализированного клиентского опыта. Без надлежащих механизмов контроля доступа конфиденциальные данные могут быть раскрыты неавторизованным сторонам, что приведет к значительным финансовым и юридическим последствиям.
Детализированные средства контроля, такие как разрешения на уровне строк, позволяют учреждениям ограничивать доступ для конкретных пользователей — например, клиентский менеджер может получать доступ только к данным счетов своих клиентов. Даже более широкий доступ, необходимый командам по управлению рисками, может тщательно отслеживаться и ограничиваться, чтобы предотвратить злоупотребления.
RBAC на уровне строк в Milvus: решение для детализированного контроля доступа
Контроль доступа на основе ролей (RBAC) — это модель безопасности, в которой доступ к ресурсам предоставляется на основе роли пользователя в организации. Роли определяют разрешения, а пользователи наследуют эти разрешения, обеспечивая безопасное и эффективное управление правами доступа.
Milvus — это высокопроизводительная векторная база данных с открытым исходным кодом, созданная для масштабирования. Она идеально подходит для создания AI-приложений на основе моделей, таких как retrieval augmented generation (RAG), системы семантического поиска, рекомендательные системы и чат-боты. Milvus предлагает решение для детализированного RBAC на основе модели разрешений, которая использует bitmap-индексацию для обеспечения контроля доступа на уровне строк. Эта функция позволяет управлять доступом к конкретным ресурсам Milvus и разрешениями на основе пользовательских ролей и привилегий. В настоящее время RBAC в Milvus доступен только в Python и Java.
RBAC в Milvus предлагает несколько преимуществ:
Скорость и эффективность: Он позволяет быстро запрашивать разрешения в больших наборах данных.
Гибкость: Он адаптируется по мере изменения ролей и обязанностей, обеспечивая актуальность разрешений.
Основы RBAC
Роли и разрешения
Роль: Представляет роль пользователя в системе, при этом каждой роли назначается определенный набор разрешений.
Разрешение: Определяет права доступа к отдельным строкам в подключении к данным (таблице) в Milvus, например возможность читать, записывать или удалять конкретные данные.
Построение bitmap-индекса
Bitmap-индексы являются основой этого механизма контроля доступа:
Каждая роль связана с bitmap, который указывает строки, к которым она может получить доступ.
Длина bitmap соответствует количеству строк в подключении:
1 в позиции означает, что роль имеет доступ к этой строке.
0 означает отсутствие доступа.
Использование Bitmap Index
Предоставление разрешений: Чтобы предоставить роли доступ к строке, установите соответствующий бит в bitmap роли в значение 1.
Проверка разрешений: Чтобы проверить, может ли роль получить доступ к конкретной строке, просто проверьте, равен ли соответствующий бит в bitmap 1.
Допустим, у нас есть соединение (таблица), Collection A, которое хранит корпоративные знания. Каждая строка представляет контент, идентифицируемый по doc_id, и связанную с ним базу знаний, kb_id.
| ID строки | PK | Данные | doc_id | kb_id | Роль |
|---|---|---|---|---|---|
| 1 | 0 | Data A | 1 | 1 | role1 |
| 2 | 1 | Data B | 1 | 1 | role1 |
| 3 | 2 | Data C | 2 | 1 | role1 |
| 4 | 3 | Data D | 2 | 1 | role1 |
| 5 | 4 | Data E | 3 | 2 | role2 |
Роли определены следующим образом:
Роль 1: Может получать доступ к строкам 1, 2, 3 и 4 (
kb_id = 1).Роль 2: Может получать доступ к строке 5 (
kb_id = 2).
Операции запросов
Когда пользователь запрашивает данные, bitmap его роли объединяется с условиями запроса, чтобы отфильтровать строки, к которым у него есть доступ. Например, если пользователь с Ролью 1 запрашивает "все данные," его bitmap 11110 вернет строки 1–4 (Data A, Data B, Data C и Data D).
Обновление разрешений
Чтобы добавить или удалить доступ для роли, просто обновите соответствующий бит в bitmap роли. Например, установка бита в 1 предоставляет доступ, а установка его в 0 отзывает его.
Преимущества и соображения
Эффективность: Операции с bitmap быстры и хорошо подходят для управления разрешениями в больших наборах данных.
Низкие накладные расходы на хранение: Bitmaps потребляют минимальный объем хранилища даже для наборов данных с миллионами строк.
Гибкость: Bitmap indexes поддерживают сложные условия запросов и их комбинации, что делает их хорошо адаптируемыми к различным сценариям использования.
Демонстрация RBAC на уровне строк в Milvus
В этом разделе мы продемонстрируем, как Milvus управляет доступом к различным базам знаний крупного предприятия.
Сценарий использования: корпоративный RAG с несколькими базами знаний
В крупном предприятии разные отделы часто поддерживают отдельные базы знаний — некоторые публичные, другие конфиденциальные — для своего приложения RAG, работающего на Milvus. Чтобы эффективно управлять разрешениями для этих баз знаний, мы реализуем контроль доступа на основе ролей (RBAC) на уровне сущностей или документов. Например, роль суперадминистратора (admin) может контролировать доступ, а дополнительные роли для конкретных бизнес-подразделений, таких как CEO, finance, sales и developer, будут иметь доступ к разным наборам данных.
Рисунок: Контроль доступа для разных ролей в крупном предприятии
Определение столбцов разрешений
Для управления доступом мы храним данные разрешений в столбце массива внутри Milvus. Этот столбец будет определять, какие роли имеют доступ к каким строкам данных. field_name для этого столбца разрешений можно настраивать, а размер массива можно изменять в зависимости от потребностей пользователя. Затем для этого столбца создается индекс BITMAP, что делает проверки разрешений эффективными.
Ниже показано, как эта настройка выполняется в коде:
# 1. Set up a Milvus client
client = MilvusClient(
uri=CLUSTER_ENDPOINT
)
# 2. Create a collection
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=False,
)
# 3. define schema
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="data", datatype=DataType.VARCHAR, max_length=100)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=128)
# 4. add security column
schema.add_field(field_name="security_group", datatype=DataType.ARRAY,
element_type=DataType.VARCHAR, max_capacity=10, max_length=100)
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="IVF_FLAT",
metric_type="L2",
params={"nlist": 1024}
)
# 5. create bitmap index for security column
index_params.add_index(field_name="security_group",
index_type="BITMAP")
# 6. create collection
client.create_collection(
collection_name="test_collection",
schema=schema,
index_params=index_params
)
Права на запись
При вставке новых данных вы назначаете разрешения, указывая, какие роли могут получать доступ к каждой строке. Это можно сделать, записав соответствующую роль (или роли) в столбец security_group.
Вот пример того, как это работает:
data =[]
data.append({
"id": random.randint(0, 100000),
"vector": [ random.uniform(-1, 1) for _ in range(128) ],
"data": "data" + str(random.randint(0,100000)),
# ceo role can read
"security_group": ["ceo"]
})
data.append({
"id": random.randint(0, 100000),
"vector": [ random.uniform(-1, 1) for _ in range(128) ],
"data": "data" + str(random.randint(0,100000)),
# finance role can read
"security_group": ["finance"]
})
data.append({
"id": random.randint(0, 100000),
"vector": [ random.uniform(-1, 1) for _ in range(128) ],
"data": "data" + str(random.randint(0,100000)),
# both sales and developer can read
"security_group": ["sales", "finance"]
})
res = client.insert(collection_name="test_collection", data=data)
Разрешение на запрос
При выполнении операций поиска или запроса важно ограничивать результаты так, чтобы отображались только данные, к которым имеет доступ конкретная роль пользователя. Данные вне разрешенных ролей пользователя будут скрыты из результатов запроса. Вот как это можно сделать:
Запрос данных на основе разрешений ролей
В приведенных ниже примерах мы используем функцию array_contains() для фильтрации данных на основе разрешений, специфичных для ролей. Каждый запрос получает только те данные, которые данная роль уполномочена видеть.
res = client.query(
collection_name="test_collection",
# Query data visible only to the CEO role
filter='array_contains(security_group, "ceo")',
output_fields=["id", "data", "security_group"],
)
print("ceo role read:")
print(res)
res = client.query(
collection_name="test_collection",
# Query data visible only to the Sales role
filter='array_contains(security_group, "sales")',
output_fields=["id", "data", "security_group"],
)
print("sales role read:")
print(res)
res = client.query(
collection_name="test_collection",
# Query data visible only to the Developer role
filter='array_contains(security_group, "develop")',
output_fields=["id", "data", "security_group"],
)
print("developer role read:")
print(res)
res = client.query(
collection_name="test_collection",
# Query data visible to either the Developer or CEO roles
filter='array_contains_any(security_group, ["develop", "ceo"])',
output_fields=["id", "data", "security_group"],
)
print("developer or ceo role read:")
print(res)
Вот пример того, как будет выглядеть вывод:
чтение роли ceo:
data: [
"{'security_group': ['ceo'], 'id': 3443, 'data': 'data35077'}",
"{'security_group': ['ceo'], 'id': 12181, 'data': 'data99090'}",
"{'security_group': ['ceo'], 'id': 16551, 'data': 'data74619'}",
"{'security_group': ['ceo'], 'id': 24466, 'data': 'data1373'}", ...
чтение роли sales:
data: [
"{'data': 'data75305', 'security_group': ['sales'], 'id': 9122}",
"{'data': 'data61054', 'security_group': ['sales'], 'id': 20087}",
"{'data': 'data47948', 'security_group': ['sales', 'develop'], 'id': 21726}",
"{'data': 'data8596', 'security_group': ['sales'], 'id': 40090}", ...
чтение роли developer:
data: [
"{'data': 'data1515', 'security_group': ['develop'], 'id': 6429}",
"{'data': 'data47031', 'security_group': ['develop'], 'id': 10953}",
"{'data': 'data47948', 'security_group': ['sales', 'develop'], 'id': 21726}",
"{'data': 'data86894', 'security_group': ['develop'], 'id': 56980}"], ...
чтение роли developer или ceo:
data: [
"{'data': 'data35077', 'security_group': ['ceo'], 'id': 3443}",
"{'data': 'data1515', 'security_group': ['develop'], 'id': 6429}",
"{'data': 'data47031', 'security_group': ['develop'], 'id': 10953}",
"{'data': 'data99090', 'security_group': ['ceo'], 'id': 12181}", ...
Этот подход гарантирует, что каждая роль видит именно те данные, к просмотру которых она авторизована, при этом скрывая любые неавторизованные данные. Вы также можете помещать несколько ролей в массив security_group, что обеспечивает гибкое и эффективное управление разрешениями.
Пользовательские фильтры с доступом на основе ролей
В некоторых случаях пользователям может потребоваться применять пользовательские фильтры при запросе данных. Эти фильтры можно комбинировать с доступом на основе ролей для уточнения поиска. Применяя контроль доступа на основе ролей вместе с условиями пользовательских фильтров, мы можем гарантировать, что пользователи получают только те данные, которые им разрешено видеть как на основе роли, так и на основе конкретных критериев запроса.
Например:
res = client.query(
collection_name="test_collection",
# Роль Sales запрашивает данные с фильтром "pk in [1, 3, 5]"
filter='pk in [1, 3, 5] && array_contains(security_group, "sales")',
output_fields=["id", "data", "security_group"],
)
res = client.query(
collection_name="test_collection",
# Роль Developer запрашивает данные с фильтром "pk > 10"
filter='pk > 10 && array_contains(security_group, "develop")',
output_fields=["id", "data", "security_group"],
)
В этих примерах запросы не только проверяют разрешения на основе ролей, но и применяют дополнительные фильтры (например, pk in [1, 3, 5] или pk > 10), чтобы сузить результаты на основе конкретных критериев. Эта гибкость позволяет пользователям создавать высокоточные запросы, сохраняя строгий контроль над доступом к данным.
Обновление разрешений
Иногда необходимо изменить разрешения — будь то предоставление доступа определенной роли к конкретной строке данных или удаление такого доступа. Milvus упрощает этот процесс с помощью своего API upsert, который позволяет обновлять разрешения, связанные со строкой данных.
Давайте рассмотрим, как можно использовать этот API для изменения разрешений для конкретной строки.
Пример: обновление разрешений для строки данных
Чтобы обновить разрешения для строки, вы просто изменяете поле security_group. В этом примере мы добавим роль "sales" к строке, которая ранее была доступна только роли "finance".
upsert_row_update = {
"id": 101,
"vector": upsert_vector,
"data": upsert_data,
# обновить роль
"security_group": ["finance", "sales"]
}
res = client.upsert(
collection_name="test_collection",
data=upsert_row_update)
Результат:
До upsert строка с pk = 101 выглядела так:
pk = 101:
data: [" {'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance'],"]
после upsert
data: ["{'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance', 'sales']}"]
Используя столбец массива security_group и фильтрацию по bitmap-индексу, мы создали надежную основу для контроля доступа на чтение на уровне строк, что позволяет нам эффективно управлять разрешениями во время запросов. Этот метод обеспечивает высокую производительность и детальный контроль над правами доступа. Однако он требует более активного участия администраторов, которым необходимо тщательно управлять разрешениями при вставке или обновлении данных и обеспечивать продуманную стратегию разрешений при создании таблиц.
Заключение
Реализация детализированного контроля доступа является критически важным компонентом современного управления данными, особенно для отраслей, работающих с конфиденциальной информацией, таких как здравоохранение и финансы. Milvus предлагает RBAC на уровне строк (Role-Based Access Control), что является надежным решением для точного и эффективного управления доступом к данным.
Этот подход не только повышает безопасность, но и обеспечивает гибкость для меняющихся потребностей бизнеса, гарантируя, что политики доступа могут адаптироваться по мере изменения ролей и обязанностей. Благодаря своим мощным инструментам и гибкой модели разрешений Milvus позволяет организациям создавать высокозащищенные масштабируемые системы данных, которые соответствуют нормативным требованиям и при этом обеспечивают беспрепятственный доступ нужным людям.
Для еще более динамичного управления разрешениями и наследования Zilliz Cloud, полностью управляемый сервис Milvus, предлагает еще более детализированные функции разрешений. Эти улучшения не только повысят эффективность администрирования, но и обеспечат большую гибкость, упрощая выполнение более широкого спектра бизнес-требований. Для получения дополнительной информации о RBAC в Zilliz Cloud ознакомьтесь с его документацией.
Дополнительные материалы
Читать далее

Introducing Functions and Model Inference on Zilliz Cloud: Automatic Embedding and Reranking with Hosted Models
Zilliz Cloud Functions auto-generate embeddings via OpenAI, Voyage AI, Cohere, or Zilliz Hosted Models. Built-in reranking — just insert text and search.

Vector Databases vs. Time Series Databases
Use a vector database for similarity search and semantic relationships; use a time series database for tracking value changes over time.

AI Integration in Video Surveillance Tools: Transforming the Industry with Vector Databases
Discover how AI and vector databases are revolutionizing video surveillance with real-time analysis, faster threat detection, and intelligent search capabilities for enhanced security.



