From d201f5b4225e6a37be90144dee9589143124c986 Mon Sep 17 00:00:00 2001 From: Liao Xin <93535922+liewstar@users.noreply.github.com> Date: Tue, 12 Nov 2024 00:28:44 +0800 Subject: [PATCH] feat: add RBAC APIs (#19) --- examples/basic_without_resources_model.conf | 11 +++ examples/basic_without_resources_policy.csv | 2 + examples/keymatch_model.conf | 11 +++ examples/rbac_with_hierarchy_policy.csv | 9 ++ examples/rbac_with_multiple_policy_model.conf | 16 ++++ examples/rbac_with_multiple_policy_policy.csv | 6 ++ examples/rbac_with_pattern_model.conf | 15 ++++ examples/rbac_with_pattern_policy.csv | 20 +++++ src/test/java/org/casbin/ClientTest.java | 83 ++++++++++++++++++- 9 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 examples/basic_without_resources_model.conf create mode 100644 examples/basic_without_resources_policy.csv create mode 100644 examples/keymatch_model.conf create mode 100644 examples/rbac_with_hierarchy_policy.csv create mode 100644 examples/rbac_with_multiple_policy_model.conf create mode 100644 examples/rbac_with_multiple_policy_policy.csv create mode 100644 examples/rbac_with_pattern_model.conf create mode 100644 examples/rbac_with_pattern_policy.csv diff --git a/examples/basic_without_resources_model.conf b/examples/basic_without_resources_model.conf new file mode 100644 index 0000000..f61bd71 --- /dev/null +++ b/examples/basic_without_resources_model.conf @@ -0,0 +1,11 @@ +[request_definition] +r = sub, act + +[policy_definition] +p = sub, act + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = r.sub == p.sub && r.act == p.act \ No newline at end of file diff --git a/examples/basic_without_resources_policy.csv b/examples/basic_without_resources_policy.csv new file mode 100644 index 0000000..c861941 --- /dev/null +++ b/examples/basic_without_resources_policy.csv @@ -0,0 +1,2 @@ +p, alice, read +p, bob, write \ No newline at end of file diff --git a/examples/keymatch_model.conf b/examples/keymatch_model.conf new file mode 100644 index 0000000..4f86ba8 --- /dev/null +++ b/examples/keymatch_model.conf @@ -0,0 +1,11 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act) \ No newline at end of file diff --git a/examples/rbac_with_hierarchy_policy.csv b/examples/rbac_with_hierarchy_policy.csv new file mode 100644 index 0000000..8b22fa5 --- /dev/null +++ b/examples/rbac_with_hierarchy_policy.csv @@ -0,0 +1,9 @@ +p, alice, data1, read +p, bob, data2, write +p, data1_admin, data1, read +p, data1_admin, data1, write +p, data2_admin, data2, read +p, data2_admin, data2, write +g, alice, admin +g, admin, data1_admin +g, admin, data2_admin \ No newline at end of file diff --git a/examples/rbac_with_multiple_policy_model.conf b/examples/rbac_with_multiple_policy_model.conf new file mode 100644 index 0000000..6f10c97 --- /dev/null +++ b/examples/rbac_with_multiple_policy_model.conf @@ -0,0 +1,16 @@ +[request_definition] +r = user, thing, action + +[policy_definition] +p = role, thing, action +p2 = role, action + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.user, p.role) && r.thing == p.thing && r.action == p.action +m2 = g(r.user, p2.role) && r.action == p.action + +[role_definition] +g = _,_ diff --git a/examples/rbac_with_multiple_policy_policy.csv b/examples/rbac_with_multiple_policy_policy.csv new file mode 100644 index 0000000..19abad4 --- /dev/null +++ b/examples/rbac_with_multiple_policy_policy.csv @@ -0,0 +1,6 @@ +p, user, /data, GET +p, admin, /data, POST +p2, user, view +p2, admin, create +g, admin, user +g, alice, admin \ No newline at end of file diff --git a/examples/rbac_with_pattern_model.conf b/examples/rbac_with_pattern_model.conf new file mode 100644 index 0000000..84580d9 --- /dev/null +++ b/examples/rbac_with_pattern_model.conf @@ -0,0 +1,15 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[role_definition] +g = _, _ +g2 = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.sub, p.sub) && g2(r.obj, p.obj) && regexMatch(r.act, p.act) \ No newline at end of file diff --git a/examples/rbac_with_pattern_policy.csv b/examples/rbac_with_pattern_policy.csv new file mode 100644 index 0000000..140c2c8 --- /dev/null +++ b/examples/rbac_with_pattern_policy.csv @@ -0,0 +1,20 @@ +p, alice, /pen/1, GET +p, alice, /pen2/1, GET +p, book_admin, book_group, GET +p, pen_admin, pen_group, GET +p, *, pen3_group, GET +p, /book/admin/:id, pen4_group, GET +p, /book/leader/2, pen4_group, POST +g, /book/user/:id, /book/admin/1 +g, /book/user/:id, /book/leader/2 +g, alice, book_admin +g, bob, pen_admin +g, cathy, /book/1/2/3/4/5 +g, cathy, pen_admin +g2, /book/*, book_group +g2, /book/:id, book_group +g2, /pen/:id, pen_group +g2, /book2/{id}, book_group +g2, /pen2/{id}, pen_group +g2, /pen3/:id, pen3_group +g2, /pen4/:id, pen4_group \ No newline at end of file diff --git a/src/test/java/org/casbin/ClientTest.java b/src/test/java/org/casbin/ClientTest.java index 4557a30..8be955c 100644 --- a/src/test/java/org/casbin/ClientTest.java +++ b/src/test/java/org/casbin/ClientTest.java @@ -3,6 +3,10 @@ import org.apache.commons.cli.ParseException; import org.junit.Test; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + import static org.junit.Assert.assertEquals; public class ClientTest { @@ -112,7 +116,7 @@ public void testCustomFunction() throws ParseException { assertEquals(Client.run(new String[]{"enforce", "-m", model, "-p", "examples/keymatch_policy.csv", "-AF", func, "cathy", "/cathy_data", "POST"}), "{\"allow\":true,\"explain\":null}"); assertEquals(Client.run(new String[]{"enforce", "-m", model, "-p", "examples/keymatch_policy.csv", "-AF", func, "cathy", "/cathy_data", "DELETE"}), "{\"allow\":false,\"explain\":null}"); - } + } @Test public void testEnforce() { @@ -216,7 +220,6 @@ public void testManagementApi() { assertEquals(Client.run(new String[]{"updatePolicy", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice,data1,write","alice,data1,read"}), "{\"allow\":true,\"explain\":null}"); - assertEquals(Client.run(new String[]{"updateNamedGroupingPolicy", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "g", "alice,data2_admin","admin,data4_admin"}), "{\"allow\":true,\"explain\":null}"); assertEquals(Client.run(new String[]{"updateNamedGroupingPolicy", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "g", "admin,data4_admin","alice,data2_admin"}), "{\"allow\":true,\"explain\":null}"); @@ -235,4 +238,80 @@ public void testManagementApi() { } + @Test + public void testRBACApi () { + assertEquals(Client.run(new String[]{"getRolesForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice"}), "{\"allow\":null,\"explain\":[\"data2_admin\"]}"); + + assertEquals(Client.run(new String[]{"getUsersForRole", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "data2_admin"}), "{\"allow\":null,\"explain\":[\"alice\"]}"); + + assertEquals(Client.run(new String[]{"hasRoleForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice", "data2_admin"}), "{\"allow\":true,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"deleteRoleForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice", "data2_admin"}), "{\"allow\":true,\"explain\":null}"); + resetRBACPolicyFile(); + + assertEquals(Client.run(new String[]{"deleteRolesForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice"}), "{\"allow\":true,\"explain\":null}"); + resetRBACPolicyFile(); + + assertEquals(Client.run(new String[]{"deleteUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice"}), "{\"allow\":true,\"explain\":null}"); + resetRBACPolicyFile(); + + assertEquals(Client.run(new String[]{"deleteRole", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "data2_admin"}), "{\"allow\":null,\"explain\":null}"); + resetRBACPolicyFile(); + + assertEquals(Client.run(new String[]{"deletePermission", "-m", "examples/basic_without_resources_model.conf", "-p", "examples/basic_without_resources_policy.csv", "read"}), "{\"allow\":true,\"explain\":null}"); + resetBasicWithResourcesPolicyFile(); + + assertEquals(Client.run(new String[]{"addPermissionForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "bob", "read"}), "{\"allow\":true,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"deletePermissionForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "bob", "read"}), "{\"allow\":true,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"deletePermissionsForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_policy.csv", "alice"}), "{\"allow\":true,\"explain\":null}"); + resetRBACPolicyFile(); + + assertEquals(Client.run(new String[]{"hasPermissionForUser", "-m", "examples/basic_without_resources_model.conf", "-p", "examples/basic_without_resources_policy.csv", "alice", "read"}), "{\"allow\":true,\"explain\":null}"); + + assertEquals(Client.run(new String[]{"getImplicitUsersForRole", "-m", "examples/rbac_with_pattern_model.conf", "-p", "examples/rbac_with_pattern_policy.csv", "book_admin"}), "{\"allow\":null,\"explain\":[\"alice\"]}"); + + assertEquals(Client.run(new String[]{"getImplicitPermissionsForUser", "-m", "examples/rbac_model.conf", "-p", "examples/rbac_with_hierarchy_policy.csv", "alice"}), "{\"allow\":null,\"explain\":[[\"alice\",\"data1\",\"read\"],[\"data1_admin\",\"data1\",\"read\"],[\"data1_admin\",\"data1\",\"write\"],[\"data2_admin\",\"data2\",\"read\"],[\"data2_admin\",\"data2\",\"write\"]]}"); + + + assertEquals(Client.run(new String[]{"getNamedImplicitPermissionsForUser", "-m", "examples/rbac_with_multiple_policy_model.conf", "-p", "examples/rbac_with_multiple_policy_policy.csv", "p2", "alice"}), "{\"allow\":null,\"explain\":[[\"admin\",\"create\"],[\"user\",\"view\"]]}"); + + + + + + + + } + + + public void resetRBACPolicyFile() { + File file = new File("examples/rbac_policy.csv"); + try { + FileWriter writer = new FileWriter(file); + writer.write("p, alice, data1, read\n"); + writer.write("p, bob, data2, write\n"); + writer.write("p, data2_admin, data2, read\n"); + writer.write("p, data2_admin, data2, write\n"); + writer.write("g, alice, data2_admin"); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void resetBasicWithResourcesPolicyFile() { + File file = new File("examples/basic_without_resources_policy.csv"); + try { + FileWriter writer = new FileWriter(file); + writer.write("p, alice, read\n"); + writer.write("p, bob, write"); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + }