Files
nadir-agent/internal/rbac/rbac.go
T
2026-06-22 16:06:57 +02:00

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
}