casbin / pycasbin Goto Github PK
View Code? Open in Web Editor NEWAn authorization library that supports access control models like ACL, RBAC, ABAC in Python
Home Page: https://casbin.org
License: Apache License 2.0
An authorization library that supports access control models like ACL, RBAC, ABAC in Python
Home Page: https://casbin.org
License: Apache License 2.0
hi,
I have a series of relationships set up like this:
User
id
customer_id
Customer
id
distributor_id
Distributor
id
I have an endpoint like /user/, and I want to restrict users to only be able to see other users whose user.customer.distributor_id is the same as their user.customer.distributor_id
How would I go about setting up a rule for a scenario like this? Is it even possible to abstract these kinds of relationships into an ABAC schema?
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, "role_root") || (g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act)
p, data1_read, data1, read
p, data2_read, data2, read
p, data2_write, data2, write
g, alice, data2_read
g, bob, role_root
import casbin
e = casbin.Enforcer("model.conf", "policy.csv")
sub = "bob" # the user that wants to access a resource.
obj = "data2" # the resource that is going to be accessed.
act = "write" # the operation that the user performs on the resource.
e.enforce(sub, obj, act)
e.get_implicit_permissions_for_user('alice')
e.get_implicit_permissions_for_user('bob')
I expect e.get_implicit_permissions_for_user('bob')
to return all permissions defined, but it is empty.
Running PyCasbin in a production environment with a decent size of rules (~30k) pycasbin starts to fall apart. Looping over the policy to find out if each rule matches only to find out that r.obj != s.obj
is pretty painful.
Without completely obliterating the internals of casbin to hard code certain checks exist and using things like sets or dictionaries to get the performance up, filtered queries are very much required.
File : rbac/default_role_manager/role_manager.py
Line : 15~16
def has_role(self, name):
return name in self.all_roles.keys()
Error : In python3 you can't iterate on a dict
Fix :
- return name in self.all_roles.keys()
+ return name in list(self.all_roles.keys())
while running the given example geeting the above error
Model config:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, eft
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)
Code:
import casbin
enforcer = casbin.Enforcer("casbin_model.conf")
enforcer.add_named_policy("p", "sub1", "obj1", "read", "deny")
enforcer.add_named_policy("p", "group1", "obj1", "read", "allow")
enforcer.add_named_grouping_policy('g', 'sub1', 'group1')
print('Objects:', enforcer.get_all_objects())
print('Subjects:', enforcer.get_all_subjects())
print('Actions:', enforcer.get_all_actions())
Here is output:
Objects: ['obj1', 'group1']
Subjects: ['sub1', 'group1']
Traceback (most recent call last):
File "test_casbin.py", line 10, in <module>
print('Actions:', enforcer.get_all_actions())
File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/management_enforcer.py", line 27, in get_all_actions
return self.get_all_named_actions('p')
File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/management_enforcer.py", line 31, in get_all_named_actions
return self.model.get_values_for_field_in_policy('p', ptype, 2)
File "/Users/namnh/.venvs/casbin/lib/python3.7/site-packages/casbin/model/policy.py", line 100, in get_values_for_field_in_policy
values.append(rule[field_index])
IndexError: list index out of range
It shows wrong object list, right list only has obj1
, and does not has group1
. And get_all_actions() is failed.
I found problem is in Assertion
class, which has policy
attribute. It is class attribute, so it is shared between instances. So when you add policy p
, it is also added to g
.
Debug:
print(enforcer.model.model['p']['p'].policy)
print(enforcer.model.model['g']['g'].policy)
print(id(enforcer.model.model['p']['p'].policy))
print(id(enforcer.model.model['g']['g'].policy))
Output:
[['sub1', 'obj1', 'read', 'deny'], ['group1', 'obj1', 'read', 'allow'], ['sub1', 'group1']]
[['sub1', 'obj1', 'read', 'deny'], ['group1', 'obj1', 'read', 'allow'], ['sub1', 'group1']]
4411842880
4411842880
I am sure there must be some features or functionalities which are not in track with casbin-core, why should we not track those features and bring them here and implement it.
Issue 66 added support for filtered policies and calls the load_filtered_policy
method of an adapter instance. Should the base Adapter class in casbin/persist/adapter.py be updated to include the method load_filtered_policy
?
Hi,
I have a use case where I need to obtain all the implicit roles of a user. As per casbin documentation, this operation is GetImplicitPermissionsForUser(). However, I cannot find the python counterpart of this function in the source code. Is this method implemented?
Thanks!
I find some supported adapters such as SQLAlchemy Adapter and Peewee Adapter in doc. How about adapters for django web frame?
I tried using py.test but get module not found errors. Can you please let me know how I can run tests and see coverage?
https://github.com/casbin/pycasbin/blob/master/.travis.yml#L11
Coverage only run test in 3 files test_enforcer.py
, test_management_api.py
, test_rbac_api.py
, does not run test in sub directories.
Enforcer load policy into memory, if there have multiple instances of enforcer and they modify policy, how can they keep sync?
Make enforcer singleton should solve this problem?
Or can you explain why enforcer shouldn't be singleton?
I ran into this issue because pycasbin was causing problems with test module discovery using pytest.
Running pip install casbin
then pip uninstall casbin
illustrates the problem:
Uninstalling casbin-0.8.2:
Would remove:
~/.virtualenvs/casbin/README.md
~/.virtualenvs/casbin/lib/python3.7/site-packages/casbin-0.8.2.dist-info/*
~/.virtualenvs/casbin/lib/python3.7/site-packages/casbin/*
~/.virtualenvs/casbin/lib/python3.7/site-packages/tests/*
That last line indicates that the tests are being placed directly into site-packages, which is incorrect and causes errors in test discovery.
We've been growing our test data set to about 2.5k rules in the policy set, which is making calls to the enforcer quite slow. Is there something that can be done to speed things up, or did I just pick a terrible model for performance?
model:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && r.act == p.act
example policy:
g,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/group:members
p,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/info,edit
p,act.io/org:acmecorp/group:admins,act.io/org:acmecorp/group:members,manage
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp,view
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp/plan:*,view
p,act.io/org:acmecorp/group:members,act.io/org:acmecorp/plan:*,create
g,act.io/user:cde7860e-5459-413c-969a-9536edbb1980,act.io/org:acmecorp/group:admins
g,act.io/user:554a09e6-2d6a-406d-aef0-2ea0e09a0e9f,act.io/org:acmecorp/group:members
g,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/group:members
p,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/info,edit
p,act.io/org:acmecorp/campaign:1/group:admins,act.io/org:acmecorp/campaign:1/group:members,manage
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1,view
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/submission:*,approve
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,create
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,read
p,act.io/org:acmecorp/campaign:1/group:members,act.io/org:acmecorp/campaign:1/version:*,update
g,act.io/user:cde7860e-5459-413c-969a-9536edbb1980,act.io/org:acmecorp/campaign:1/group:admins
g,act.io/user:3ae34b92-a0f8-4b3f-a7bd-877c9ba303a4,act.io/org:acmecorp/campaign:1/group:members
g,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/group:members
p,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/info,edit
p,act.io/org:acmecorp/campaign:2/group:admins,act.io/org:acmecorp/campaign:2/group:members,manage
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2,view
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/submission:*,approve
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,create
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,read
p,act.io/org:acmecorp/campaign:2/group:members,act.io/org:acmecorp/campaign:2/version:*,update
g,act.io/user:925d614b-12f4-4048-91c5-adf9f278dcb9,act.io/org:acmecorp/campaign:2/group:admins
g,act.io/user:6e48501a-eff8-4ec7-8215-638c7726e163,act.io/org:acmecorp/campaign:2/group:members
when I use allow-and-deny model in my project , fllow is my define :
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, 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 || p.obj == "" || keyMatch(r.obj, p.obj) || keyMatch2(r.obj, p.obj)) && (r.act == p.act || p.act == "")
I want to use keyMatch2 func to match the “:” expression ,but when I use the '/' to represent the home page, the authority management loses control, and all the URLs under the same user can be accessed
Here is my definition of police:
p, anonymous, /users/index/, *, allow
p, alice, /, *, allow
alice can access any url! But it seems to work in the editor!
use python flask+sqlalchemy-adapter
My model.conf is
[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 && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
Policy is
p, ops, /process/cancel, POST
p, ops, /process, POST
and Request is
ops, /process/approve, POST
the result should False, but in fact it is:
2020-07-20 13:53:23,985 - INFO - Request: ops, /process/approve, POST ---> True
Did I code something wrong?
Hi @techoner , currently, we use 0.5
, 0.4
versions. This is not the best practice. We should follow the Semantic Versioning, simply MAJOR.MINOR.PATCH
. So it should be 0.5.0
instead of 0.5
. I found most of the packages in: https://pypi.org follow this design.
I think we can do this for next release.
One way I can find is I need to maintain all the tenants(domain) outside casbin and call get_roles_for_user_in_domain . Is there any other efficient away?
Hello. In this doc page, the maintainers of Casbin seem to imply that you can choose/write your own RoleManager
class. However, this seems to be hardcoded in. Is there a way to supply a custom class? Can one be made with relative ease?
pycasbin/casbin/core_enforcer.py
Lines 65 to 72 in a915dce
Before and after login, the debug log printed by caspin shows that the users accessed are anonymous. In theory, after the authentication is successful, the authenticated user information should be displayed. How should this inform the user to obtain the setting of caspin and identify the authenticated user normally
[2020-03-27 17:34:42,218] INFO in views: 登出成功
127.0.0.1 - - [27/Mar/2020 17:34:42] "GET /auth/logout/ HTTP/1.1" 302 -
2020-03-27 17:34:42,230 - INFO - Request: anonymous, /auth/, GET ---> True
127.0.0.1 - - [27/Mar/2020 17:34:42] "GET /auth/ HTTP/1.1" 200 -
2020-03-27 17:34:44,792 - INFO - Request: anonymous, /auth/login/, GET ---> True
127.0.0.1 - - [27/Mar/2020 17:34:44] "GET /auth/login/ HTTP/1.1" 200 -
2020-03-27 17:34:52,642 - INFO - Request: anonymous, /auth/login/, POST ---> True
[2020-03-27 17:34:52,680] INFO in views: test login sucess
question
I am using the model file default rbac_with_domains_model.conf
and policy file rbac_with_domains_policy.csv
loading it as
import casbin
x = casbin.Enforcer('<model file>','<conf file>')
I am assigning a new role for the user to it as
y.add_role_for_user_in_domain('prashant','admin', 'domain1')
now I want to save this policy, so I am doing
x.save_policy()
but this is not saving my new added policy in a file.
when I see the save_policy
code in codebase no procedure to save is written ie
def save_policy(self):
pass
my question is, shouldn't it be a new method to save all the policy in the file be there? or I am doing something wrong with my approach. if I am doing wrong please help me to correct it.
As the title , it point out that i don't have the method e.get_roles('alice'), what happen whit this?If it's convenient for you, please answer me ,or can you provide a complete example of pycasbin ? Thankyou!
I'm using pycasbin, with sqlalchemy-adapter as adapter. Policies are stored in mysql.
When I'm testing, with about 20 policies. everything is perfect.
After I stored 30000+ policies in mysql, queries become very slow, about 3-4 seconds per query.
Here is the example code.
import casbin
from casbin import persist
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from casbin.model import Model
Base = declarative_base()
MYSQL_CONF = "mysql+pymysql://.........."
TABLE_NAME = 'auth_rule'
DOM = 'test'
LOG_ENABLED = False
class CasbinRule(Base):
__tablename__ = TABLE_NAME
id = Column(Integer, primary_key=True)
ptype = Column(String(255))
v0 = Column(String(255))
v1 = Column(String(255))
v2 = Column(String(255))
v3 = Column(String(255))
v4 = Column(String(255))
v5 = Column(String(255))
class Adapter(persist.Adapter):
"""the interface for Casbin adapters."""
def __init__(self, dsn):
self._engine = create_engine(dsn)
session = sessionmaker(bind=self._engine)
self._session = session()
Base.metadata.create_all(self._engine)
def load_policy(self, model):
"""loads all policy rules from the storage."""
lines = self._session.query(CasbinRule).all()
for line in lines:
text = line.ptype
if line.v0:
text = text + ', ' + line.v0
if line.v1:
text = text + ', ' + line.v1
if line.v2:
text = text + ', ' + line.v2
if line.v3:
text = text + ', ' + line.v3
if line.v4:
text = text + ', ' + line.v4
if line.v5:
text = text + ', ' + line.v5
persist.load_policy_line(text, model)
def _save_policy_line(self, ptype, rule):
line = CasbinRule(ptype=ptype)
if len(rule) > 0:
line.v0 = rule[0]
if len(rule) > 1:
line.v1 = rule[1]
if len(rule) > 2:
line.v2 = rule[2]
if len(rule) > 3:
line.v3 = rule[3]
if len(rule) > 4:
line.v4 = rule[4]
if len(rule) > 5:
line.v5 = rule[5]
self._session.add(line)
self._session.commit()
def save_policy(self, model):
"""saves all policy rules to the storage."""
for sec in ["p", "g"]:
if sec not in model.model.keys():
continue
for ptype, ast in model.model[sec].items():
for rule in ast.policy:
self._save_policy_line(ptype, rule)
return True
def __del__(self):
self._session.close()
class Auth:
mysql_conf = MYSQL_CONF
def __init__(self):
self.adapter = Adapter(self.mysql_conf)
self.new_model_conf = Model()
self.new_model_conf.add_def("r","r","sub, obj, act, dom") #
self.new_model_conf.add_def("p","p","sub, obj, act, dom") #
self.new_model_conf.add_def("g","g","_, _")
self.new_model_conf.add_def("g","g2","_, _, _") #
self.new_model_conf.add_def("g","g3","_, _, _") #
self.new_model_conf.add_def("e","e","some(where (p.eft == allow))")
self.new_model_conf.add_def("m","m",'g(r.sub, p.sub) && (g2(r.obj, p.obj, r.dom) || p.obj == "*") && (g3(r.act, p.act, r.dom) || p.act == "*") && r.dom == p.dom')
self.e = casbin.Enforcer(self.new_model_conf, self.adapter, LOG_ENABLED)
def check_auth(self, sub, obj, act, dom=DOM):
sub = str(sub)
obj = str(obj)
act = str(act)
dom = str(dom)
return self.e.enforce(sub, obj, act, dom):
######CasbinRule and Adapter are from github project:
######pycasbin/sqlalchemy-adapter/casbin_sqlalchemy_adapter/adapter.py
auth = Auth()
result = auth.e.enforce('1234','2345','read', 'test')
Hi metors, sorry for late. Right now is there any chances about taking part in GSoC in pycasbin project ?
Hi,
I'm wondering about best practice in pycasbin.
Example 1
Say I have a DB table of stores:
# | id | name | description |
---|---|---|---|
1 | 1 | Store 1 | Store 1 |
2 | 2 | Store 2 | Store 2 |
3 | 3 | Store 3 | Store 3 |
4 | 4 | Store 4 | Store 4 |
5 | 5 | Store 5 | Store 5 |
A DB table of policies:
# | id | ptype | v0 | v1 | v2 | v3 | v4 | v5 |
---|---|---|---|---|---|---|---|---|
1 | 1 | p | alice | Store 1 | read | NULL | NULL | NULL |
2 | 2 | p | alice | Store 2 | write | NULL | NULL | NULL |
3 | 3 | p | alice | Store 3 | write | NULL | NULL | NULL |
4 | 4 | p | alice | Store 4 | read | NULL | NULL | NULL |
Would this be the best way to get a list of stores that Alice has access to?:
permissions = e.get_implicit_permissions_for_user("alice")
for permission in permissions:
result = session.query(Store).filter(Store.name == permission[1]).first()
print(f"Store Name: {result.name} - Store Description: {result.description}")
Example 2
As another example; if I wanted to use DB table ID's instead of Store names, would I use the table name as a domain?
# | id | ptype | v0 | v1 | v2 | v3 | v4 | v5 |
---|---|---|---|---|---|---|---|---|
2 | 3 | p | Store Manager | Store | 1 | write | NULL | NULL |
3 | 4 | p | Store Manager | Store | 2 | write | NULL | NULL |
4 | 5 | p | Store Manager | Store | 3 | write | NULL | NULL |
5 | 6 | p | Store Manager | Store | 4 | write | NULL | NULL |
14 | 16 | g | alice | Store Manager | Store | NULL | NULL | NULL |
permissions = e.get_implicit_permissions_for_user("Alice", "Store")
for permission in permissions:
result = session.query(Store).filter(Store.id == permission[2]).first()
print(f"Store Name: {result.name} - Store Description: {result.description}")
One last question: I am using the casbin_sqlalchemy_adapter, what are all of the v0-v5 columns for?
Thanks for any feedback :-)
The logging code currently assumes all parameters are strings, when passing objects (for instance when using ABAC) an error is raised:
casbin/enforcer.py", line 289, in enforce
req_str = req_str + ", ".join(rvals)
TypeError: sequence item 0: expected str instance, dict found
See: casbin/Casbin.NET#37
There's an issue with the pypi repository.
$ virtualenv --python=python3 venv && source ./venv/bin/activate && pip install casbin
Already using interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /repos/agosto/gcp/project_template/venv/bin/python3
Also creating executable in /repos/agosto/gcp/project_template/venv/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
Collecting casbin
Could not find a version that satisfies the requirement casbin (from versions: )
No matching distribution found for casbin
https://github.com/casbin/pycasbin
In the following introduction:
Besides the static policy file, Casbin also provides API for permission management at run-time. For example, You can get all the roles assigned to a user as below:
roles = e.get_roles("alice")
There is no such method like get_roles("alice")! use get_roles_for_user("alice") instead!
Let's say that in a policy, instead of providing a boolean kind of right, it grants some amount of a resource. For instance
p, sub, act, obj, amount
Is it possible to define a model so I get that amount as a result of calling Enforce instead of a true/false effect?
Hello, I have read the sources and have few questions.
Is this project really production ready? I have found hard coded effect expressions in different parts of source code. I thought that it is implemented using some dsl interpretation but there are at most 4 cases that can be used as effects (see effectors module). That looks very strange to me.
The official paper https://arxiv.org/pdf/1903.09756.pdf states that casbin is implemented in lua and used in interpreter-in-interpreter way. In fact all casbin implementations are just straightforward ports from golang version. Can we trust this paper? Also the benchmarks section of this paper has nothing in common with actual implementation of pycasbin.
Some parts of code look not optimized and not pythonic, for example a function that removes duplicates from a string array.
Wrapping up: casbin is great on paper but i’m a bit worried if I really can use it in production due to questions above.
P.S.: I appreciate the work been done on this project and thank you for making it open sourced.
With filtered policy support available it would be awesome to have this available in a general release rather than needing to us git repos.
import casbin
def test():
enforcer = casbin.Enforcer('path/to/model.conf',
'path/to/policy.csv')
added = enforcer.add_policy('alice', 'data1', 'read')
result = enforcer.enforce('alice', 'data1', 'read')
print('result: {}'.format(result))
if __name__ == "__main__":
test()
output:
Traceback (most recent call last):
File "C:/Users/Ken/PycharmProjects/casbin_test/app1/test.py", line 22, in <module>
test()
File "C:/Users/Ken/PycharmProjects/casbin_test/app1/test.py", line 14, in test
added = enforcer.add_policy('alice', 'data1', 'read')
File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\management_api.py", line 92, in add_policy
return self.add_named_policy('p', *params)
File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\management_api.py", line 110, in add_named_policy
rule_added = self._add_policy('p', ptype, policy)
File "C:\Users\Ken\PycharmProjects\casbin_test\venv\lib\site-packages\casbin\internal_api.py", line 5, in _add_policy
rule_added = self.model.add_policy(sec, ptype, rule)
AttributeError: 'Model' object has no attribute 'add_policy'
PyCasbin currently sets up its own logger:
https://github.com/casbin/pycasbin/tree/master/casbin/log
Since pycasbin is a supporting module to an application it should differ the logging setup to the application that would leverage the module. This is done by the module class setting self.logger = logging.getLogger()
to get the root logger.
Then when calls are made with self.logger.[method]([message])
it will either log as expected or if no logger is gotten then it just wont log as expected. Currently there is no way to override the default pycasbin log level because it is statically set and if you disable the logger you disable all log messages. There is also no good way to override the enforcer class logger since it is not class property.
https://github.com/casbin/pycasbin/blob/master/casbin/log/default_logger.py#L11
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L1
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L25
https://github.com/casbin/pycasbin/blob/master/casbin/core_enforcer.py#L289
The current behavior of pycasbin results in duplicate logs when the application sets up a logger of its own.
2020-10-13 15:54:01,688 - INFO - Request: isadmin, /api/v1/applications, GET ---> True
[2020-10-13 15:54:01,688] INFO in default_logger: Request: isadmin, /api/endpoint, GET ---> True
I will open a PR for these changes when I can unless someones gets to it before me.
pymongo
performance is better than mongoengine
(Please note I had submitted this issue on casbin, and was told to move it to pycasbin, which I am doing verbatim).
We have profiled a simple Casbin enforcement call over an (admittedly abnormally large) policy set. We did this with a go and a python script. The python version takes about 30x the time per enforcement call (1.5 seconds on an i5).
2 things I would like to ask the authors (who suggested I opened this issue):
m = casbin.model.Model()
a = casbin.persist.Adapter()
e = casbin.Enforcer(m, a)
e.set_role_manager(casbin.rbac.default_role_manager.RoleManager(10))
m.add_def("r", "r", "sub, obj, act")
m.add_def("p", "p", "sub, obj, act")
m.add_def("g", "g", "_, _")
m.add_def("e", "e", "some(where (p.eft == allow))")
m.add_def("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")
a.add_policy("p", "p", ["alice", "data1", "read"])
a.add_policy("p", "p", ["bob", "data2", "write"])
assert e.enforce("alice", "data1", "read")
assert not e.enforce("alice", "data1", "write")
assert e.enforce("bob", "data2", "write")
assert not e.enforce("bob", "data1", "write")
Fails at assert e.enforce("alice", "data1", "read")
.
pycasbin/casbin/rbac/default_role_manager/role_manager.py
Lines 5 to 13 in 6b52db1
The method doesn't work!Because all_roles = dict() is invalid!
A bug for pycasbin:
If one use import casbin
, he changed his logging config, which is not expected.
The code is in pycasbin/log/default_logger:
pycasbin/casbin/log/default_logger.py
Lines 1 to 4 in cddd622
Current implementation replaces &&
and ||
with and
and or
correspondingly but does not handle !
operator.
Is there any suggested way I can achieve backward compatibility for my policy definition.
One way is to change all the existing policy data according to policy definition change, but this does not seem right once you have thousands of users in your production environment.
Is there any way to pass a Role Manager to a custom matcher function so inherited roles could be tested using a matcher function?
The alternative would be to pass a matcher function to a g function.
An example showing the need for this is:
g, permission::read, permission_group::admin
g, permission::write, permission_group::admin
g, permission::execute, permission_group::admin
g, permission::read, permission_group::readwrite
g, permission::write, permission_group::readwrite
g, permission::read, permission_group::readonly
g, /resource_1, resource_group::engineering
g, /resource_2, resource_group::engineering
g, /resource_3/*, resource_group::engineering
p, user::[email protected], resource_group::engineering, permission_group::admin, allow
In the above example, I can match enforcement requests for /resource_1 and /resource_2 with a g function. However, there is no way I can think of to match to /resource_3/foo and /resource_3/bar using a matcher function such as the built in keyMatch.
Is there an alternative way to approach this problem?
Is it possible to register a custom function in the pycasbin enforcer?
I did some lib code inspection and I'm not sure if it's possible.
https://casbin.org/docs/en/syntax-for-models#how-to-add-a-customized-function
in builtin_operators.py
def regex_match(key1, key2):
"""determines whether key1 matches the pattern of key2 in regular expression."""
res = re.match(key2, key1)
if res:
return True
else:
return False
when url is / that can match any url
HiI am struggling with using eval functions for ABAC with policy in pycasbin
Model-taken from example
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub_rule, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = eval(p.sub_rule) && r.obj == p.obj && r.act == p.act
Policy - taken from example
p, r.sub.Age > 18 && r.sub.Age < 60, /data1, read
Data{ Age: 40}, /data1, read
ErrorTraceback (most recent call last):
File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 406, in _eval_call
func = self.functions[node.func.id]
KeyError: 'eval'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "Test.py", line 8, in <module>
print (e.enforce(sub, obj, act))
File "/usr/local/lib/python3.8/dist-packages/casbin-0.8.4-py3.8.egg/casbin/core_enforcer.py", line 237, in enforce
result = expression.eval(parameters)
File "/usr/local/lib/python3.8/dist-packages/casbin-0.8.4-py3.8.egg/casbin/util/expression.py", line 29, in eval
return self._eval(self.expr_parsed_value)
File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 343, in _eval
return handler(node)
File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 375, in _eval_boolop
vout = self._eval(value)
File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 343, in _eval
return handler(node)
File "/home/tomer/.local/lib/python3.8/site-packages/simpleeval.py", line 408, in _eval_call
raise FunctionNotDefined(node.func.id, self.expr)
simpleeval.FunctionNotDefined: Function 'eval' not defined, for expression 'eval(p_sub_rule) and r_obj == p_obj and r_act == p_act'.
also i see this function is not registered: https://github.com/casbin/pycasbin/blob/master/casbin/model/function.py
Appreciate any help
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.