Documentation ¶
Overview ¶
Package rbac is role based access control library. At core uses `sync.Map` so, it can be used from multiple goroutines concurrently.package rbac
rbac is dependend on these terms:
- Action Defines what can possible for a permission
- Permission Defines permission related to a resource to be accessed
- Role Defines group of permissions with defined actions
Usage:
Library usage has 2 phases:
- Development
- Runtime
Development Phase ¶
First get an instance for `RBAC`
import "github.com/euroteltr/rbac" R := rbac.New(nil) // you can pass a logger to constructor also: // R := rbac.New(rbac.ConsoleLogger)
During development you will register your permissions for your each resource with valid actions for that permission:
// You can also use rbac.CRUD for those crud actions usersPerm, err := R.RegisterPermission("users", "User resource", rbac.Create, rbac.Read, rbac.Update, rbac.Delete) if err != nil { panic(err) }
`userPerm` is defined with CRUD actions, which means that any action not in that list will be invalid. You can define your own actions( like `ApproveAction := rbac.Action("approve")`) and add them also.
Runtime Phase:
At run time we define our roles and permit permissions to them.
adminRole, err := R.RegisterRole("admin", "Admin role") if err != nil { fmt.Printf("can not add admin role, err: %v\n", err) } if err = R.Permit(adminRole.ID, usersPerm, rbac.CRUD, ApproveAction); err != nil { fmt.Errorf("can not permit crud and ApproveAction actions to role %s\n", adminRole.ID) }
Now we can check if a role is granted some permission:
if !R.IsGranted(adminRole.ID, usersPerm, rbac.Write) { fmt.Printf("admin role does not have write grant on users\n") }else{ fmt.Printf("admin role does have write grant on users\n") } // You can also check by perm.ID also if !R.IsGrantedStr("admin", "users", rbac.CRUD) { fmt.Printf("admin role does not have CRUD grants on users\n") }else{ fmt.Printf("admin role does have CRUD grants on users\n") }
Persisting and Loading ¶
`rbac.RBAC` is `json` compatible. You can dump all data in `RBAC` instance to JSON:
b, err := json.Marshal(R) if err != nil { fmt.Printf("rback marshall failed with %v\n", err) }else{ fmt.Printf("RBAC: %s", b) }
Also you can use builtin SaveJSON function to save to a io.Writer:
filename := "/tmp/rbac.json" f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Printf("can not load json file %s, err: %v\n", filename, err) return err } defer f.Close() if err = R.SaveJSON(f); err != nil { fmt.Printf("unable to save to json file, err:%v\n", err) }
And load it from file:
filename := "/tmp/rbac.json" f, err := os.Open(filename) if err != nil { return err } defer f.Close() if err = R.LoadJSON(f); err != nil { fmt.Errorf("unable to load from json file, err:%v\n", err) }
In dumped JSON root "permissions" part is for reference. Root `roles` is the part you can modify in file and reload it to define `Role`s with `Permission`s.
{ "permissions": [ { "id": "users", "description": "User resource", "actions": [ "create", "read", "update", "delete" ] } ], "roles": [ { "id": "admin", "description": "Admin role", "grants": { "users": [ "create", "read", "update", "delete" ] }, "parents": [] } ] }
Role inheritance ¶
A `Role` can have parent `Role`s. You can add a parent `Role` like this:
// Add a new role sysAdmRole, err := R.RegisterRole("sysadm", "System admin role") if err != nil { fmt.Printf("can not add agent role, err: %v\n", err) } // Now add adminRole as parent if err = sysAdmRole.AddParent(adminRole); err != nil { fmt.Printf("adding parent role failed with: %v\n", err) } // Now all permissions in adminRole will be also valid for sysAdmRole if R.IsGranted(sysAdmRole.ID, usersPerm, rbac.CRUD) { fmt.Printf("sysadmin role has all crud actions granted\n") }
If circular parent reference is found, you'll get error while running `AddParent`.
Index ¶
- func SetLogger(logger Logger)
- type Action
- type ConsoleLogger
- type Logger
- type NullLogger
- type Permission
- type RBAC
- func (r *RBAC) AllGranted(roleIDs []string, perm *Permission, action ...Action) (res bool)
- func (r *RBAC) AnyGranted(roleIDs []string, perm *Permission, action ...Action) (res bool)
- func (r *RBAC) Clone(roles bool) (trg *RBAC)
- func (r *RBAC) GetAllPermissions(roleIDs []string) map[string][]Action
- func (r *RBAC) GetRole(roleID string) *Role
- func (r *RBAC) IsGranted(roleID string, perm *Permission, actions ...Action) bool
- func (r *RBAC) IsGrantedStr(roleID string, permID string, actions ...Action) bool
- func (r *RBAC) IsPermissionExist(permissionID string, action Action) (res bool)
- func (r *RBAC) IsRoleExist(roleID string) (res bool)
- func (r *RBAC) LoadJSON(reader io.Reader) error
- func (r *RBAC) MarshalJSON() ([]byte, error)
- func (r *RBAC) Permissions() []*Permission
- func (r *RBAC) Permit(roleID string, perm *Permission, actions ...Action) error
- func (r *RBAC) RegisterPermission(permissionID, description string, actions ...Action) (*Permission, error)
- func (r *RBAC) RegisterRole(roleID string, description string) (*Role, error)
- func (r *RBAC) RemoveRole(roleID string) error
- func (r *RBAC) Revoke(roleID string, perm *Permission, actions ...Action) error
- func (r *RBAC) RoleGrants() []*RoleGrants
- func (r *RBAC) Roles() (res []*Role)
- func (r *RBAC) SaveJSON(writer io.Writer) (err error)
- func (r *RBAC) UnmarshalJSON(b []byte) (err error)
- type Role
- type RoleGrants
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Action ¶
type Action string
Action is permission action
const ( // None is for empty action None Action = "" // Create is for create action Create Action = "create" // Read is for read action Read Action = "read" // Update is for update action Update Action = "update" // Delete is for delete action Delete Action = "delete" // CRUD is for, create+read+update+delete permissions CRUD Action = "crud" // Download is for downloading action Download = "download" // Upload is for uploading action Upload = "upload" )
type ConsoleLogger ¶
type ConsoleLogger struct { }
ConsoleLogger is console logger
func (*ConsoleLogger) Debugf ¶
func (nl *ConsoleLogger) Debugf(format string, args ...interface{})
Debugf is for debug logging
func (*ConsoleLogger) Errorf ¶
func (nl *ConsoleLogger) Errorf(format string, args ...interface{})
Errorf is for error logging
type Logger ¶
type Logger interface { Debugf(format string, args ...interface{}) Errorf(format string, args ...interface{}) }
Logger is interface for logger to be used in RBAC
type NullLogger ¶
type NullLogger struct { }
NullLogger is null logger
func (*NullLogger) Debugf ¶
func (nl *NullLogger) Debugf(format string, args ...interface{})
Debugf is for debug logging
func (*NullLogger) Errorf ¶
func (nl *NullLogger) Errorf(format string, args ...interface{})
Errorf is for error logging
type Permission ¶
Permission defines rbac permission
func (*Permission) Actions ¶
func (p *Permission) Actions() []Action
Actions returns list of Actions
func (*Permission) MarshalJSON ¶
func (p *Permission) MarshalJSON() ([]byte, error)
MarshalJSON serializes a Permission to JSON
type RBAC ¶
type RBAC struct { sync.Map // key: role.ID, value: role // contains filtered or unexported fields }
RBAC is role bases access control manager
func (*RBAC) AllGranted ¶
func (r *RBAC) AllGranted(roleIDs []string, perm *Permission, action ...Action) (res bool)
AllGranted checks if all roles have the permission.
func (*RBAC) AnyGranted ¶
func (r *RBAC) AnyGranted(roleIDs []string, perm *Permission, action ...Action) (res bool)
AnyGranted checks if any role has the permission.
func (*RBAC) GetAllPermissions ¶
GetAllPermissions returns granted permissions for a role(including inherited permissions from parents)
func (*RBAC) GetRole ¶
GetRole finds and returns role from instance, if role is not found returns nil
func (*RBAC) IsGranted ¶
func (r *RBAC) IsGranted(roleID string, perm *Permission, actions ...Action) bool
IsGranted checks if a role with target permission and actions has a grant
func (*RBAC) IsGrantedStr ¶
IsGrantedStr checks if permID is greanted with target actions for role
func (*RBAC) IsPermissionExist ¶
IsPermissionExist checks if a permission with target ID and action is defined
func (*RBAC) IsRoleExist ¶
IsRoleExist checks if a role with target ID is defined
func (*RBAC) MarshalJSON ¶
MarshalJSON serializes a all roles to JSON
func (*RBAC) Permissions ¶
func (r *RBAC) Permissions() []*Permission
Permissions returns all Permissions
func (*RBAC) Permit ¶
func (r *RBAC) Permit(roleID string, perm *Permission, actions ...Action) error
Permit grants a permission with defined actions to a role
func (*RBAC) RegisterPermission ¶
func (r *RBAC) RegisterPermission(permissionID, description string, actions ...Action) (*Permission, error)
RegisterPermission defines and registers a permission
func (*RBAC) RegisterRole ¶
RegisterRole defines and registers a role
func (*RBAC) RemoveRole ¶
RemoveRole deletes role from instance
func (*RBAC) Revoke ¶
func (r *RBAC) Revoke(roleID string, perm *Permission, actions ...Action) error
Revoke removes a permission from a role
func (*RBAC) UnmarshalJSON ¶
UnmarshalJSON parses RBAC from JSON
type Role ¶
type Role struct { ID string `json:"id"` Description string `json:"description"` sync.Map `json:"-"` // key: permissionID, values sync.Map[action]=true/false // contains filtered or unexported fields }
Role defines a role
func (*Role) RemoveParent ¶
RemoveParent removes parent role
type RoleGrants ¶
type RoleGrants struct { ID string `json:"id"` Description string `json:"description"` Grants grantsMap `json:"grants"` Parents []string `json:"parents"` }
RoleGrants is used during JSON Marshalling