Casbin: access control in go. Part 1
Welcome everyone! After a long break caused by turbulent events in my life, I finally found time and inspiration to complete the series of articles about access control using Casbin. In this second and final part, we'll dive into practical implementation and look at a specific example of using this powerful library together with my own open-source project Guard.
Despite having limited time for writing technical articles lately, I continued working on tools that can make life easier for Go developers. And today I'm happy to share the results of this work with you.
Introduction
In the previous part, we looked at basic concepts of access control and different approaches to its implementation. Now we'll focus on the practical implementation of a three-level access control system using Casbin.
Open-source project "Guard"
Guard is a library that simplifies working with
Casbinin Go projects and provides a convenient interface for implementing access control.
Code on Github
https://github.com/nesymno/guard
So, Guard provides its own factory for creating multi-level authorization, which significantly simplifies working with Casbin in Go. This implementation covers most typical use cases.
Additionally, Guard allows creating custom authorization implementations through the Factory interface:
type Factory interface {
Scope(data ScopeData) Scope
SubjectUser(id string) Subject
SubjectRole(tenantID, id string) Subject
SubjectGroup(tenantID, id string) Subject
Object(s Scope, p Perm) Object
GroupPolicy(sub, role Subject) GroupPolicy
PolicyFromCasbin(p []string) (Policy, error)
RolePolicyFromCasbin(p []string) (RolePolicy, error)
RolePoliciesFromCasbin(p [][]string) ([]RolePolicy, error)
GroupPolicyFromCasbin(p []string) (GroupPolicy, error)
}This interface provides the ability to:
- Create custom scopes to limit access context
- Define different types of subjects: users, roles, and groups
- Configure access objects and their policies
- Convert
Casbinrules toGuardformat and vice versa
Thanks to this flexibility, you as developers can adapt Guard to your project's specific needs while maintaining all the benefits of using Casbin.
Usage Example
Let's look at an example of using Guard. Just go to the guard/examples/tenant/main.go file and review it:
func main() {
// Create a new Guard factory
f := guard.NewFactory()
// Create a scope for tenant with ID "1"
s := f.Scope(guard.ScopeData{TenantID: "1"})
// Create a user with ID "user1"
user := f.SubjectUser("user1")
// Create "admin" role for tenant "1"
role := f.SubjectRole("1", "admin")
// Create a group policy that assigns the role to the user
groupPolicy := f.GroupPolicy(user, role)
// Create "resource1" object with "read" permission
obj := f.Object(s, guard.Read)
// Create a policy that allows admin role to read the resource
policy := guard.NewPolicy(role, obj)
// Initialize Casbin enforcer
e, _ := casbin.NewEnforcer("examples/tenant/model.conf")
// Add policies to enforcer
e.AddPolicy(policy.ToCasbin()...)
e.AddGroupingPolicy(groupPolicy.ToCasbin()...)
// Check access
ok, _ := e.Enforce(user.String(), s.String(), "resource1", "read")
fmt.Printf("Access granted: %v\n", ok)
}Let's break down this example step by step
- A new
Guardfactory is created, which provides methods for creating all necessary components - A scope is defined for a specific tenant (organization), allowing isolation of access rules between different organizations
- Subjects are created: user and role
- Role is assigned to user through group policy
- An object is created with specific access right (in this case - reading)
- A policy is created that allows admin role to read the resource
- All policies are converted to
Casbinformat and added to enforcer - User's access is verified
Main features of Guard library
✓ Multi-level access control system (users, roles, groups)
✓ Multi-tenancy support through scopes
✓ Convenient interface for working with Casbin
✓ Type safety through using Go structures instead of strings
✓ Extensibility through custom factory implementations
✓ Easy integration with existing Go projects
The library significantly simplifies working with Casbin, providing a convenient API for typical use cases while maintaining flexibility and extensibility of the base functionality.
Tests
Writing tests was my biggest pain point. They require a lot of work, lots of mocks, and it's difficult to track and remember everything. Still, it needed to be done so I could share it with you.

Coverage of main structure that contains all necessary methods
Conclusion
In this article, we looked at the practical implementation of access control using the Guard library, which significantly simplifies working with Casbin in Go projects. We saw how easy it is to set up a multi-level authorization system using users, roles, and groups.
Guard provides not only a convenient API for typical use cases but also the possibility of extension through custom factory implementations. This makes the library flexible enough for use in various projects, from small applications to complex enterprise systems.
Although developing and testing such an access control system can be a challenging task, using Guard significantly simplifies this process by providing a type-safe and intuitive interface for working with Casbin.