Files
netbird/client/internal/ipcauth/authz_level.go
T

94 lines
2.8 KiB
Go

package ipcauth
import (
"google.golang.org/grpc/codes"
gstatus "google.golang.org/grpc/status"
)
// AuthzLevel is the authority a caller holds over the daemon's current state.
// The values are ordered, and each level can do everything the levles below
// it can. A MethodPolicy is satisfied when the caller's level is at least
// the level the method requires.
type AuthzLevel uint8
const (
// AuthzLevelNone is a caller whose kernel identity could not be established.
AuthzLevelNone AuthzLevel = iota
// AuthzLevelIdentified is any caller the kernel could verify.
AuthzLevelIdentified
// AuthzLevelProfileOwner is a caller being the owner of the current targeted
// profile
AuthzLevelProfileOwner
// AuthzLevelSessionHolder is a caller that owns the current active profile
// and the session is currently connected (after running UP).
AuthzLevelSessionHolder
// AuthzLevelPrivileged is root, an elevated administrator or the daemon's
// own identity (if running as less privileges than root).
AuthzLevelPrivileged
)
// String() resolves a AuthzLevel to a human readable debug string.
func (l AuthzLevel) String() string {
switch l {
case AuthzLevelIdentified:
return "identified"
case AuthzLevelProfileOwner:
return "profile owner"
case AuthzLevelSessionHolder:
return "session holder"
case AuthzLevelPrivileged:
return "privileged"
default:
return "unidentified"
}
}
// RequireLevel builds a rule from a level, for composing inside another rule.
func RequireLevel(want AuthzLevel) Rule {
return func(r Request) error {
if r.Level >= want {
return nil
}
return denyLevel(r, want)
}
}
func denyLevel(r Request, want AuthzLevel) error {
return gstatus.Errorf(codes.PermissionDenied,
"%s requires %s, caller %s is %s", r.Method, want, r.Identity, r.Level)
}
// denyPolicyLevel refuses a caller at the gate, where the policy is in hand.
//
// Requiring privilege is the one denial a caller can act on, so it carries the
// elevated command rather than a bare refusal. A privileged method that declares
// no action keeps the plain message. Rules deny through denyLevel instead: they
// cannot reach the policy table without an initialization cycle, and no rule
// requires privilege.
func denyPolicyLevel(r Request, p MethodPolicy) error {
switch p.Level {
case AuthzLevelPrivileged:
if p.Action != "" {
actor, command := RequiredActor(p.Command)
return PrivilegeError(PrivilegeSummary(p.Action, actor), command)
}
case AuthzLevelSessionHolder:
// resolveLevel stops at profile owner only when a session is running and
// somebody else holds it.
if r.Level == AuthzLevelProfileOwner {
return SessionHeldError(p.Action)
}
return NotOwnerError(p.Action)
case AuthzLevelProfileOwner:
return NotOwnerError(p.Action)
}
return denyLevel(r, p.Level)
}