Repository: casbin/casbin (2025-08-11T12:23:17Z)

Issue:
[feature] support LBAC model and add its test case
What is LBAC: https://en.wikipedia.org/wiki/Lattice-based_access_control

How to resolve this issue? Refer to:

- Option-1: you need to modify Casbin core enforce code to support the new model, refer to ReBAC: https://github.com/casbin/casbin/pull/1501
- Option-2: you don't need to modify Casbin core enforce code, aka the existing Casbin lib already supports this scenario, refer to BLP: https://github.com/casbin/casbin/pull/1512

You can also heavily use the Casbin editor (https://editor.casbin.org/) to test & share your designed model, policy, request and enforcement result. Note: if you choose `Option-2`, the Casbin editor should already 100% works with your model.


Discussion:

Patch:
diff --git a/examples/lbac_model.conf b/examples/lbac_model.conf
new file mode 100644
index 00000000..be509a2e
--- /dev/null
+++ b/examples/lbac_model.conf
@@ -0,0 +1,14 @@
+[request_definition]
+r = sub, subject_confidentiality, subject_integrity, obj, object_confidentiality, object_integrity, act
+
+[policy_definition]
+p = sub, obj, act
+
+[role_definition]
+g = _, _
+
+[policy_effect]
+e = some(where (p.eft == allow))
+
+[matchers]
+m = (r.act == "read" && r.subject_confidentiality >= r.object_confidentiality && r.subject_integrity >= r.object_integrity) || (r.act == "write" && r.subject_confidentiality <= r.object_confidentiality && r.subject_integrity <= r.object_integrity)
\ No newline at end of file


Test patch:
diff --git a/lbac_test.go b/lbac_test.go
new file mode 100644
index 00000000..53d0693a
--- /dev/null
+++ b/lbac_test.go
@@ -0,0 +1,56 @@
+// Copyright 2025 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package casbin
+
+import (
+	"testing"
+)
+
+func testEnforceLBAC(t *testing.T, e *Enforcer, sub string, subConf, subInteg float64, obj string, objConf, objInteg float64, act string, res bool) {
+	t.Helper()
+	if myRes, err := e.Enforce(sub, subConf, subInteg, obj, objConf, objInteg, act); err != nil {
+		t.Errorf("Enforce Error: %s", err)
+	} else if myRes != res {
+		t.Errorf("%s, conf=%v, integ=%v, %s, conf=%v, integ=%v, %s: %t, supposed to be %t", sub, subConf, subInteg, obj, objConf, objInteg, act, myRes, res)
+	}
+}
+
+func TestLBACModel(t *testing.T) {
+	e, _ := NewEnforcer("examples/lbac_model.conf")
+
+	t.Log("Testing normal read operation scenarios")
+	testEnforceLBAC(t, e, "admin", 5, 5, "file_topsecret", 3, 3, "read", true) // both high
+	testEnforceLBAC(t, e, "manager", 4, 4, "file_secret", 4, 2, "read", true)  // confidentiality equal, integrity higher
+	testEnforceLBAC(t, e, "staff", 3, 3, "file_internal", 2, 3, "read", true)  // confidentiality higher, integrity equal
+	testEnforceLBAC(t, e, "guest", 2, 2, "file_public", 2, 2, "read", true)    // both dimensions equal
+
+	t.Log("Testing read operation violation scenarios")
+	testEnforceLBAC(t, e, "staff", 3, 3, "file_secret", 4, 2, "read", false)      // insufficient confidentiality level
+	testEnforceLBAC(t, e, "manager", 4, 4, "file_sensitive", 3, 5, "read", false) // insufficient integrity level
+	testEnforceLBAC(t, e, "guest", 2, 2, "file_internal", 3, 1, "read", false)    // insufficient confidentiality level
+	testEnforceLBAC(t, e, "staff", 3, 3, "file_protected", 1, 4, "read", false)   // insufficient integrity level
+
+	t.Log("Testing normal write operation scenarios")
+	testEnforceLBAC(t, e, "guest", 2, 2, "file_public", 2, 2, "write", true)   // both dimensions equal
+	testEnforceLBAC(t, e, "staff", 3, 3, "file_internal", 5, 4, "write", true) // both low
+	testEnforceLBAC(t, e, "manager", 4, 4, "file_secret", 4, 5, "write", true) // confidentiality equal, integrity low
+	testEnforceLBAC(t, e, "admin", 5, 5, "file_archive", 5, 5, "write", true)  // both dimensions equal
+
+	t.Log("Testing write operation violation scenarios")
+	testEnforceLBAC(t, e, "manager", 4, 4, "file_internal", 3, 5, "write", false) // confidentiality level too high
+	testEnforceLBAC(t, e, "staff", 3, 3, "file_public", 2, 2, "write", false)     // both dimensions too high
+	testEnforceLBAC(t, e, "admin", 5, 5, "file_secret", 5, 4, "write", false)     // integrity level too high
+	testEnforceLBAC(t, e, "guest", 2, 2, "file_private", 1, 3, "write", false)    // confidentiality level too high
+}