

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Exemplo 2: Controle de acesso multilocatário e RBAC definido pelo usuário com OPA e Rego
<a name="opa-rbac-examples"></a>

Este exemplo usa OPA e Rego para demonstrar como o controle de acesso pode ser implementado em uma API para um aplicativo multilocatário com funções personalizadas definidas pelos usuários locatários. Também demonstra como o acesso pode ser restrito com base em um inquilino. Esse modelo mostra como a OPA pode tomar decisões granulares de permissão com base nas informações fornecidas em uma função de alto nível.

![RBAC definido pelo usuário com OPA e Rego](http://docs.aws.amazon.com/pt_br/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/opa-example-2.png)


As funções dos inquilinos são armazenadas em dados externos (dados RBAC) que são usados para tomar decisões de acesso ao OPA:

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

Essas funções, quando definidas por um usuário inquilino, devem ser armazenadas em uma fonte de dados externa ou em um provedor de identidade (IdP) que possa atuar como uma fonte confiável ao mapear funções definidas pelo inquilino para as permissões e para o próprio inquilino. 

Este exemplo usa duas políticas no OPA para tomar decisões de autorização e examinar como essas políticas impõem o isolamento do inquilino. Essas políticas usam os dados RBAC definidos anteriormente.

```
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")
}
```

Para mostrar como essa regra funcionará, considere uma consulta OPA que tenha a seguinte entrada:

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

Uma decisão de autorização para essa chamada de API é feita da seguinte forma, combinando os *dados do RBAC*, *as políticas de OPA* e a entrada da consulta *OPA*:

1. Um usuário de `Tenant A` faz uma chamada de API para`/viewData/tenant_a`.

1. O microsserviço Data recebe a chamada e consulta a `allowViewData` regra, passando a entrada mostrada no exemplo de entrada da consulta OPA.

1. A OPA usa a regra consultada nas políticas de OPA para avaliar a entrada fornecida. O OPA também usa os dados dos dados do RBAC para avaliar a entrada. A OPA faz o seguinte:

   1. Verifica se o método usado para fazer a chamada da API é`GET`.

   1. Verifica se o caminho solicitado é`viewData`.

   1. Verifica se o `tenant_id` no caminho é igual ao `input.tenant_id` associado ao usuário. Isso garante que o isolamento do inquilino seja mantido. Outro inquilino, mesmo com uma função idêntica, não pode ser autorizado a fazer essa chamada de API.

   1. Extrai uma lista de permissões de função dos dados externos das funções e as atribui à variável. `role_permissions` Essa lista é recuperada usando a função definida pelo inquilino associada ao usuário no `input.role.`

   1. Verifica `role_permissions` se ele contém a permissão `viewData.`

1. A OPA retorna a seguinte decisão ao microsserviço Data:

```
{
    "allowViewData": true
}
```

Esse processo mostra como o RBAC e a conscientização do inquilino podem contribuir para a tomada de uma decisão de autorização com a OPA. Para ilustrar melhor esse ponto, considere uma chamada de API para `/viewData/tenant_b` com a seguinte entrada de consulta:

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

Essa regra retornaria a mesma saída da entrada da consulta OPA, embora seja para um inquilino diferente que tenha uma função diferente. Isso ocorre porque essa chamada é para `/tenant_b` e os `view_data_role` dados do RBAC ainda têm a `viewData` permissão associada a ela. Para aplicar o mesmo tipo de controle de acesso`/updateData`, você pode usar uma regra de OPA semelhante:

```
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")
}
```

Essa regra é funcionalmente igual à `allowViewData` regra, mas verifica um caminho e um método de entrada diferentes. A regra ainda garante o isolamento do inquilino e verifica se a função definida pelo inquilino concede permissão ao chamador da API. Para ver como isso pode ser aplicado, examine a seguinte entrada de consulta para uma chamada de API para`/updateData/tenant_b`:

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

Essa entrada de consulta, quando avaliada com a `allowUpdateData` regra, retorna a seguinte decisão de autorização:

```
{
    "allowUpdateData": false
}
```

Essa chamada não será autorizada. Embora o chamador da API esteja associado ao correto `tenant_id` e esteja chamando a API usando um método aprovado, ele `input.role` é definido pelo inquilino`view_data_role`. `view_data_role`Não tem `updateData` permissão; portanto, a chamada para não `/updateData` é autorizada. Essa chamada teria sido bem-sucedida para um `tenant_b` usuário que tem `update_data_role` o.