Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions examples/rbac_with_abac_rule_model.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[request_definition]
r = sub, obj, act, ctx

[policy_definition]
p = sub, obj, act, ctx_rule, eft

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) && (r.obj == p.obj) && (r.act == p.act || p.act == "*") && (p.ctx_rule == "noRule" || eval(p.ctx_rule))
14 changes: 14 additions & 0 deletions examples/rbac_with_abac_rule_policy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
p, admin, data1, read, noRule, allow
p, admin, data1, read, r.ctx.age < 18 || r.ctx.type == 'minor', deny

p, admin, data2, write, noRule, allow
p, admin, data2, write, r.ctx.network == 'http', deny

p, admin, data3, *, noRule, allow

p, user, data4, read, noRule, allow
p, user, data4, read, r.ctx.RiskStatus == 'high', deny

g, alice, admin
g, alice, user
g, bob, admin
58 changes: 58 additions & 0 deletions src/test/java/org/casbin/jcasbin/main/AbacAPIUnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import static org.casbin.jcasbin.main.TestUtil.testDomainEnforce;
import static org.casbin.jcasbin.main.TestUtil.testEnforce;
import static org.casbin.jcasbin.main.TestUtil.testRBACWithABACRuleEnforce;

public class AbacAPIUnitTest {
@Test
Expand Down Expand Up @@ -79,6 +80,63 @@ public void testABACMapRequest() {
testEnforce(e, "bob", data2, "write", true);
}

@Test
public void testRBACWithABACRule() {
// rbac_with_abac_rule_model combines RBAC (g) with ABAC context rules (p.ctx_rule).
// The matcher evaluates a context rule as a per-request allow/deny filter.
//
// Ported from casbin/rbac_with_abac_rule_test.go (Go). In jcasbin (Aviator 5.9.0)
// `null < 18` evaluates to true, so an empty HashMap would incorrectly trip the
// data1/read deny rule. The Go test sidesteps the same problem in govaluate
// (which throws on missing keys) by always supplying a neutral context; we do
// the same here so the two test suites stay assertion-compatible.
Enforcer e = new Enforcer(
"examples/rbac_with_abac_rule_model.conf",
"examples/rbac_with_abac_rule_policy.csv"
);

Map<String, Object> neutralCtx = makeRBACABACCtx(100, "adult", "https", "low");
Map<String, Object> minorCtx = makeRBACABACCtx(18, "minor", "https", "low");
Map<String, Object> httpCtx = makeRBACABACCtx(100, "adult", "http", "low");
Map<String, Object> highRiskCtx = makeRBACABACCtx(100, "adult", "https", "high");

// alice has roles {admin, user}; bob has role {admin}.

// admin/data1/read: allow under noRule, deny when context matches r.ctx.age < 18 || r.ctx.type == "minor".
testRBACWithABACRuleEnforce(e, "alice", "data1", "read", neutralCtx, true);
testRBACWithABACRuleEnforce(e, "alice", "data1", "read", minorCtx, false);

// admin/data2: no policy for "read" so it is denied; "write" is allowed under noRule
// and denied when r.ctx.network == "http".
testRBACWithABACRuleEnforce(e, "alice", "data2", "read", neutralCtx, false);
testRBACWithABACRuleEnforce(e, "alice", "data2", "write", neutralCtx, true);
testRBACWithABACRuleEnforce(e, "alice", "data2", "write", httpCtx, false);

// admin/data3/* : wildcard action matches any act, allowed under noRule.
testRBACWithABACRuleEnforce(e, "alice", "data3", "read", neutralCtx, true);
testRBACWithABACRuleEnforce(e, "alice", "data3", "write", neutralCtx, true);

// user/data4/read: allowed under noRule, denied when r.ctx.RiskStatus == "high".
testRBACWithABACRuleEnforce(e, "alice", "data4", "read", neutralCtx, true);
testRBACWithABACRuleEnforce(e, "alice", "data4", "read", highRiskCtx, false);

// bob is admin only, so he can use admin policies but not user policies.
testRBACWithABACRuleEnforce(e, "bob", "data1", "read", neutralCtx, true);
testRBACWithABACRuleEnforce(e, "bob", "data4", "read", neutralCtx, false);

// Unknown resource has no matching policy -> denied.
testRBACWithABACRuleEnforce(e, "alice", "data5", "read", neutralCtx, false);
}

private static Map<String, Object> makeRBACABACCtx(int age, String typ, String network, String risk) {
Map<String, Object> ctx = new HashMap<>();
ctx.put("age", age);
ctx.put("type", typ);
ctx.put("network", network);
ctx.put("RiskStatus", risk);
return ctx;
}

public static class TestEvalRule {
private String name;
private int age;
Expand Down
4 changes: 4 additions & 0 deletions src/test/java/org/casbin/jcasbin/main/TestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ static void testEnforceWithContext(Enforcer e, EnforceContext enforceContext, Ob
assertEquals(res, e.enforce(enforceContext, sub, obj, act));
}

static void testRBACWithABACRuleEnforce(Enforcer e, Object sub, Object obj, String act, Map<String, Object> ctx, boolean res) {
assertEquals(res, e.enforce(sub, obj, act, ctx));
}

static void testDomainEnforce(Enforcer e, Object sub, Object dom, Object obj, Object act, boolean res) {
assertEquals(res, e.enforce(sub, dom, obj, act));
}
Expand Down