Integrate Firestore as the policy storage for Casbin with Python/Flask stack
The fundamental way to integrate Firestore as the policy storage for Casbin is by using a dedicated Adapter. In Casbin, an adapter serves as the persistent layer, handling the LoadPolicy() and SavePolicy() operations between the in-memory enforcer and the database.
Since you are using a Python/Flask stack, you'll need the appropriate Python Firestore Adapter for Casbin [1].
1. Prerequisites and Installation​
To set up Firestore persistence for your Python Casbin enforcer, you need to install the necessary packages and ensure your Google Cloud credentials are configured.
-
Casbin: The core Casbin library.
pip install pycasbin -
Firestore Adapter: While there isn't one official adapter maintained by the core Casbin team for Python and Firestore, community-maintained packages exist, such as
pycasbin-firebase-adapter[2] (which uses the Firebase Admin SDK to access Firestore).pip install pycasbin-firebase-adapter firebase-admin -
Authentication: Ensure the environment where your Flask app runs (e.g., GCP App Engine, Cloud Run, GKE) has the necessary IAM permissions to access Firestore, or that you have set up a service account key [3].
2. Setting up the Adapter and Enforcer​
The setup involves two main steps: initializing the Firebase Admin SDK and then passing the initialized object to the Casbin Adapter constructor.
A. Initialize Firebase Admin SDK​
The Casbin Firestore adapter relies on the Firebase Admin SDK to communicate with the database.
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
# --- 1. Load Credentials ---
# Best practice on GCP (e.g., Cloud Run) is to use Application Default Credentials (ADC).
try:
cred = credentials.ApplicationDefault()
firebase_admin.initialize_app(cred)
except:
# Fallback for local testing (replace with your path)
cred = credentials.Certificate("path/to/serviceAccountKey.json")
firebase_admin.initialize_app(cred)
db = firestore.client()
B. Create and Use the Casbin Adapter​
Now, you pass the initialized Firestore client (db) to the adapter, and then pass the adapter to the Casbin Enforcer.
import casbin
from pycasbin_firebase_adapter import Adapter as FirestoreAdapter # Rename for clarity
# 1. Instantiate the Adapter, pointing it to your Firestore client
# Note: The adapter may allow specifying a collection name (e.g., 'casbin_rules').
adapter = FirestoreAdapter(db)
# 2. Instantiate the Enforcer with your model and the new adapter
# 'model.conf' contains the definition of your access control model (e.g., RBAC).
e = casbin.Enforcer("model.conf", adapter)
# --- Policy is automatically loaded into memory here (LoadPolicy()) ---
# 3. Enforcement Check (Uses the in-memory policy)
sub = "alice"
obj = "/reports/finance"
act = "read"
if e.enforce(sub, obj, act):
print(f"{sub} is permitted to {act} {obj}.")
else:
print(f"{sub} is denied access to {obj}.")
Annotation: When the Enforcer is created, the Adapter's LoadPolicy() method is called, which fetches all policy rules (p, g, g2) from Firestore and loads them into Casbin's in-memory model.
3. Policy Management in Firestore​
Once the adapter is set up, you manage all policy rules using the Casbin API; you never interact directly with the Firestore collection for Casbin rules.
A. Saving New Policies​
When you make changes using the Casbin management API, the adapter automatically translates those changes into Firestore documents.
| Casbin API Call | Firestore Document Action |
|---|---|
e.add_policy("editor", "/data", "write") | Creates a new document in the Casbin collection (e.g., ptype: p, v0: editor, v1: /data, v2: write). |
e.add_grouping_policy("user_x", "editor") | Creates a new document (e.g., ptype: g, v0: user_x, v1: editor). |
e.save_policy() | Overwrites the entire policy in Firestore with the current in-memory state (used less frequently). |
B. Firestore Policy Structure​
The Firestore adapter typically stores the policy rules as documents in a single collection (e.g., casbin_rules). Each document will have fields corresponding to the Casbin policy line structure:
| Field | Casbin Policy Line Component |
|---|---|
ptype | The policy type (p, g, g2, etc.) |
v0 | The first field (e.g., user or role) |
v1 | The second field (e.g., resource or parent_role) |
v2 to v5 | Subsequent fields (e.g., action or domain) |
This ensures that the NoSQL structure of Firestore can faithfully represent the relational policy rules Casbin uses.
