Habilitando o Controle de Acesso Granular com RBAC em Nível de Linha do Milvus
Por que o Controle de Acesso é Importante em Sistemas de Dados Modernos
Controle de acesso é um dos desafios mais urgentes na gestão moderna de dados, especialmente para empresas. À medida que as organizações crescem, particularmente em ambientes com vários departamentos e funções, tanto uma segurança robusta quanto um acesso fluido são essenciais. Vamos analisar dois exemplos em que o controle de acesso é especialmente importante.
Saúde: Equilibrando Privacidade e Colaboração
No setor de saúde, as organizações devem proteger a privacidade dos pacientes enquanto promovem a colaboração entre profissionais médicos. Imagine um médico que precisa de acesso total aos registros médicos de um paciente para fazer um diagnóstico e um plano de tratamento precisos. No entanto, esse médico não deveria poder acessar registros de pacientes que ele não está tratando. Para atender a essa necessidade, o controle de acesso granular é essencial, garantindo que apenas a equipe médica autorizada possa visualizar dados sensíveis de pacientes. Esse nível de controle ajuda as organizações a cumprir regulamentações rigorosas como a HIPAA, ao mesmo tempo em que protege a privacidade.
Finanças: Protegendo Dados Sensíveis
O setor financeiro enfrenta desafios semelhantes quando se trata de controle de acesso. Bancos e instituições financeiras lidam com enormes quantidades de dados sensíveis—detalhes de contas, históricos de transações, pontuações de crédito etc. Esses dados são frequentemente convertidos em vetores e armazenados em um banco de dados vetorial como o Milvus para detecção de fraudes, análise de riscos e experiências personalizadas para clientes. Sem controles de acesso adequados, dados sensíveis poderiam ser expostos a partes não autorizadas, levando a consequências financeiras e legais significativas.
Controles granulares, como permissões em nível de linha, permitem que as instituições restrinjam o acesso a usuários específicos—por exemplo, um gerente de clientes pode acessar apenas os dados das contas de seus próprios clientes. Mesmo um acesso mais amplo, exigido por equipes de gestão de riscos, pode ser cuidadosamente monitorado e restrito para evitar uso indevido.
RBAC em nível de linha do Milvus: uma Solução de Controle de Acesso Granular
Controle de Acesso Baseado em Função (RBAC) é um modelo de segurança em que o acesso a recursos é concedido com base na função de um usuário dentro de uma organização. As funções definem permissões, e os usuários herdam essas permissões, garantindo uma gestão segura e eficiente dos direitos de acesso.
Milvus é um banco de dados vetorial de código aberto e alto desempenho criado para escala. Ele é perfeito para construir aplicações de IA de modelo, como geração aumentada por recuperação (RAG), mecanismos de busca semântica, sistemas de recomendação e chatbots. O Milvus oferece uma solução RBAC granular baseada em um modelo de permissões que usa indexação bitmap para possibilitar controle de acesso em nível de linha. Esse recurso permite controlar o acesso a recursos e permissões específicos do Milvus com base em funções e privilégios de usuários. Atualmente, o RBAC do Milvus está disponível apenas em Python e Java.
O RBAC do Milvus oferece várias vantagens:
Velocidade e Eficiência: Permite a consulta rápida de permissões em grandes conjuntos de dados.
Flexibilidade: Adapta-se à medida que funções e responsabilidades evoluem, garantindo que as permissões permaneçam atualizadas.
Fundamentos do RBAC
Funções e Permissões
Função: Representa a função de um usuário no sistema, com cada função atribuída a um conjunto específico de permissões.
Permissão: Especifica direitos de acesso a linhas individuais em uma conexão de dados (tabela) dentro do Milvus, como a capacidade de ler, gravar ou excluir dados específicos.
Construção de índice bitmap
Índices bitmap são a base deste mecanismo de controle de acesso:
Cada função está associada a um bitmap que indica as linhas que ela pode acessar.
O comprimento do bitmap corresponde ao número de linhas na conexão:
Um 1 em uma posição significa que a função tem acesso a essa linha.
Um 0 significa sem acesso.
Uso de Índice Bitmap
Concessão de Permissões: Para dar a uma função acesso a uma linha, defina o bit correspondente no bitmap da função como 1.
Verificação de Permissões: Para verificar se uma função pode acessar uma linha específica, basta verificar se o bit correspondente no bitmap é 1.
Digamos que temos uma conexão (tabela), Collection A, que armazena conhecimento empresarial. Cada linha representa conteúdo identificado por doc_id e sua base de conhecimento associada, kb_id.
| ID da Linha | PK | Dados | doc_id | kb_id | Função |
|---|---|---|---|---|---|
| 1 | 0 | Dados A | 1 | 1 | role1 |
| 2 | 1 | Dados B | 1 | 1 | role1 |
| 3 | 2 | Dados C | 2 | 1 | role1 |
| 4 | 3 | Dados D | 2 | 1 | role1 |
| 5 | 4 | Dados E | 3 | 2 | role2 |
As funções são definidas da seguinte forma:
Função 1: Pode acessar as linhas 1, 2, 3 e 4 (
kb_id = 1).Função 2: Pode acessar a linha 5 (
kb_id = 2).
Operações de Consulta
Quando um usuário consulta os dados, o bitmap da sua função é combinado com as condições da consulta para filtrar as linhas que ele está autorizado a acessar. Por exemplo, se um usuário com Função 1 consulta "todos os dados," seu bitmap 11110 retornará as linhas 1–4 (Dados A, Dados B, Dados C e Dados D).
Atualização de Permissões
Para adicionar ou remover acesso para uma função, basta atualizar o bit correspondente no bitmap da função. Por exemplo, definir um bit como 1 concede acesso, enquanto defini-lo como 0 revoga o acesso.
Vantagens e Considerações
Eficiência: Operações de bitmap são rápidas e bem adequadas para gerenciar permissões em grandes conjuntos de dados.
Baixa Sobrecarga de Armazenamento: Bitmaps consomem armazenamento mínimo, mesmo para conjuntos de dados com milhões de linhas.
Flexibilidade: Índices bitmap oferecem suporte a condições e combinações de consultas complexas, tornando-os altamente adaptáveis a vários casos de uso.
Demonstração de RBAC em Nível de Linha no Milvus
Nesta seção, demonstraremos como o Milvus gerencia o acesso a várias bases de conhecimento de uma grande empresa.
Caso de Uso: Um RAG Empresarial com Múltiplas Bases de Conhecimento
Em uma grande empresa, diferentes departamentos frequentemente mantêm bases de conhecimento separadas—algumas públicas, outras confidenciais—para sua aplicação de RAG alimentada pelo Milvus. Para gerenciar permissões de forma eficaz entre essas bases de conhecimento, implementamos controles de acesso baseados em funções (RBAC) com base em entidades ou documentos. Por exemplo, uma função de superadministrador (admin) pode supervisionar o acesso, com funções adicionais para unidades de negócios específicas, como CEO, finanças, vendas e desenvolvedor, cada uma tendo acesso a diferentes conjuntos de dados.
Figura: Controle de acesso para diferentes funções em uma grande empresa
Definição de Colunas de Permissão
Para gerenciar o acesso, armazenamos dados de permissão em uma coluna de array dentro do Milvus. Essa coluna definirá quais funções têm acesso a quais linhas de dados. O field_name para essa coluna de permissão é personalizável, e o tamanho do array pode ser ajustado com base nas necessidades do usuário. Um índice BITMAP é então criado para essa coluna, tornando as verificações de permissão eficientes.
Abaixo está como essa configuração é feita em código:
# 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
)
Permissões de Escrita
Ao inserir novos dados, você atribui permissões especificando quais funções podem acessar cada linha. Isso pode ser feito escrevendo a(s) função(ões) correspondente(s) na coluna security_group.
Aqui está um exemplo de como isso funciona:
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)
Permissão de Consulta
Ao realizar operações de busca ou consulta, é essencial restringir os resultados para mostrar apenas os dados aos quais a função específica de um usuário tem acesso. Dados fora das funções permitidas do usuário serão ocultados dos resultados da consulta. Veja como isso pode ser feito:
Consultando Dados com Base nas Permissões de Função
Nos exemplos abaixo, usamos a função array_contains() para filtrar dados com base em permissões específicas de função. Cada consulta recupera apenas os dados que a função fornecida está autorizada a ver.
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)
Aqui está um exemplo de como seria a saída:
ceo role read:
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 role read:
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 role read:
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 or ceo role read:
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}", ...
Essa abordagem garante que cada função veja exatamente os dados que está autorizada a visualizar, ocultando quaisquer dados não autorizados. Você também pode empilhar várias funções no array security_group, permitindo um gerenciamento de permissões flexível e eficiente.
Filtros personalizados com acesso baseado em função
Em alguns casos, os usuários podem precisar aplicar filtros personalizados ao consultar dados. Esses filtros podem ser combinados com acesso baseado em função para refinar as pesquisas. Ao aplicar o controle de acesso baseado em função junto com condições de filtro personalizadas, podemos garantir que os usuários recuperem apenas os dados que têm permissão para ver com base tanto na função quanto nos critérios específicos da consulta.
Por exemplo:
res = client.query(
collection_name="test_collection",
# Sales role queries data with the filter "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 role queries data with the filter "pk > 10"
filter='pk > 10 && array_contains(security_group, "develop")',
output_fields=["id", "data", "security_group"],
)
Nesses exemplos, as consultas não apenas verificam as permissões baseadas em função, mas também aplicam filtros adicionais (como pk in [1, 3, 5] ou pk > 10) para restringir os resultados com base em critérios específicos. Essa flexibilidade permite que os usuários criem consultas altamente direcionadas, mantendo um controle rigoroso sobre o acesso aos dados.
Atualizar permissões
Há momentos em que você precisa alterar permissões — seja concedendo acesso a uma função específica para uma determinada linha de dados, seja removendo esse acesso. O Milvus facilita esse processo com sua API upsert, que permite atualizar as permissões associadas a uma linha de dados.
Vamos ver como você pode usar essa API para modificar permissões para uma linha específica.
Exemplo: Atualizando permissões para uma linha de dados
Para atualizar as permissões de uma linha, basta ajustar o campo security_group. Neste exemplo, adicionaremos a função "sales" a uma linha que anteriormente era acessível apenas pela função "finance".
upsert_row_update = {
"id": 101,
"vector": upsert_vector,
"data": upsert_data,
# update role
"security_group": ["finance", "sales"]
}
res = client.upsert(
collection_name="test_collection",
data=upsert_row_update)
Resultado:
Antes do upsert, a linha com pk = 101 era assim:
pk = 101:
data: [" {'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance'],"]
após upsert
data: ["{'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance', 'sales']}"]
Ao usar a coluna de array security_group e a filtragem por índice bitmap, estabelecemos uma base sólida para o controle de acesso de leitura em nível de linha, permitindo-nos gerenciar permissões de forma eficaz durante as consultas. Esse método oferece alto desempenho e controle granular sobre os direitos de acesso. No entanto, ele exige uma abordagem mais prática por parte dos administradores, que devem gerenciar cuidadosamente as permissões ao inserir ou atualizar dados e garantir uma estratégia de permissões bem planejada ao criar tabelas.
Conclusão
Implementar controle de acesso granular é um componente crítico do gerenciamento de dados moderno, especialmente para setores que lidam com informações sensíveis, como saúde e finanças. Milvus oferece RBAC em nível de linha (Controle de Acesso Baseado em Funções), que é uma solução robusta para gerenciar o acesso a dados com precisão e eficiência.
Essa abordagem não apenas aprimora a segurança, mas também oferece flexibilidade para necessidades de negócios em evolução, garantindo que as políticas de acesso possam se adaptar à medida que funções e responsabilidades mudam. Com suas ferramentas poderosas e seu modelo de permissões flexível, o Milvus capacita as organizações a criar sistemas de dados altamente seguros e escaláveis que atendem aos requisitos regulatórios, ao mesmo tempo em que oferecem acesso contínuo às pessoas certas.
Para um gerenciamento de permissões e herança ainda mais dinâmico, Zilliz Cloud, o serviço totalmente gerenciado do Milvus, possui recursos de permissões ainda mais granulares. Esses aprimoramentos não apenas melhorarão a eficiência administrativa, mas também oferecerão maior flexibilidade, facilitando o atendimento a uma variedade mais ampla de requisitos de negócios. Para obter mais informações sobre o RBAC do Zilliz Cloud, consulte sua documentação.
Leitura adicional
Continue lendo

A Few Notes from Databricks Data + AI Summit 2026: Why the Data Layer Matters Again
James Luan shares notes from Databricks Data + AI Summit 2026 on why production AI is pushing the data layer back to the center of infrastructure.

Zilliz Cloud Now Available in AWS Asia Pacific (Seoul)
Zilliz Cloud is now available in AWS Seoul — low-latency vector search, in-country data residency, and one-step migration for Korean AI teams. 31 regions across 5 clouds.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.



