アクセス制御(認可)ライブラリ Casbin の使い方まとめ
モデル定義
CasbinはPERM (Policy, Effect, Request, Matcher) ベースのアクセス制御モデルを採用している。モデル定義はconfファイルに記述するが、この中にはPERMに相当するPolicy Definition、Policy Effect、Request Definition、Matcherの4セクションを少なくとも記述する必要がある。
Access Control List (ACL)
ファイルシステム等で使われるACLのモデル定義を題材に、Casbinのモデル定義方法を解説する。(参考:Syntax for Models)
Request Definition
[request_definition]
r = sub, obj, act
[request_definition]
ではアクセス判定要求(access request)の入力となるモデルを定義する。ACLモデル定義のように、たいていの場合は sub
(アクセス実行者)、obj
(アクセス対象)、act
(アクセス方法)の3つを利用する。
Policy Definition
[policy_definition]
p = sub, obj, act
[policy_definition]
ではポリシーの記述形式を定義する。このモデル定義で「 file1 (obj)
を user1 (sub)
が read (act)
できる」というポリシーを記述すると p, user1, file1, read
となる。
※ Casbinでは現在、policy definitionを1つのみしか定義できない制約がある。
Matcher
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
[machers]
ではアクセス判定要求に合致するポリシーを探す条件式を定義する。アクセス判定要求 r
とポリシー p
それぞれの [request_definition]
で定義したモデルを .
で参照し、条件式を記述する。
ACLモデル定義では、アクセス判定要求の sub
obj
act
の全てが一致するポリシーを合致するものと判定されることになる。
※ Casbinでは現状、matcherを1つのみしか定義できない制約がある。(条件式に算術・論理演算子が使えるので、たいていの場合は1つで十分とのこと。)
Policy Effect
[policy_effect]
e = some(where (p.eft == allow))
[policy_effect]
ではアクセス判定要求に複数のポリシーが合致した場合に、どのように判定を行うかを定義する。
ACLモデル定義では、Matcherの条件式で合致するポリシーのうち eft
が allow
に設定されたものが1つでもある ( some
) 場合に許可判定となる。
この eft
はアクセス不許可ポリシー(ブラックリスト)を定義するときにPolicy Definitionに定義する要素である。ACLモデル定義のように eft
がPolicy Definitionに定義されていない場合は、p.eft
は allow
が設定されている(デフォルト値が allow
)とみなされる。アクセス不許可ポリシーの利用例は、Supported ModelsのDeny-overrideを参照。
Role Based Access Control (RBAC)
RBACに対応するには、ACLのモデル定義から以下の2点を変更すればよい。(参考:RBAC)
Role Definition
[role_definition]
g = _, _
[role_definition]
(オプショナルセクション)ではロールの記述形式を定義する。( [policy_definition]
のロール版と考えると理解しやすい。)
このモデル定義で user1
への role1
割り当てを記述すると g, user1, role1
となる。
Matchers
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
[matchers]
では、Role Definitionを関数として参照して、アクセス判定要求のアクセス実行者 r.sub
(ユーザー)とポリシーのアクセス実行者 p.sub
(ロール)の組み合わせに対応するポリシーが存在するかを判定する。
実装例(Java)
rbac_model.confのモデル定義を読み込み、ロール、ポリシー追加、アクセス要求の判定を行う実装例を紹介する。
/* モデル定義の読み込み */
Enforcer se = new Enforcer(ClassLoader.getSystemResource("rbac_model.conf").getFile());
// マルチスレッドで利用する場合はSyncedEnforcerクラスを使う
// Enforcer se = new SyncedEnforcer(ClassLoader.getSystemResource("rbac_model.conf").getFile());
/* ロール割り当て */
se.addNamedGroupingPolicy("g", "user1", "role1");
// デフォルトのロール(グループ)名 "g" に対して割り当てを行うメソッドも提供されている
//se.addGroupingPolicy("user1", "role1");
//se.addRoleForUser("user1", "role1");
se.addNamedPolicy("p", "role1", "data1", "read");
// デフォルトのポリシー名 "p" に対してポリシー追加を行うメソッドも提供されている
se.addPolicy("role1", "data1", "read");
/* アクセス要求判定 */
if (se.enforce("user1", "data1", "read")) {
System.out.println("user1 can read data1.");
}
if (se.enforce("role1", "data1", "read")) {
System.out.println("role1 can read data1.");
}
/* ユーザーのロール取得 */
List<String> roleList = se.getRolesForUser("user1");
System.out.println("user1 has " + roleList + " roles.");
実行結果
user1 can read data1.
role1 can read data1.
user1 has [role1] roles.