Files
netbird/client/internal/ipcauth/authz_level.go
T
2026-09-17 14:36:56 +02:00

90 lines
2.8 KiB
Go

package ipcauth
import (
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"
}
}
// resolveLevel is the authority the caller holds over the profile the request
// names. The second return is what was wrong with the handle, when that is
// worth showing the caller instead of a refusal. It never raises the level: a
// resolution that failed still denies.
func resolveLevel(id Identity, target string, st DaemonState) (AuthzLevel, error) {
if !id.Known() {
return AuthzLevelNone, nil
}
if IsPrivilegedCaller(id) {
return AuthzLevelPrivileged, nil
}
ownsProfile, err := st.OwnsProfile(id, target)
if err != nil {
return AuthzLevelIdentified, presentableHandleError(target, err)
}
if !ownsProfile {
return AuthzLevelIdentified, nil
}
if holder, running := st.SessionHolder(); !running || holder.Matches(id) {
return AuthzLevelSessionHolder, nil
}
return AuthzLevelProfileOwner, nil
}
// presentableHandleError keeps a resolution failure only when the gate can put
// it in front of the caller in place of its own refusal. Everything else is
// dropped, and the caller gets the refusal their level earned.
func presentableHandleError(target string, err error) error {
// An empty target is the active profile rather than something the caller
// typed, so a failure to resolve it is not theirs to correct.
if target == "" {
return nil
}
// Only a gRPC status reaches the caller as a sentence the CLI and the UI
// render.
if _, ok := gstatus.FromError(err); !ok {
return nil
}
return err
}