72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
|
|
package rbac
|
||
|
|
|
||
|
|
type Permission string
|
||
|
|
|
||
|
|
const (
|
||
|
|
Read Permission = "read"
|
||
|
|
Write Permission = "write"
|
||
|
|
// Root is the high-impact tier: destructive or irreversible operations
|
||
|
|
// (reboot, shutdown, account deletion, firewall flush, …) that callers
|
||
|
|
// should be able to grant separately from routine writes.
|
||
|
|
Root Permission = "root"
|
||
|
|
All Permission = "*" // wildcard: matches any permission
|
||
|
|
)
|
||
|
|
|
||
|
|
// Wildcard is the module-key value that matches all modules in a Role's grants.
|
||
|
|
const Wildcard = "*"
|
||
|
|
|
||
|
|
type Role struct {
|
||
|
|
Name string
|
||
|
|
ModuleGrants map[string][]Permission // module ID (or "*") -> permissions (each may be "*")
|
||
|
|
}
|
||
|
|
|
||
|
|
type RBAC struct {
|
||
|
|
roles map[string]Role
|
||
|
|
userRoles map[string][]string
|
||
|
|
}
|
||
|
|
|
||
|
|
func New() *RBAC {
|
||
|
|
return &RBAC{
|
||
|
|
roles: make(map[string]Role),
|
||
|
|
userRoles: make(map[string][]string),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *RBAC) DefineRole(role Role) {
|
||
|
|
r.roles[role.Name] = role
|
||
|
|
}
|
||
|
|
|
||
|
|
// RoleExists reports whether a role with the given name has been defined.
|
||
|
|
func (r *RBAC) RoleExists(name string) bool {
|
||
|
|
_, ok := r.roles[name]
|
||
|
|
return ok
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *RBAC) AssignRole(username, roleName string) {
|
||
|
|
r.userRoles[username] = append(r.userRoles[username], roleName)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Can checks whether the user holds any role granting (module, perm),
|
||
|
|
// honoring "*" wildcards on both the module key and inside the permission list.
|
||
|
|
func (r *RBAC) Can(username, module string, perm Permission) bool {
|
||
|
|
for _, roleName := range r.userRoles[username] {
|
||
|
|
role, ok := r.roles[roleName]
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
// Check the exact module key AND the wildcard module key.
|
||
|
|
for _, key := range []string{module, Wildcard} {
|
||
|
|
grants, ok := role.ModuleGrants[key]
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
for _, p := range grants {
|
||
|
|
if p == perm || p == All {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|