mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-13 00:49:07 +02:00
[client] Profile ownership console user tofu (#7529)
* Add consoleuser and stamp default profile on known username in migration * Refactor consoleuser to verify Id, fix seats on linux and default stamp * Add default profile claim * Add disable auto-claim of default profile and always fail close * Add disable auto-claim flag to migration * Adding timeout to console user on Linux and close library load on darwin * Fixed failed close test * Close both Dlopen for darwin * Replace RegisterFunc with purego.Dlsym to avoid possible panic * Fix freebsd tty enumeration * Fix active profile migration logic and add test * Log defaultClaimDisabled error once * Guard against panicking console user lookup. * Fix merge conflict * Fix broken tests
This commit is contained in:
@@ -22,6 +22,11 @@ import (
|
||||
"github.com/netbirdio/netbird/util"
|
||||
)
|
||||
|
||||
// EnvDisableDefaultProfileClaim turns off the console-user claim of an unowned
|
||||
// default profile. The profile then stays unowned until a privileged caller
|
||||
// records an owner.
|
||||
const EnvDisableDefaultProfileClaim = "NB_DISABLE_DEFAULT_PROFILE_CLAIM"
|
||||
|
||||
var (
|
||||
oldDefaultConfigPathDir = ""
|
||||
oldDefaultConfigPath = ""
|
||||
@@ -596,6 +601,7 @@ func (s *ServiceManager) loadAllProfilesForIdentity(userID ipcauth.Identity) ([]
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.claimDefaultProfileIfNeeded(allProfiles, userID)
|
||||
s.claimLegacyProfiles(allProfiles, userID)
|
||||
|
||||
accessible := make([]Profile, 0, len(allProfiles))
|
||||
@@ -659,6 +665,67 @@ func (s *ServiceManager) claimLegacyProfiles(profiles []Profile, id ipcauth.Iden
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServiceManager) claimDefaultProfileIfNeeded(profiles []Profile, id ipcauth.Identity) {
|
||||
if !id.Known() || ipcauth.IsPrivilegedCaller(id) {
|
||||
return
|
||||
}
|
||||
|
||||
var unowned bool
|
||||
var p *Profile
|
||||
for i := range profiles {
|
||||
p = &profiles[i]
|
||||
if p.ID == defaultProfileName && len(p.Owners) == 0 {
|
||||
unowned = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if unowned && !defaultProfileClaimDisabled() && isConsoleUser(id) {
|
||||
principal := ipcauth.OwnerPrincipalForIdentity(id)
|
||||
parsed, ok := ipcauth.ParsePrincipal(principal)
|
||||
if !ok {
|
||||
log.Warnf("not claiming default profile, %q is not a usable owner", principal)
|
||||
return
|
||||
}
|
||||
if err := StampOwner(p.Path, id); err != nil {
|
||||
log.Warnf("could not claim default profile %s for %#v: %v", p.Path, id, err)
|
||||
return
|
||||
}
|
||||
p.Owners = []ipcauth.Principal{parsed}
|
||||
log.Infof("claimed default profile %s for %s", p.Path, principal)
|
||||
}
|
||||
}
|
||||
|
||||
// isConsoleUser is a variable so a test can decide whether a caller is at the
|
||||
// console without the machine running the test having a seat of its own.
|
||||
var isConsoleUser = ipcauth.IsConsoleUser
|
||||
|
||||
// logDefaultClaimDisabledOrError keeps the notice to once per process, since the claim
|
||||
// path runs on every profile load. It also logs a parse failure once.
|
||||
var logDefaultClaimDisabledOrError sync.Once
|
||||
|
||||
// defaultProfileClaimDisabled reports whether the environment turns off the
|
||||
// console-user claim of the default profile.
|
||||
func defaultProfileClaimDisabled() bool {
|
||||
val := os.Getenv(EnvDisableDefaultProfileClaim)
|
||||
if val == "" {
|
||||
return false
|
||||
}
|
||||
disabled, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
logDefaultClaimDisabledOrError.Do(func() {
|
||||
log.Warnf("failed to parse %s: %v", EnvDisableDefaultProfileClaim, err)
|
||||
})
|
||||
return false
|
||||
}
|
||||
if disabled {
|
||||
logDefaultClaimDisabledOrError.Do(func() {
|
||||
log.Infof("%s is set, the default profile stays unowned and reachable only by a privileged caller until an owner is recorded another way", EnvDisableDefaultProfileClaim)
|
||||
})
|
||||
}
|
||||
return disabled
|
||||
}
|
||||
|
||||
func hasUnownedLegacyProfile(profiles []Profile) bool {
|
||||
for i := range profiles {
|
||||
if profiles[i].LegacyUserDir != "" && len(profiles[i].Owners) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user