tailcfg: report StateEncrypted in Hostinfo (#16434)

Report whether the client is configured with state encryption (which
varies by platform and can be optional on some). Wire it up to
`--encrypt-state` in tailscaled, which is set for Linux/Windows, and set
defaults for other platforms. Macsys will also report this if full
Keychain migration is done.

Updates #15830

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
Andrew Lytvynov
2025-07-02 10:52:00 -07:00
committed by GitHub
parent d2edf7133a
commit 172e26b3e3
7 changed files with 47 additions and 1 deletions

View File

@@ -2244,6 +2244,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
hostinfo.Userspace.Set(b.sys.IsNetstack())
hostinfo.UserspaceRouter.Set(b.sys.IsNetstackRouter())
hostinfo.AppConnector.Set(b.appConnector != nil)
hostinfo.StateEncrypted = b.stateEncrypted()
b.logf.JSON(1, "Hostinfo", hostinfo)
// TODO(apenwarr): avoid the need to reinit controlclient.
@@ -7801,3 +7802,29 @@ func (b *LocalBackend) vipServicesFromPrefsLocked(prefs ipn.PrefsView) []*tailcf
var (
metricCurrentWatchIPNBus = clientmetric.NewGauge("localbackend_current_watch_ipn_bus")
)
func (b *LocalBackend) stateEncrypted() opt.Bool {
switch runtime.GOOS {
case "android", "ios":
return opt.NewBool(true)
case "darwin":
switch {
case version.IsMacAppStore():
return opt.NewBool(true)
case version.IsMacSysExt():
// MacSys still stores its state in plaintext on disk in addition to
// the Keychain. A future release will clean up the on-disk state
// files.
// TODO(#15830): always return true here once MacSys is fully migrated.
sp, _ := syspolicy.GetBoolean(syspolicy.EncryptState, false)
return opt.NewBool(sp)
default:
// Probably self-compiled tailscaled, we don't use the Keychain
// there.
return opt.NewBool(false)
}
default:
_, ok := b.store.(ipn.EncryptedStateStore)
return opt.NewBool(ok)
}
}