Abilitare il controllo degli accessi granulare con RBAC a livello di riga di Milvus
Perché il controllo degli accessi è importante nei moderni sistemi di dati
Il controllo degli accessi è una delle sfide più pressanti nella moderna gestione dei dati, soprattutto per le aziende. Man mano che le organizzazioni crescono, in particolare in ambienti con più reparti e ruoli, sia una sicurezza robusta sia un accesso fluido sono fondamentali. Vediamo due esempi in cui il controllo degli accessi è particolarmente importante.
Sanità: bilanciare privacy e collaborazione
Nel settore sanitario, le organizzazioni devono proteggere la privacy dei pazienti favorendo al contempo la collaborazione tra professionisti medici. Immagina un medico che ha bisogno di accesso completo alle cartelle cliniche di un paziente per formulare una diagnosi e un piano di trattamento accurati. Tuttavia, quel medico non dovrebbe poter accedere alle cartelle dei pazienti che non sta curando. Per soddisfare questa esigenza, è essenziale un controllo degli accessi granulare, che garantisca che solo il personale medico autorizzato possa visualizzare dati sensibili dei pazienti. Questo livello di controllo aiuta le organizzazioni a rispettare normative rigorose come HIPAA, salvaguardando al contempo la privacy.
Finanza: proteggere i dati sensibili
Il settore finanziario affronta sfide simili quando si tratta di controllo degli accessi. Banche e istituzioni finanziarie gestiscono enormi quantità di dati sensibili—dettagli dei conti, cronologie delle transazioni, punteggi di credito, ecc. Questi dati vengono spesso convertiti in vettori e archiviati in un database vettoriale come Milvus per il rilevamento delle frodi, l’analisi del rischio e esperienze cliente personalizzate. Senza controlli di accesso adeguati, i dati sensibili potrebbero essere esposti a parti non autorizzate, portando a significative conseguenze finanziarie e legali.
Controlli granulari, come le autorizzazioni a livello di riga, consentono alle istituzioni di limitare l’accesso a utenti specifici—ad esempio, un gestore clienti può accedere solo ai dati dei conti dei propri clienti. Anche un accesso più ampio, richiesto dai team di gestione del rischio, può essere attentamente monitorato e limitato per prevenire abusi.
RBAC a livello di riga di Milvus: una soluzione di controllo degli accessi granulare
Il controllo degli accessi basato sui ruoli (RBAC) è un modello di sicurezza in cui l’accesso alle risorse viene concesso in base al ruolo di un utente all’interno di un’organizzazione. I ruoli definiscono le autorizzazioni e gli utenti ereditano tali autorizzazioni, garantendo una gestione sicura ed efficiente dei diritti di accesso.
Milvus è un database vettoriale open-source ad alte prestazioni, progettato per la scalabilità. È perfetto per creare applicazioni di AI basate su modelli come retrieval augmented generation (RAG), motori di ricerca semantica, sistemi di raccomandazione e chatbot. Milvus offre una soluzione RBAC granulare basata su un modello di autorizzazioni che utilizza l’indicizzazione bitmap per abilitare il controllo degli accessi a livello di riga. Questa funzionalità consente di controllare l’accesso a specifiche risorse e autorizzazioni di Milvus in base a ruoli e privilegi degli utenti. Attualmente, Milvus RBAC è disponibile solo in Python e Java.
Milvus RBAC offre diversi vantaggi:
Velocità ed efficienza: Consente query rapide delle autorizzazioni in grandi dataset.
Flessibilità: Si adatta all’evoluzione di ruoli e responsabilità, garantendo che le autorizzazioni rimangano aggiornate.
Fondamenti di RBAC
Ruoli e autorizzazioni
Ruolo: Rappresenta il ruolo di un utente nel sistema, con ogni ruolo assegnato a un insieme specifico di autorizzazioni.
Autorizzazione: Specifica i diritti di accesso alle singole righe in una connessione dati (tabella) all’interno di Milvus, come la possibilità di leggere, scrivere o eliminare dati specifici.
Creazione dell’indice bitmap
Gli indici bitmap sono la base di questo meccanismo di controllo degli accessi:
Ogni ruolo è associato a una bitmap che indica le righe a cui può accedere.
La lunghezza della bitmap corrisponde al numero di righe nella connessione:
Un 1 in una posizione significa che il ruolo ha accesso a quella riga.
Un 0 significa nessun accesso.
Utilizzo dell’indice bitmap
Concessione dei permessi: Per concedere a un ruolo l’accesso a una riga, imposta il bit corrispondente nella bitmap del ruolo a 1.
Verifica dei permessi: Per verificare se un ruolo può accedere a una riga specifica, controlla semplicemente se il bit corrispondente nella bitmap è 1.
Supponiamo di avere una connessione (tabella), Collection A, che memorizza la conoscenza aziendale. Ogni riga rappresenta contenuto identificato da doc_id e dalla knowledge base associata, kb_id.
| ID riga | PK | Dati | doc_id | kb_id | Ruolo |
|---|---|---|---|---|---|
| 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 |
I ruoli sono definiti come segue:
Ruolo 1: Può accedere alle righe 1, 2, 3 e 4 (
kb_id = 1).Ruolo 2: Può accedere alla riga 5 (
kb_id = 2).
Operazioni di query
Quando un utente interroga i dati, la bitmap del suo ruolo viene combinata con le condizioni della query per filtrare le righe a cui è autorizzato ad accedere. Ad esempio, se un utente con Ruolo 1 esegue una query su "tutti i dati", la sua bitmap 11110 restituirà le righe 1–4 (Data A, Data B, Data C e Data D).
Aggiornamento dei permessi
Per aggiungere o rimuovere l’accesso per un ruolo, aggiorna semplicemente il bit corrispondente nella bitmap del ruolo. Ad esempio, impostare un bit a 1 concede l’accesso, mentre impostarlo a 0 lo revoca.
Vantaggi e considerazioni
Efficienza: Le operazioni su bitmap sono rapide e adatte alla gestione dei permessi in dataset di grandi dimensioni.
Basso overhead di archiviazione: Le bitmap consumano uno spazio di archiviazione minimo, anche per dataset con milioni di righe.
Flessibilità: Gli indici bitmap supportano condizioni e combinazioni di query complesse, rendendoli altamente adattabili a vari casi d’uso.
Dimostrazione dell’RBAC a livello di riga in Milvus
In questa sezione, dimostreremo come Milvus gestisce l’accesso a varie knowledge base di una grande azienda.
Caso d’uso: un RAG aziendale con più knowledge base
In una grande azienda, diversi dipartimenti spesso mantengono knowledge base separate—alcune pubbliche, altre riservate—per la loro applicazione RAG basata su Milvus. Per gestire efficacemente i permessi tra queste knowledge base, implementiamo controlli di accesso basati sui ruoli (RBAC) basati su entità o documenti. Ad esempio, un ruolo di super amministratore (admin) potrebbe supervisionare l’accesso, con ruoli aggiuntivi per unità aziendali specifiche come CEO, finanza, vendite e sviluppatore, ciascuno con accesso a diversi insiemi di dati.
Figura: Controllo degli accessi per diversi ruoli in una grande azienda
Definizione delle colonne dei permessi
Per gestire l’accesso, memorizziamo i dati dei permessi in una colonna array all’interno di Milvus. Questa colonna definirà quali ruoli hanno accesso a quali righe di dati. Il field_name per questa colonna dei permessi è personalizzabile e la dimensione dell’array può essere regolata in base alle esigenze dell’utente. Viene quindi creato un indice BITMAP per questa colonna, rendendo efficienti le verifiche dei permessi.
Di seguito è riportato come questa configurazione viene eseguita nel codice:
# 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. crea indice bitmap per la colonna security
index_params.add_index(field_name="security_group",
index_type="BITMAP")
# 6. crea collection
client.create_collection(
collection_name="test_collection",
schema=schema,
index_params=index_params
)
Permessi di scrittura
Quando si inseriscono nuovi dati, si assegnano i permessi specificando quali ruoli possono accedere a ciascuna riga. Questo può essere fatto scrivendo il/i ruolo/i corrispondente/i nella colonna security_group.
Ecco un esempio di come funziona:
data =[]
data.append({
"id": random.randint(0, 100000),
"vector": [ random.uniform(-1, 1) for _ in range(128) ],
"data": "data" + str(random.randint(0,100000)),
# il ruolo ceo può leggere
"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)),
# il ruolo finance può leggere
"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)),
# sia sales sia developer possono leggere
"security_group": ["sales", "finance"]
})
res = client.insert(collection_name="test_collection", data=data)
Permesso di query
Quando si eseguono operazioni di ricerca o query, è essenziale limitare i risultati in modo da mostrare solo i dati a cui il ruolo specifico di un utente ha accesso. I dati al di fuori dei ruoli consentiti dell’utente saranno nascosti dai risultati della query. Ecco come si può fare:
Esecuzione di query sui dati in base ai permessi dei ruoli
Negli esempi seguenti, usiamo la funzione array_contains() per filtrare i dati in base ai permessi specifici dei ruoli. Ogni query recupera solo i dati che il ruolo indicato è autorizzato a vedere.
res = client.query(
collection_name="test_collection",
# Esegue query sui dati visibili solo al ruolo 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",
# Esegue query sui dati visibili solo al ruolo 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",
# Esegue query sui dati visibili solo al ruolo 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",
# Esegue query sui dati visibili ai ruoli 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)
Ecco un esempio di come apparirebbe l’output:
lettura ruolo 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'}", ...
lettura ruolo 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}", ...
lettura ruolo 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}"], ...
lettura ruolo 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}", ...
Questo approccio garantisce che ogni ruolo veda esattamente i dati che è autorizzato a visualizzare, nascondendo al contempo qualsiasi dato non autorizzato. Puoi anche impilare più ruoli nell'array security_group, consentendo una gestione delle autorizzazioni flessibile ed efficiente.
Filtri personalizzati con accesso basato sui ruoli
In alcuni casi, gli utenti potrebbero dover applicare filtri personalizzati durante l'interrogazione dei dati. Questi filtri possono essere combinati con l'accesso basato sui ruoli per perfezionare le ricerche. Applicando il controllo degli accessi basato sui ruoli insieme a condizioni di filtro personalizzate, possiamo garantire che gli utenti recuperino solo i dati che sono autorizzati a vedere in base sia al ruolo sia ai criteri specifici della query.
Ad esempio:
res = client.query(
collection_name="test_collection",
# Il ruolo Sales interroga i dati con il 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",
# Il ruolo Developer interroga i dati con il filtro "pk > 10"
filter='pk > 10 && array_contains(security_group, "develop")',
output_fields=["id", "data", "security_group"],
)
In questi esempi, le query non solo verificano le autorizzazioni basate sui ruoli, ma applicano anche filtri aggiuntivi (come pk in [1, 3, 5] o pk > 10) per restringere i risultati in base a criteri specifici. Questa flessibilità consente agli utenti di creare query altamente mirate mantenendo al contempo un controllo rigoroso sull'accesso ai dati.
Aggiornare le autorizzazioni
Ci sono momenti in cui è necessario modificare le autorizzazioni, che si tratti di concedere l'accesso a un ruolo specifico per una particolare riga di dati o di rimuovere tale accesso. Milvus semplifica questo processo con la sua API upsert, che consente di aggiornare le autorizzazioni associate a una riga di dati.
Vediamo come puoi utilizzare questa API per modificare le autorizzazioni per una riga specifica.
Esempio: aggiornamento delle autorizzazioni per una riga di dati
Per aggiornare le autorizzazioni per una riga, basta regolare il campo security_group. In questo esempio, aggiungeremo il ruolo "sales" a una riga che in precedenza era accessibile solo dal ruolo "finance".
upsert_row_update = {
"id": 101,
"vector": upsert_vector,
"data": upsert_data,
# aggiorna ruolo
"security_group": ["finance", "sales"]
}
res = client.upsert(
collection_name="test_collection",
data=upsert_row_update)
Risultato:
Prima dell'upsert, la riga con pk = 101 appariva così:
pk = 101:
data: [" {'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance'],"]
dopo l'upsert
data: ["{'id': 101,
'data': 'data63309',
'vector': [0.38069534, 0.15088418, -0.6266929, -0.6038463, 0.2516377...],
'security_group': ['finance', 'sales']}"]
Utilizzando la colonna array security_group e il filtro con indice bitmap, abbiamo stabilito una solida base per il controllo degli accessi in lettura a livello di riga, consentendoci di gestire efficacemente le autorizzazioni durante le query. Questo metodo offre prestazioni elevate e un controllo granulare sui diritti di accesso. Tuttavia, richiede un approccio più manuale da parte degli amministratori, che devono gestire attentamente le autorizzazioni durante l'inserimento o l'aggiornamento dei dati e garantire una strategia di autorizzazioni ben ponderata durante la creazione delle tabelle.
Conclusione
Implementare un controllo degli accessi granulare è un componente critico della moderna gestione dei dati, specialmente per i settori che trattano informazioni sensibili come sanità e finanza. Milvus offre RBAC (Role-Based Access Control) a livello di riga, una soluzione robusta per gestire l'accesso ai dati con precisione ed efficienza.
Questo approccio non solo migliora la sicurezza, ma offre anche flessibilità per le esigenze aziendali in evoluzione, garantendo che le policy di accesso possano adattarsi man mano che ruoli e responsabilità cambiano. Con i suoi potenti strumenti e il suo modello di autorizzazioni flessibile, Milvus consente alle organizzazioni di creare sistemi di dati altamente sicuri e scalabili che soddisfano i requisiti normativi offrendo al contempo un accesso senza interruzioni alle persone giuste.
Per una gestione delle autorizzazioni e un'ereditarietà ancora più dinamiche, Zilliz Cloud, il servizio completamente gestito di Milvus, dispone di funzionalità di autorizzazione ancora più granulari. Questi miglioramenti non solo aumenteranno l'efficienza amministrativa, ma offriranno anche maggiore flessibilità, rendendo più semplice soddisfare una gamma più ampia di requisiti aziendali. Per maggiori informazioni su Zilliz Cloud RBAC, consulta la sua documentazione.
Letture aggiuntive
Continua a leggere

Build Multimodal Search for 3D Assets with Tripo and Zilliz Cloud
Generate 3D assets with Tripo, then search them by text, image, and metadata with multimodal embeddings and Zilliz Cloud.

Announcing VDBBench 1.0: Open-Source VectorDB Benchmarking with Your Real-World Production Workloads
Discover VDBBench 1.0, an open-source tool for benchmarking vector databases with real-world production data, streaming ingestion, and concurrent workloads.

Cosmos World Foundation Model Platform for Physical AI
NVIDIA's Cosmos platform enables safe, digital twin training of GenAI models for physical applications, overcoming data scarcity and safety challenges.



