PyCasbin
PyCasbin is a powerful and efficient open-source authorization library for Python projects (currently v2.8.0). It supports enforcing access control based on various models like ACL, RBAC, and ABAC. The library is actively maintained with frequent updates and aims for feature parity across its different language implementations.
Warnings
- breaking Version 2.0.0 introduced breaking changes. While specific API changes are not fully detailed in the public changelog, a major version bump indicates potential incompatibilities. Users upgrading from v1.x should review the changelog for any necessary adaptations.
- gotcha Performance differences: The Python implementation of Casbin (`PyCasbin`) can be significantly slower (up to 30x in some cases) than its Go counterpart (`Go-Casbin`) when dealing with large or complex policy sets. This is primarily due to differences in the underlying expression evaluation engines.
- gotcha Logging configuration: PyCasbin uses Python's standard `logging` module. If an application sets up its own logger, this can lead to duplicate log messages or prevent PyCasbin's logs from appearing if the application's logging is not correctly configured to handle it.
- gotcha ABAC `in` operator behavior: When using the `in` operator in matchers for Attribute-Based Access Control (ABAC) with array literals (e.g., `r.obj in ('data2', 'data3')`), some Casbin implementations across languages might have specific requirements, such as the array length being greater than one to avoid unexpected behavior or panics. Ensure your array literals are well-formed and test thoroughly.
Install
-
pip install pycasbin
Imports
- Enforcer
import casbin enforcer = casbin.Enforcer(...)
- SyncedEnforcer
from casbin import SyncedEnforcer
- AsyncEnforcer
from casbin.enforcer import Enforcer as AsyncEnforcer # or from casbin.enforcer import AsyncEnforcer # if using direct import and not renaming
Quickstart
import casbin
import os
# Create dummy model and policy files for the example
with open('model.conf', 'w') as f:
f.write('''
[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 && r.obj == p.obj && r.act == p.act
''')
with open('policy.csv', 'w') as f:
f.write('''
p, alice, data1, read
p, bob, data2, write
p, data2_admin, data2, *
''')
async def run_enforcer():
# Initialize an enforcer with a model file and a policy file
# For real applications, use an adapter (e.g., casbin_sqlalchemy_adapter)
e = casbin.Enforcer('model.conf', 'policy.csv')
# Test if 'alice' can 'read' 'data1'
if await e.enforce('alice', 'data1', 'read'):
print("Alice CAN read data1")
else:
print("Alice CANNOT read data1")
# Test if 'bob' can 'read' 'data2'
if await e.enforce('bob', 'data2', 'read'):
print("Bob CAN read data2")
else:
print("Bob CANNOT read data2")
# Test if 'bob' can 'write' 'data2'
if await e.enforce('bob', 'data2', 'write'):
print("Bob CAN write data2")
else:
print("Bob CANNOT write data2")
# Add a policy dynamically
await e.add_policy('cathy', 'data3', 'read')
if await e.enforce('cathy', 'data3', 'read'):
print("Cathy CAN read data3 (after adding policy)")
# Remove temporary files
os.remove('model.conf')
os.remove('policy.csv')
if __name__ == '__main__':
import asyncio
asyncio.run(run_enforcer())