Pular para o conteúdo principal

Understanding How Casbin Matching Works in Detail

Neste post, vou explicar o design e a implementação do RBAC usando a biblioteca Casbin. Para uma plataforma SaaS lidando com múltiplas hierarquias de recursos e papéis que herdam permissões de níveis superiores, Casbin oferece uma alternativa performática a ser considerada.

Introdução ao RBAC

RBAC é um método de restringir o acesso a recursos com base nos papéis que os indivíduos possuem. Para entender melhor como o RBAC hierárquico funciona, vamos dar uma olhada no sistema RBAC do Azure na próxima seção e depois tentar implementar um sistema semelhante.

Entendendo o RBAC Hierárquico do Azure

Hierarquia do Azure

Há um papel chamado Owner para todos os recursos no Azure. Suponha que se eu tenho o papel de Owner atribuído a mim no nível de assinatura, isso significa que sou o Owner de todos os grupos de recursos e recursos sob essa assinatura. Se eu tenho o papel de Owner no nível do grupo de recursos, então sou o Owner de todos os recursos sob esse grupo de recursos.

Esta imagem mostra que tenho acesso de Owner no nível da assinatura. Proprietário da Assinatura

Quando verifico o IAM de um Grupo de Recursos sob esta Assinatura, você pode ver que herdei o acesso de Owner da assinatura. Proprietário do RG

Então, é assim que o RBAC do Azure é hierárquico. A maioria dos softwares empresariais usa RBAC hierárquico devido à natureza hierárquica dos níveis de recursos. Neste tutorial, tentaremos implementar um sistema semelhante usando Casbin.

Como Funciona o Casbin?

Antes de mergulhar na implementação, é importante entender o que é Casbin e como ele funciona em um alto nível. Este entendimento é necessário porque cada sistema de Controle de Acesso Baseado em Papéis (RBAC) pode variar com base em requisitos específicos. Ao compreender o funcionamento do Casbin, podemos ajustar eficazmente o modelo.

O que é ACL?

ACL significa Lista de Controle de Acesso. É um método no qual os usuários são mapeados para ações e ações para recursos.

A definição do modelo

Vamos considerar um exemplo simples de um modelo ACL.

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  1. A request_definition é o template de consulta do sistema. Por exemplo, uma solicitação alice, write, data1 pode ser interpretada como 'A sujeito Alice pode realizar a ação 'write' no objeto 'data1'?'

  2. A policy_definition é o template de atribuição do sistema. Por exemplo, ao criar uma política alice, write, data1, você está atribuindo permissão ao sujeito Alice para realizar a ação 'write' no objeto 'data1'.

  3. O policy_effect define o efeito da política.

  4. Na seção matchers, a solicitação é combinada com a política usando as condições r.sub == p.sub && r.obj == p.obj && r.act == p.act.

Agora vamos testar o modelo no editor Casbin

Abra o editor e cole o modelo acima no editor de Modelo.

Cole o seguinte no editor de Política:

p, alice, read, data1
p, bob, write, data2

e o seguinte no editor de Solicitação:

alice, read, data1

O resultado será:

true

Representação visual do modelo ACL, política e correspondência de solicitação

acl

O que é RBAC?

RBAC significa Controle de Acesso Baseado em Papéis. No RBAC, um usuário é atribuído a um papel para um recurso, e um papel pode conter ações arbitrárias. A solicitação verifica então se o usuário tem permissão para realizar a ação no recurso.

A definição do modelo

Vamos considerar um exemplo simples de modelo RBAC:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
  1. A role_definition é um construtor de relação de gráfico que usa um Grafo para comparar o objeto de solicitação com o objeto de política.

Agora vamos testar o modelo no editor Casbin

Abra o editor e cole o modelo acima no editor de Modelo.

Cole o seguinte no editor de Política:

p, alice, reader, data1
p, bob, owner, data2

g, reader, read
g, owner, read
g, owner, write

e o seguinte no editor de Requisições:

alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1

O resultado será:

true
false
true
true
false

Representação visual do modelo RBAC, política e correspondência de requisições

rbac

A tabela g - Mapeamento de função para ação tem um mapeamento gráfico da função para ação. Este Gráfico pode ser codificado como uma lista de arestas, conforme mostrado na política, que é uma maneira comum de representar um Gráfico:

g, reader, read
g, owner, read
g, owner, write
informação

p indica uma política normal que pode ser comparada usando o operador ==. g é uma função de comparação baseada em Gráfico. Você pode definir vários comparadores de Gráfico adicionando um sufixo numérico como g, g2, g3, ... e assim por diante.

O que é RBAC Hierárquico?

No RBAC Hierárquico, existem mais de um tipo de recursos e há uma relação de herança entre os tipos de recursos. Por exemplo, "assinatura" é um tipo e "grupoDeRecursos" é outro tipo. Uma sub1 do tipo Assinatura pode conter vários gruposDeRecursos (rg1, rg2) do tipo GrupoDeRecursos.

Semelhante à hierarquia de recursos, haverá dois tipos de funções e ações: funções e ações de Assinatura, e funções e ações de GrupoDeRecursos. Há uma relação arbitrária entre a função de Assinatura e a função de GrupoDeRecursos. Por exemplo, considere uma Função de Assinatura proprietário-sub. Esta função é herdada por uma Função de GrupoDeRecursos proprietário-rg, o que significa que se eu for atribuído à função proprietário-sub na Assinatura sub1, então eu automaticamente também obtenho a função proprietário-rg em rg1 e rg2.

A definição do modelo

Vamos pegar um exemplo simples do modelo RBAC Hierárquico:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && g2(p.obj, r.obj)
  1. O role_definition é um construtor de relação gráfica que usa um Gráfico para comparar o objeto de requisição com o objeto de política.

Agora vamos testar o modelo no editor Casbin

Abra o editor e cole o modelo acima no editor de Modelo.

Cole o seguinte no editor de Política:

p, alice, sub-reader, sub1
p, bob, rg-owner, rg2

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

E cole o seguinte no editor de Requisições:

alice, rg-read, rg1

O resultado será:

true

Representação visual do modelo RBAC, política e correspondência de requisições

hrbac

A tabela g - Mapeamento de função para (Ação, Função) tem um gráfico mapeando a função para a ação, mapeamento de função. Este gráfico pode ser codificado como uma lista de arestas, conforme mostrado na política, que é uma maneira comum de representar um gráfico:

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

A tabela g2 - Mapeamento de Assinatura para GrupoDeRecursos tem um gráfico mapeando assinatura para grupoDeRecursos:

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

Representação visual da correspondência de Sujeito

hrbac-sub-match

Representação visual da correspondência de Ação

hrbac-act-match

Representação visual da correspondência de Objeto

hrbac-obj-match

informação

Quando uma requisição é submetida ao Casbin, essa correspondência acontece para todas as políticas. Se pelo menos uma política corresponder, então o resultado da requisição é verdadeiro. Se nenhuma política corresponder à requisição, então o resultado é falso.

Conclusão

Neste tutorial, aprendemos sobre como diferentes modelos de autorização funcionam e como eles podem ser modelados usando Casbin. Na segunda parte deste tutorial, implementaremos isso em uma aplicação de demonstração Spring Boot e protegeremos as APIs usando Casbin.