Skip to main content

Command Palette

Search for a command to run...

Entendendo OpenFGA: Fundamentos, Modelagem e Otimização

Updated
Entendendo OpenFGA: Fundamentos, Modelagem e Otimização

A arquitetura de autorização apoia-se frequentemente em modelos estabelecidos, cada um com seus trade-offs. O RBAC (Role-Based Access Control) é eficiente para estruturas estáticas, enquanto o ABAC (Attribute-Based) e OPA (Policy-as-Code) trazem flexibilidade via atributos. No entanto, essas abordagens degradam em performance quando a permissão depende de uma topologia de dados complexa e profundidade hierárquica (ex: pastas aninhadas).

O OpenFGA resolve esse gargalo adotando o modelo do Google Zanzibar: a autorização deixa de ser uma verificação de regras para se tornar uma navegação em grafo de relacionamentos (ReBAC).

1. Modelagem: O Caso "Google Drive"

Ao projetar sistemas de permissão hierárquicos, caímos em um dilema clássico. Modelos mais normalizados reduzem redundância e evitam atualizações em massa, mas tornam a leitura de hierarquias profundas dependente de queries recursivas custosas. Modelos mais desnormalizados aceleram algumas leituras, mas aumentam drasticamente o volume de escrita: mover uma pasta com 100.000 arquivos pode exigir atualizar 100.000 registros de permissão para manter a consistência.

O OpenFGA resolve esse dilema alterando a natureza da verificação para um “cálculo de rota” num grafo. A complexidade de escrita mantém-se constante (O(1)), pois basta alterar uma aresta (como o pai da pasta) para que o acesso seja propagado instantaneamente, sem os custos de latência de leitura das abordagens puramente relacionais.

A unidade fundamental para construir esse grafo é a Tupla: User [...] Relation [...] Object.

Para ilustrar, vamos modelar esse sistema de arquivos:

A DSL e a Resolução de Grafos

model
  schema 1.1

type user

type folder
  relations
    define viewer: [user]

type document
  relations
    define parent: [folder]
    define viewer: [user] or viewer from parent

O ponto-chave é a cláusula viewer from parent.

Ela permite que o sistema deduza permissões sem duplicar informação. Quando o OpenFGA precisa saber se anne pode ver document:A, ele simplesmente segue a relação até folder:Pai. Se anne já é viewer da pasta, o acesso é permitido.

Esse encadeamento reduz o tamanho do conjunto de dados e mantém a verificação rápida, mesmo em hierarquias profundas.

2. Arquitetura e Resiliência no Caminho Crítico

No dia-a-dia, utilizar o OpenFGA significará que cada requisição da aplicação depende da autorização do serviço do OpenFGA, então qualquer variação de latência afeta todo o sistema diretamente.

A solução para reduzir esse problema passa primeiro pela imutabilidade dos modelos: como um modelo em produção nunca muda enquanto está sendo usado, não há risco de uma alteração gerar comportamentos inconsistentes ou erros intermitentes no meio do fluxo. A lógica de autorização permanece fixa, o que evita surpresas no ponto onde a aplicação mais precisa de previsibilidade.

A escolha por consistência eventual segue a mesma linha prática. Em ambientes distribuídos, buscar sempre a leitura mais atual implica adicionar latência constante a cada verificação. Como autorizações acontecem o tempo todo e criações de permissão são menos frequentes, vale mais a pena aceitar alguns milissegundos de defasagem na escrita para manter o caminho de leitura o mais rápido possível.

E a topologia entra fechando o ciclo: quanto menos rede houver entre a aplicação e o serviço de autorização, menor a latência você irá experimentar. Executar o OpenFGA como sidecar ou manter cache local reduz a verificação praticamente a uma operação local. Isso aumenta um pouco o consumo de recursos no nó (caso esteja utilizando o Kubernetes), mas elimina hops de rede e estabiliza a latência onde ela realmente importa.

3. Dicas de Otimização

A. Implícito vs. Explícito

A API do OpenFGA permite que você faça requisições utilizando 2 abordagens quanto ao authorization model:

  1. Implícita: O servidor busca qual é o modelo de autorização "mais recente" no banco.

  2. Explícita: O cliente envia o authorization_model_id diretamente.

Como mostram os testes, enviar o authorization_model_id reduz a latência de forma bem consistente. A abordagem implícita sempre adiciona um custo de latência que só piora conforme o modelo cresce.

B. Evite utilizar operações AND e BUT NOT

Operadores como AND e BUT NOT custam mais porque obrigam o servidor a compor resultados de múltiplas consultas internas. Em vez de avaliar uma única relação, ele precisa buscar dois conjuntos, cruzar ou subtrair itens e só então montar a resposta final. O gráfico reflete exatamente esse trabalho extra. Quando a regra pode ser expressa sem esses operadores, o ListObjects tende a ter uma latência muito menor.