mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-27 11:41:14 +00:00
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:
@@ -162,7 +162,8 @@ type CapabilityVersion int
|
||||
// - 115: 2025-03-07: Client understands DERPRegion.NoMeasureNoHome.
|
||||
// - 116: 2025-05-05: Client serves MagicDNS "AAAA" if NodeAttrMagicDNSPeerAAAA set on self node
|
||||
// - 117: 2025-05-28: Client understands DisplayMessages (structured health messages), but not necessarily PrimaryAction.
|
||||
const CurrentCapabilityVersion CapabilityVersion = 117
|
||||
// - 118: 2025-07-01: Client sends Hostinfo.StateEncrypted to report whether the state file is encrypted at rest (#15830)
|
||||
const CurrentCapabilityVersion CapabilityVersion = 118
|
||||
|
||||
// ID is an integer ID for a user, node, or login allocated by the
|
||||
// control plane.
|
||||
@@ -878,6 +879,12 @@ type Hostinfo struct {
|
||||
Location *Location `json:",omitempty"`
|
||||
|
||||
TPM *TPMInfo `json:",omitempty"` // TPM device metadata, if available
|
||||
// StateEncrypted reports whether the node state is stored encrypted on
|
||||
// disk. The actual mechanism is platform-specific:
|
||||
// * Apple nodes use the Keychain
|
||||
// * Linux and Windows nodes use the TPM
|
||||
// * Android apps use EncryptedSharedPreferences
|
||||
StateEncrypted opt.Bool `json:",omitempty"`
|
||||
|
||||
// NOTE: any new fields containing pointers in this type
|
||||
// require changes to Hostinfo.Equal.
|
||||
|
||||
@@ -188,6 +188,7 @@ var _HostinfoCloneNeedsRegeneration = Hostinfo(struct {
|
||||
ServicesHash string
|
||||
Location *Location
|
||||
TPM *TPMInfo
|
||||
StateEncrypted opt.Bool
|
||||
}{})
|
||||
|
||||
// Clone makes a deep copy of NetInfo.
|
||||
|
||||
@@ -69,6 +69,7 @@ func TestHostinfoEqual(t *testing.T) {
|
||||
"ServicesHash",
|
||||
"Location",
|
||||
"TPM",
|
||||
"StateEncrypted",
|
||||
}
|
||||
if have := fieldsOf(reflect.TypeFor[Hostinfo]()); !reflect.DeepEqual(have, hiHandles) {
|
||||
t.Errorf("Hostinfo.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
|
||||
|
||||
@@ -303,6 +303,7 @@ func (v HostinfoView) ServicesHash() string { return v.ж.Serv
|
||||
func (v HostinfoView) Location() LocationView { return v.ж.Location.View() }
|
||||
func (v HostinfoView) TPM() views.ValuePointer[TPMInfo] { return views.ValuePointerOf(v.ж.TPM) }
|
||||
|
||||
func (v HostinfoView) StateEncrypted() opt.Bool { return v.ж.StateEncrypted }
|
||||
func (v HostinfoView) Equal(v2 HostinfoView) bool { return v.ж.Equal(v2.ж) }
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
@@ -346,6 +347,7 @@ var _HostinfoViewNeedsRegeneration = Hostinfo(struct {
|
||||
ServicesHash string
|
||||
Location *Location
|
||||
TPM *TPMInfo
|
||||
StateEncrypted opt.Bool
|
||||
}{})
|
||||
|
||||
// View returns a read-only view of NetInfo.
|
||||
|
||||
Reference in New Issue
Block a user