Skip to content

Commit

Permalink
feat: add abac with rule and test. (#170)
Browse files Browse the repository at this point in the history
Signed-off-by: stonex <1479765922@qq.com>
  • Loading branch information
sheny1xuan authored Nov 21, 2021
1 parent 64fc8dd commit f9d1a33
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 1 deletion.
26 changes: 25 additions & 1 deletion casbin/enforcer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ bool Enforcer::m_enforce(const std::string& matcher, Scope scope) {
for(auto func : m_user_func_list)
m_func_map.AddFunction(std::get<0>(func), std::get<1>(func), std::get<2>(func));

bool hasEval = HasEval(exp_string);

std::unordered_map<std::string, int> p_int_tokens;
std::vector<std::string>& p_tokens = m_model->m["p"].assertion_map["p"]->tokens;
p_int_tokens.reserve(p_tokens.size());
Expand Down Expand Up @@ -105,7 +107,29 @@ bool Enforcer::m_enforce(const std::string& matcher, Scope scope) {
PushStringPropToObject(m_func_map.scope, "p", p_vals[j], token);
}

m_func_map.Evaluate(exp_string);
if(hasEval) {
auto ruleNames = GetEvalValue(exp_string);
std::unordered_map<std::string, std::string> replacements;
for(auto& ruleName: ruleNames) {
auto ruleNameCpy = EscapeAssertion(ruleName);

bool ok = p_int_tokens.find(ruleNameCpy) != p_int_tokens.end();
if (ok) {
int idx = p_int_tokens[ruleNameCpy];
replacements[ruleName] = p_vals[idx];
} else {
m_log.LogPrint("please make sure rule exists in policy when using eval() in matcher");
return false;
}
}

auto expWithRule = ReplaceEvalWithMap(exp_string, replacements);
m_func_map.Evaluate(expWithRule);

} else {

m_func_map.Evaluate(exp_string);
}

//TODO
// log.LogPrint("Result: ", result)
Expand Down
19 changes: 19 additions & 0 deletions casbin/util/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::s
return replacedExp;
}

// GetEvalValue returns the parameters of function eval
std::vector<std::string> GetEvalValue(std::string s) {
std::vector<std::string> rules;
rules.reserve(10);
std::smatch m;

while (std::regex_search(s, m, evalReg)) {
if (m.empty()) {
return rules;
}
std::string rule = m[1];

rules.push_back(rule);
s = m.suffix();
}

return rules;
}

} // namespace casbin

#endif // EVAL_CPP
2 changes: 2 additions & 0 deletions casbin/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ bool HasEval(const std::string& s);
// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);

// GetEvalValue returns the parameters of function eval
std::vector<std::string> GetEvalValue(std::string s);
} // namespace casbin

#endif
3 changes: 3 additions & 0 deletions include/casbin/casbin_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,9 @@ namespace casbin {

// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);

// GetEvalValue returns the parameters of function eval
std::vector<std::string> GetEvalValue(std::string s);

// Exception class for Casbin Adapter Exception.
class CasbinAdapterException : std::logic_error {
Expand Down
2 changes: 2 additions & 0 deletions tests/config_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ static const std::string priority_model_path = relative_path + "/examples/priori
static const std::string priority_policy_path = relative_path + "/examples/priority_policy.csv";

static const std::string abac_model_path = relative_path + "/examples/abac_model.conf";
static const std::string abac_rule_model_path = relative_path + "/examples/abac_rule_model.conf";
static const std::string abac_rule_policy_path = relative_path + "/examples/abac_rule_policy.csv";
52 changes: 52 additions & 0 deletions tests/model_enforcer_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ casbin::Scope InitializeParamsWithDomains(const std::string& sub, const std::str
return scope;
}

casbin::Scope InitializeParamsWithJson(std::shared_ptr<nlohmann::json> sub, std::string obj, std::string act) {
casbin::Scope scope = casbin::InitializeScope();
casbin::PushObject(scope, "r");

casbin::PushStringPropToObject(scope, "r", obj, "obj");
casbin::PushStringPropToObject(scope, "r", act, "act");

casbin::PushObject(scope, "sub");
casbin::PushObjectPropFromJson(scope, *sub, "sub");
casbin::PushObjectPropToObject(scope, "r", "sub");

return scope;
}

void TestEnforce(casbin::Enforcer& e, casbin::Scope& scope, bool res) {
ASSERT_EQ(res, e.Enforce(scope));
}
Expand Down Expand Up @@ -523,6 +537,44 @@ TEST(TestModelEnforcer, TestABACModelWithJson) {
ASSERT_TRUE(e.Enforce(listParams));
ASSERT_TRUE(e.Enforce(vectorParams));
}

std::shared_ptr<nlohmann::json> newTestSubject(std::string name, int age) {
nlohmann::json sub = {{"Name", name}, {"Age", age}};
return std::make_shared<nlohmann::json>(sub);
}

TEST(TestModelEnforcer, TestABACPolicyWithJson) {
casbin::Enforcer e(abac_rule_model_path, abac_rule_policy_path);

auto sub1 = newTestSubject("alice", 16);
auto sub2 = newTestSubject("alice", 20);
auto sub3 = newTestSubject("alice", 65);

auto scope = InitializeParamsWithJson(sub1, "/data1", "read");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub1, "/data2", "read");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub1, "/data1", "write");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub1, "/data2", "write");
TestEnforce(e, scope, true);
scope = InitializeParamsWithJson(sub2, "/data1", "read");
TestEnforce(e, scope, true);
scope = InitializeParamsWithJson(sub2, "/data2", "read");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub2, "/data1", "write");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub2, "/data2", "write");
TestEnforce(e, scope, true);
scope = InitializeParamsWithJson(sub3, "/data1", "read");
TestEnforce(e, scope, true);
scope = InitializeParamsWithJson(sub3, "/data2", "read");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub3, "/data1", "write");
TestEnforce(e, scope, false);
scope = InitializeParamsWithJson(sub3, "/data2", "write");
TestEnforce(e, scope, false);
}
/*
type testCustomRoleManager struct {}
Expand Down

0 comments on commit f9d1a33

Please sign in to comment.