

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
<a name="opa-rbac-examples"></a>

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](http://docs.aws.amazon.com/it_it/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/opa-example-2.png)


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`

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

1. 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`

   1. Verifica che il percorso richiesto sia. `viewData`

   1. 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.

   1. 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.`

   1. Verifica se `role_permissions` contiene l'autorizzazione `viewData.`

1. 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'`viewData`autorizzazione. 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_role`Non dispone dell'`updateData`autorizzazione, pertanto la chiamata a non è autorizzata. `/updateData` Questa chiamata avrebbe avuto successo per un `tenant_b` utente che dispone di`update_data_role`.