Habilitar el control de acceso granular con RBAC a nivel de fila en Milvus
Por qué el control de acceso importa en los sistemas de datos modernos
El control de acceso es uno de los desafíos más apremiantes en la gestión moderna de datos, especialmente para las empresas. A medida que las organizaciones crecen, particularmente en entornos con múltiples departamentos y roles, tanto una seguridad robusta como un acceso fluido son fundamentales. Veamos dos ejemplos donde el control de acceso es especialmente importante.
Salud: Equilibrar la privacidad y la colaboración
En el sector de la salud, las organizaciones deben proteger la privacidad del paciente mientras fomentan la colaboración entre profesionales médicos. Imagina a un médico que necesita acceso completo a los registros médicos de un paciente para hacer un diagnóstico preciso y un plan de tratamiento. Sin embargo, ese médico no debería poder acceder a los registros de pacientes que no está tratando. Para satisfacer esta necesidad, el control de acceso detallado es esencial, garantizando que solo el personal médico autorizado pueda ver datos sensibles de pacientes. Este nivel de control ayuda a las organizaciones a cumplir con regulaciones estrictas como HIPAA mientras protege la privacidad.
Finanzas: Proteger datos sensibles
La industria financiera enfrenta desafíos similares en lo que respecta al control de acceso. Los bancos y las instituciones financieras manejan cantidades enormes de datos sensibles: detalles de cuentas, historiales de transacciones, puntajes crediticios, etc. Estos datos a menudo se convierten en vectores y se almacenan en una base de datos vectorial como Milvus para la detección de fraudes, el análisis de riesgos y experiencias de cliente personalizadas. Sin controles de acceso adecuados, los datos sensibles podrían quedar expuestos a partes no autorizadas, lo que llevaría a consecuencias financieras y legales significativas.
Los controles detallados, como los permisos a nivel de fila, permiten a las instituciones restringir el acceso a usuarios específicos; por ejemplo, un gestor de clientes puede acceder únicamente a los datos de cuenta de sus propios clientes. Incluso un acceso más amplio, requerido por los equipos de gestión de riesgos, puede ser cuidadosamente monitoreado y restringido para prevenir el uso indebido.
RBAC a nivel de fila de Milvus: una solución de control de acceso detallado
El control de acceso basado en roles (RBAC) es un modelo de seguridad en el que el acceso a recursos se concede según el rol de un usuario dentro de una organización. Los roles definen permisos, y los usuarios heredan esos permisos, garantizando una gestión segura y eficiente de los derechos de acceso.
Milvus es una base de datos vectorial de código abierto y alto rendimiento creada para escalar. Es perfecta para crear aplicaciones de IA con modelos, como generación aumentada por recuperación (RAG), motores de búsqueda semántica, sistemas de recomendación y chatbots. Milvus ofrece una solución RBAC detallada basada en un modelo de permisos que utiliza indexación de mapa de bits para habilitar el control de acceso a nivel de fila. Esta característica te permite controlar el acceso a recursos y permisos específicos de Milvus en función de los roles y privilegios de los usuarios. Actualmente, Milvus RBAC solo está disponible en Python y Java.
Milvus RBAC ofrece varias ventajas:
Velocidad y eficiencia: Permite consultar rápidamente permisos en grandes conjuntos de datos.
Flexibilidad: Se adapta a medida que los roles y las responsabilidades evolucionan, garantizando que los permisos se mantengan actualizados.
Fundamentos de RBAC
Roles y permisos
Rol: Representa el rol de un usuario en el sistema, con cada rol asignado a un conjunto específico de permisos.
Permiso: Especifica derechos de acceso a filas individuales en una conexión de datos (tabla) dentro de Milvus, como la capacidad de leer, escribir o eliminar datos específicos.
Creación de índices de mapa de bits
Los índices de mapa de bits son la base de este mecanismo de control de acceso:
Cada rol está asociado con un mapa de bits que indica las filas a las que puede acceder.
La longitud del mapa de bits coincide con el número de filas en la conexión:
Un 1 en una posición significa que el rol tiene acceso a esa fila.
Un 0 significa sin acceso.
Uso del índice bitmap
Otorgar permisos: Para dar acceso a un rol a una fila, establece el bit correspondiente en el bitmap del rol en 1.
Comprobar permisos: Para verificar si un rol puede acceder a una fila específica, simplemente comprueba si el bit correspondiente en el bitmap es 1.
Supongamos que tenemos una conexión (tabla), Colección A, que almacena conocimiento empresarial. Cada fila representa contenido identificado por doc_id y su base de conocimiento asociada, kb_id.
| ID de fila | PK | Datos | doc_id | kb_id | Rol |
|---|---|---|---|---|---|
| 1 | 0 | Datos A | 1 | 1 | role1 |
| 2 | 1 | Datos B | 1 | 1 | role1 |
| 3 | 2 | Datos C | 2 | 1 | role1 |
| 4 | 3 | Datos D | 2 | 1 | role1 |
| 5 | 4 | Datos E | 3 | 2 | role2 |
Los roles se definen de la siguiente manera:
Rol 1: Puede acceder a las filas 1, 2, 3 y 4 (
kb_id = 1).Rol 2: Puede acceder a la fila 5 (
kb_id = 2).
Operaciones de consulta
Cuando un usuario consulta los datos, el bitmap de su rol se combina con las condiciones de la consulta para filtrar las filas a las que está autorizado a acceder. Por ejemplo, si un usuario con Rol 1 consulta "todos los datos," su bitmap 11110 devolverá las filas 1–4 (Datos A, Datos B, Datos C y Datos D).
Actualizar permisos
Para añadir o eliminar el acceso de un rol, simplemente actualiza el bit correspondiente en el bitmap del rol. Por ejemplo, establecer un bit en 1 concede acceso, mientras que establecerlo en 0 lo revoca.
Ventajas y consideraciones
Eficiencia: Las operaciones con bitmaps son rápidas y adecuadas para gestionar permisos en grandes conjuntos de datos.
Baja sobrecarga de almacenamiento: Los bitmaps consumen un almacenamiento mínimo, incluso para conjuntos de datos con millones de filas.
Flexibilidad: Los índices bitmap admiten condiciones y combinaciones de consulta complejas, lo que los hace altamente adaptables a diversos casos de uso.
Demostración de RBAC a nivel de fila en Milvus
En esta sección, demostraremos cómo Milvus gestiona el acceso a varias bases de conocimiento de una gran empresa.
Caso de uso: un RAG empresarial con múltiples bases de conocimiento
En una gran empresa, diferentes departamentos suelen mantener bases de conocimiento separadas —algunas públicas, otras confidenciales— para su aplicación RAG impulsada por Milvus. Para gestionar permisos de manera efectiva en estas bases de conocimiento, implementamos controles de acceso basados en roles (RBAC) basados en entidades o documentos. Por ejemplo, un rol de superadministrador (admin) podría supervisar el acceso, con roles adicionales para unidades de negocio específicas como CEO, finanzas, ventas y desarrollador, cada uno con acceso a diferentes conjuntos de datos.
Figura: Control de acceso para diferentes roles en una gran empresa
Definición de columnas de permisos
Para gestionar el acceso, almacenamos los datos de permisos en una columna de array dentro de Milvus. Esta columna definirá qué roles tienen acceso a qué filas de datos. El field_name para esta columna de permisos es personalizable, y el tamaño del array puede ajustarse según las necesidades del usuario. Luego se crea un índice BITMAP para esta columna, lo que hace que las comprobaciones de permisos sean eficientes.
A continuación se muestra cómo se realiza esta configuración en 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. crear índice bitmap para la columna de seguridad
index_params.add_index(field_name="security_group",
index_type="BITMAP")
# 6. crear colección
client.create_collection(
collection_name="test_collection",
schema=schema,
index_params=index_params
)
Permisos de escritura
Al insertar nuevos datos, asignas permisos especificando qué roles pueden acceder a cada fila. Esto se puede hacer escribiendo el/los rol(es) correspondiente(s) en la columna security_group.
Aquí tienes un ejemplo de cómo 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)),
# el rol ceo puede leer
"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)),
# el rol finance puede leer
"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)),
# tanto sales como developer pueden leer
"security_group": ["sales", "finance"]
})
res = client.insert(collection_name="test_collection", data=data)
Permiso de consulta
Al realizar operaciones de búsqueda o consulta, es esencial restringir los resultados para mostrar solo los datos a los que tiene acceso el rol específico de un usuario. Los datos fuera de los roles permitidos del usuario se ocultarán de los resultados de la consulta. Así es como se puede hacer:
Consultar datos según los permisos de rol
En los ejemplos siguientes, usamos la función array_contains() para filtrar datos según permisos específicos de rol. Cada consulta recupera solo los datos que el rol dado está autorizado a ver.
res = client.query(
collection_name="test_collection",
# Consultar datos visibles solo para el rol CEO
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",
# Consultar datos visibles solo para el rol Sales
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",
# Consultar datos visibles solo para el rol Developer
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",
# Consultar datos visibles para los roles Developer o CEO
filter='array_contains_any(security_group, ["develop", "ceo"])',
output_fields=["id", "data", "security_group"],
)
print("developer or ceo role read:")
print(res)
Aquí tienes un ejemplo de cómo se vería la salida:
lectura de rol 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'}", ...
lectura de rol 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}", ...
lectura de rol 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}"], ...
lectura de rol developer o 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}", ...
Este enfoque garantiza que cada rol vea exactamente los datos que está autorizado a ver, mientras oculta cualquier dato no autorizado. También puede apilar varios roles en el array security_group, lo que permite una gestión de permisos flexible y eficiente.
Filtros personalizados con acceso basado en roles
En algunos casos, los usuarios pueden necesitar aplicar filtros personalizados al consultar datos. Estos filtros pueden combinarse con el acceso basado en roles para refinar las búsquedas. Al aplicar el control de acceso basado en roles junto con condiciones de filtro personalizadas, podemos garantizar que los usuarios solo recuperen datos que tienen permitido ver según tanto el rol como los criterios específicos de la consulta.
Por ejemplo:
res = client.query(
collection_name="test_collection",
# El rol Sales consulta datos con el filtro "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",
# El rol Developer consulta datos con el filtro "pk > 10"
filter='pk > 10 && array_contains(security_group, "develop")',
output_fields=["id", "data", "security_group"],
)
En estos ejemplos, las consultas no solo comprueban los permisos basados en roles, sino que también aplican filtros adicionales (como pk in [1, 3, 5] o pk > 10) para reducir los resultados según criterios específicos. Esta flexibilidad permite a los usuarios crear consultas altamente específicas mientras mantienen un control estricto sobre el acceso a los datos.
Actualizar permisos
Hay ocasiones en las que necesita cambiar permisos, ya sea conceder acceso a un rol específico para una fila de datos concreta o eliminar ese acceso. Milvus facilita este proceso con su API upsert, que le permite actualizar los permisos asociados con una fila de datos.
Veamos cómo puede usar esta API para modificar permisos para una fila específica.
Ejemplo: Actualizar permisos para una fila de datos
Para actualizar los permisos de una fila, simplemente ajuste el campo security_group. En este ejemplo, agregaremos el rol "sales" a una fila que anteriormente solo era accesible por el rol "finance".
upsert_row_update = {
"id": 101,
"vector": upsert_vector,
"data": upsert_data,
# actualizar rol
"security_group": ["finance", "sales"]
}
res = client.upsert(
collection_name="test_collection",
data=upsert_row_update)
Resultado:
Antes del upsert, la fila con pk = 101 se veía así:
pk = 101:
data: [" {'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance'],"]
después de upsert
data: ["{'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance', 'sales']}"]
Al usar la columna de array security_group y el filtrado con índice bitmap, hemos establecido una base sólida para el control de acceso de lectura a nivel de fila, lo que nos permite gestionar eficazmente los permisos durante las consultas. Este método ofrece un rendimiento sólido y un control detallado sobre los derechos de acceso. Sin embargo, sí requiere un enfoque más manual por parte de los administradores, quienes deben gestionar cuidadosamente los permisos al insertar o actualizar datos y garantizar una estrategia de permisos bien pensada al crear tablas.
Conclusión
Implementar un control de acceso detallado es un componente crítico de la gestión moderna de datos, especialmente para industrias que manejan información sensible como la salud y las finanzas. Milvus ofrece RBAC a nivel de fila (Control de acceso basado en roles), que es una solución robusta para gestionar el acceso a los datos con precisión y eficiencia.
Este enfoque no solo mejora la seguridad, sino que también ofrece flexibilidad para las necesidades empresariales en evolución, garantizando que las políticas de acceso puedan adaptarse a medida que cambian los roles y las responsabilidades. Con sus potentes herramientas y su modelo de permisos flexible, Milvus permite a las organizaciones crear sistemas de datos altamente seguros y escalables que cumplen con los requisitos regulatorios, al tiempo que ofrecen acceso fluido a las personas adecuadas.
Para una gestión de permisos e herencia aún más dinámica, Zilliz Cloud, el servicio completamente gestionado de Milvus, cuenta con funciones de permisos aún más detalladas. Estas mejoras no solo aumentarán la eficiencia administrativa, sino que también ofrecerán mayor flexibilidad, facilitando el cumplimiento de una gama más amplia de requisitos empresariales. Para obtener más información sobre RBAC de Zilliz Cloud, consulta su documentación.
Lecturas adicionales
Sigue leyendo

How to Choose the Best Embedding Model for RAG in 2026: 10 Models Benchmarked
We benchmarked 10 embedding models on cross-modal, cross-lingual, long-document, and dimension compression tasks. See which one fits your RAG pipeline.

My Wife Wanted Dior. I Spent $600 on Claude Code to Vibe-Code a 2M-Line Database Instead.
Write tests, not code reviews. How a test-first workflow with 6 parallel Claude Code sessions turns a 2M-line C++ codebase into a daily shipping pipeline.

Demystifying the Milvus Sizing Tool
Explore how to use the Sizing Tool to select the optimal configuration for your Milvus deployment.



