Esempio 2: controllo degli accessi multi-tenant e RBAC definito dall'utente con OPA e Rego - AWS Guida prescrittiva

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Esempio 2: controllo degli accessi multi-tenant e RBAC definito dall'utente con OPA e Rego

Questo esempio utilizza OPA e Rego per dimostrare come implementare il controllo degli accessi su un'API per un'applicazione multi-tenant con ruoli personalizzati definiti dagli utenti tenant. Dimostra inoltre come è possibile limitare l'accesso in base a un tenant. Questo modello mostra come OPA può prendere decisioni granulari sulle autorizzazioni sulla base delle informazioni fornite in un ruolo di alto livello.

RBAC definito dall'utente con OPA e Rego

I ruoli degli inquilini sono archiviati in dati esterni (dati RBAC) utilizzati per prendere decisioni di accesso per OPA:

{ "roles": { "tenant_a": { "all_access_role": ["viewData", "updateData"] }, "tenant_b": { "update_data_role": ["updateData"], "view_data_role": ["viewData"] } } }

Questi ruoli, se definiti da un utente tenant, devono essere archiviati in un'origine dati esterna o in un provider di identità (IdP) che possa fungere da fonte di verità durante la mappatura dei ruoli definiti dal tenant alle autorizzazioni e al tenant stesso. 

Questo esempio utilizza due politiche in OPA per prendere decisioni di autorizzazione e per esaminare come queste politiche impongono l'isolamento dei tenant. Queste politiche utilizzano i dati RBAC definiti in precedenza.

default allowViewData = false allowViewData = true { input.method == "GET" input.path = ["viewData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "viewData") }

Per mostrare come funzionerà questa regola, considera una query OPA con il seguente input:

{ "tenant_id": "tenant_a", "role": "all_access_role", "path": ["viewData", "tenant_a"], "method": "GET" }

Una decisione di autorizzazione per questa chiamata API viene presa come segue, combinando i dati RBAC, le politiche OPA e l'input della query OPA:

  1. Un utente di Tenant A effettua una chiamata API a. /viewData/tenant_a

  2. Il microservizio Data riceve la chiamata e interroga la allowViewData regola, passando l'input mostrato nell'esempio di input della query OPA.

  3. OPA utilizza la regola richiesta nelle politiche OPA per valutare l'input fornito. L'OPA utilizza anche i dati dei dati RBAC per valutare l'input. L'OPA esegue le seguenti operazioni:

    1. Verifica che il metodo utilizzato per effettuare la chiamata API sia. GET

    2. Verifica che il percorso richiesto sia. viewData

    3. Verifica che il valore tenant_id nel percorso sia uguale a quello input.tenant_id associato all'utente. Ciò garantisce il mantenimento dell'isolamento degli inquilini. Un altro tenant, anche con un ruolo identico, non può essere autorizzato a effettuare questa chiamata API.

    4. Estrae un elenco di autorizzazioni di ruolo dai dati esterni dei ruoli e le assegna alla variabile. role_permissions Questo elenco viene recuperato utilizzando il ruolo definito dal tenant associato all'utente in input.role.

    5. Verifica se role_permissions contiene l'autorizzazione viewData.

  4. OPA restituisce la seguente decisione al microservizio Data:

{ "allowViewData": true }

Questo processo mostra come RBAC e la consapevolezza degli inquilini possono contribuire a prendere una decisione di autorizzazione con OPA. Per illustrare ulteriormente questo punto, considera una chiamata API a /viewData/tenant_b con il seguente input di query:

{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["viewData", "tenant_b"], "method": "GET" }

Questa regola restituirebbe lo stesso output dell'input della query OPA, sebbene sia destinata a un tenant diverso che ha un ruolo diverso. Questo perché questa chiamata è destinata /tenant_b e ai dati view_data_role in RBAC è ancora associata l'viewDataautorizzazione. Per applicare lo stesso tipo di controllo degli accessi per/updateData, puoi utilizzare una regola OPA simile:

default allowUpdateData = false allowUpdateData = true { input.method == "POST" input.path = ["updateData", tenant_id] input.tenant_id == tenant_id role_permissions := data.roles[input.tenant_id][input.role][_] contains(role_permissions, "updateData") }

Questa regola è funzionalmente la stessa della allowViewData regola, ma verifica un percorso e un metodo di input diversi. La regola garantisce comunque l'isolamento dei tenant e verifica che il ruolo definito dal tenant conceda l'autorizzazione al chiamante dell'API. Per vedere come ciò potrebbe essere applicato, esamina il seguente input di query per una chiamata API a: /updateData/tenant_b

{ "tenant_id": "tenant_b", "role": "view_data_role", "path": ["updateData", "tenant_b"], "method": "POST" }

Questo input di query, se valutato con la allowUpdateData regola, restituisce la seguente decisione di autorizzazione:

{ "allowUpdateData": false }

Questa chiamata non sarà autorizzata. Sebbene il chiamante dell'API sia associato all'indirizzo corretto tenant_id e stia chiamando l'API utilizzando un metodo approvato, input.role è definito dal view_data_role tenant. view_data_roleNon dispone dell'updateDataautorizzazione, pertanto la chiamata a non è autorizzata. /updateData Questa chiamata avrebbe avuto successo per un tenant_b utente che dispone diupdate_data_role.