Understanding How Casbin Matching Works in Detail
この投稿では、Casbinライブラリを使用したRBACの設計と実装について説明します。 複数のリソース階層と、上位レベルから権限を継承するロールを扱うSaaSプラットフォームに対して、Casbinはパフォーマンスの高い代替手段を提供します。
RBACへの導入
RBACは、個々の持つ役割に基づいてリソースへのアクセスを制限する方法です。 階層型RBACの仕組みをより理解するために、次のセクションでAzureのRBACシステムを見てみて、それに似たシステムを実装しようと試みます。
Azureの階層型RBACの理解
AzureのすべてのリソースにはOwnerという役割があります。 もし私がサブスクリプションレベルでOwnerの役割を割り当てられていると仮定すると、それは私がそのサブスクリプションの下にあるすべてのリソースグループとリソースのOwnerであることを意味します。 もし私がリソースグループレベルでOwnerを持っているなら、私はそのリソースグループの下にあるすべてのリソースのOwnerです。
この画像は、私がサブスクリプションレベルでOwnerのアクセス権を持っていることを示しています。
このサブスクリプションの下のリソースグループのIAMを確認すると、私がサブスクリプションからOwnerのアクセス権を継承していることがわかります。
これが、AzureのRBACが階層的である方法です。 リソースレベルの階層性のため、ほとんどのエンタープライズソフトウェアは階層型RBACを使用しています。 このチュートリアルでは、Casbinを使用して同様のシステムを実装しようと試みます。
Casbinはどのように動作するのか?
実装に入る前に、Casbinが何であり、高レベルでどのように機能するかを理解することが重要です。 この理解は必要です。なぜなら、各ロールベースのアクセス制御(RBAC)システムは、特定の要件に基づいて異なる可能性があるからです。 Casbinの仕組みを把握することで、モデルを効果的に微調整することができます。
ACLとは何ですか?
ACLはAccess Control Listの略です。 これは、ユーザーがアクションにマッピングされ、アクションがリソースにマッピングされる方法です。
モデル定義
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
request_definitionはシステムのクエリテンプレートです。 例えば、リクエスト
alice, write, data1
は「主体Aliceがオブジェクト'data1'に対して'write'アクションを実行できるか?」と解釈できます。policy_definitionはシステムの割り当てテンプレートです。 たとえば、ポリシー
alice, write, data1
を作成することで、Aliceという主体に対して、オブジェクト'data1'に対する'action'を実行する権限を割り当てています。policy_effectはポリシーの効果を定義します。
matchersセクションでは、リクエストが条件
r.sub == p.sub && r.obj == p.obj && r.act == p.act
を使用してポリシーと一致します。
では、Casbinエディターでモデルをテストしてみましょう
エディターを開き、上記のモデルをモデルエディターに貼り付けます。
以下をポリシーエディターに貼り付けます:
p, alice, read, data1
p, bob, write, data2
そして、以下をリクエストエディターに貼り付けます:
alice, read, data1
結果は次のようになります:
true
ACLモデル、ポリシー、リクエストマッチングの視覚的な表現
RBACとは何ですか?
RBACはRole-Based Access Controlの略です。 RBACでは、ユーザーにリソースの役割が割り当てられ、役割には任意のアクションを含めることができます。 その後、リクエストはユーザーがリソースに対してアクションを実行する権限を持っているかどうかをチェックします。
モデル定義
簡単な例として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
- role_definitionは、グラフを使用してリクエストオブジェクトとポリシーオブジェクトを比較するグラフ関係ビルダーです。
では、Casbinエディターでモデルをテストしてみましょう
エディターを開き、上記のモデルをモデルエディターに貼り付けます。
以下をポリシーエディターに貼り付けます:
p, alice, reader, data1
p, bob, owner, data2
g, reader, read
g, owner, read
g, owner, write
そして、以下をリクエストエディターに貼り付けます:
alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1
結果は次のようになります:
true
false
true
true
false
RBACモデル、ポリシー、リクエストマッチングの視覚的な表現
g - Role to action mappingテーブルは、役割をアクションにマッピングするグラフを持っています。 このグラフは、ポリシーに示されているように、エッジのリストとしてコード化することができます。これはグラフを表現する一般的な方法です:
g, reader, read
g, owner, read
g, owner, write
pは、**==**演算子を使用して比較できる通常のポリシーを示します。 gはグラフベースの比較関数です。 数値の接尾辞を追加することで、**g, g2, g3, ...**などといった複数のグラフ比較器を定義することができます。
階層型RBACとは何ですか?
階層的RBACでは、リソースの種類が複数あり、リソースの種類間には継承関係が存在します。 例えば、「subscription」は一つの種類で、「resourceGroup」は別の種類です。 Subscriptionタイプのsub1は、ResourceGroupタイプの複数のresourceGroups(rg1、rg2)を含むことができます。
リソースの階層と同様に、役割とアクションには2つのタイプがあります:Subscriptionの役割とアクション、およびResourceGroupの役割とアクション。 Subscriptionの役割とResourceGroupの役割の間には任意の関係があります。 例えば、Subscription Roleのsub-ownerを考えてみましょう。 この役割は、ResourceGroup Roleのrg-ownerに継承されます。つまり、私がSubscriptionのsub1にsub-ownerの役割を割り当てられた場合、自動的にrg1とrg2のrg-ownerの役割も得ることになります。
モデルの定義
階層的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) && g2(p.obj, r.obj)
- role_definitionは、グラフを使用してリクエストオブジェクトとポリシーオブジェクトを比較するグラフ関係ビルダーです。
次に、Casbinエディターでモデルをテストしてみましょう
エディターを開き、上記のモデルをモデルエディターに貼り付けます。
以下をポリシーエディターに貼り付けます:
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
そして、以下をリクエストエディターに貼り付けます:
alice, rg-read, rg1
結果は以下のようになります:
true
RBACモデル、ポリシー、リクエストマッチングの視覚的表現
g - Role to (Action, Role) Mappingテーブルは、役割をアクション、役割マッピングにマッピングするグラフを持っています。 このグラフは、ポリシーに示されているように、エッジのリストとしてコード化することができます。これはグラフを表現する一般的な方法です:
// 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
g2 - Sub to RG Mappingテーブルは、subscriptionをresourceGroupにマッピングするグラフを持っています:
// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2
Subject Matchingの視覚的表現
Action Matchingの視覚的表現
Object Matchingの視覚的表現
リクエストがCasbinに送信されると、このマッチングはすべてのポリシーに対して行われます。 少なくとも一つのポリシーがマッチすると、リクエストの結果はtrueになります。 ポリシーがリクエストに一致しない場合、結果はfalseになります。
結論
このチュートリアルでは、さまざまな認証モデルがどのように動作し、それらがCasbinを使用してどのようにモデル化できるかについて学びました。 このチュートリアルの第2部では、これをデモのSpring Bootアプリケーションに実装し、Casbinを使用してAPIを保護します。