ipn/ipnlocal, feature/posture: pull posture out into a modular feature

Updates #12614

Change-Id: I9d08a1330b9c55e1a23e7979a707e11d8e090d79
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2025-09-29 15:50:17 -07:00
committed by Brad Fitzpatrick
parent 038cdb4640
commit ba76578447
12 changed files with 157 additions and 88 deletions
-49
View File
@@ -17,15 +17,12 @@ import (
"tailscale.com/control/controlclient"
"tailscale.com/ipn"
"tailscale.com/net/sockstats"
"tailscale.com/posture"
"tailscale.com/tailcfg"
"tailscale.com/types/netmap"
"tailscale.com/util/clientmetric"
"tailscale.com/util/goroutines"
"tailscale.com/util/httpm"
"tailscale.com/util/set"
"tailscale.com/util/syspolicy/pkey"
"tailscale.com/util/syspolicy/ptype"
"tailscale.com/version"
)
@@ -52,9 +49,6 @@ var c2nHandlers = map[methodAndPath]c2nHandler{
// SSH
req("/ssh/usernames"): handleC2NSSHUsernames,
// Device posture.
req("GET /posture/identity"): handleC2NPostureIdentityGet,
// App Connectors.
req("GET /appconnector/routes"): handleC2NAppConnectorDomainRoutesGet,
@@ -324,46 +318,3 @@ func handleC2NSetNetfilterKind(b *LocalBackend, w http.ResponseWriter, r *http.R
w.WriteHeader(http.StatusNoContent)
}
func handleC2NPostureIdentityGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
b.logf("c2n: GET /posture/identity received")
res := tailcfg.C2NPostureIdentityResponse{}
// Only collect posture identity if enabled on the client,
// this will first check syspolicy, MDM settings like Registry
// on Windows or defaults on macOS. If they are not set, it falls
// back to the cli-flag, `--posture-checking`.
choice, err := b.polc.GetPreferenceOption(pkey.PostureChecking, ptype.ShowChoiceByPolicy)
if err != nil {
b.logf(
"c2n: failed to read PostureChecking from syspolicy, returning default from CLI: %s; got error: %s",
b.Prefs().PostureChecking(),
err,
)
}
if choice.ShouldEnable(b.Prefs().PostureChecking()) {
res.SerialNumbers, err = posture.GetSerialNumbers(b.polc, b.logf)
if err != nil {
b.logf("c2n: GetSerialNumbers returned error: %v", err)
}
// TODO(tailscale/corp#21371, 2024-07-10): once this has landed in a stable release
// and looks good in client metrics, remove this parameter and always report MAC
// addresses.
if r.FormValue("hwaddrs") == "true" {
res.IfaceHardwareAddrs, err = b.getHardwareAddrs()
if err != nil {
b.logf("c2n: GetHardwareAddrs returned error: %v", err)
}
}
} else {
res.PostureDisabled = true
}
b.logf("c2n: posture identity disabled=%v reported %d serials %d hwaddrs", res.PostureDisabled, len(res.SerialNumbers), len(res.IfaceHardwareAddrs))
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(res)
}
+3 -26
View File
@@ -68,7 +68,6 @@ import (
"tailscale.com/net/tsaddr"
"tailscale.com/net/tsdial"
"tailscale.com/paths"
"tailscale.com/posture"
"tailscale.com/syncs"
"tailscale.com/tailcfg"
"tailscale.com/tsd"
@@ -344,12 +343,6 @@ type LocalBackend struct {
// notified about.
lastNotifiedDriveShares *views.SliceView[*drive.Share, drive.ShareView]
// lastKnownHardwareAddrs is a list of the previous known hardware addrs.
// Previously known hwaddrs are kept to work around an issue on Windows
// where all addresses might disappear.
// http://go/corp/25168
lastKnownHardwareAddrs syncs.AtomicValue[[]string]
// lastSuggestedExitNode stores the last suggested exit node suggestion to
// avoid unnecessary churn between multiple equally-good options.
lastSuggestedExitNode tailcfg.StableNodeID
@@ -419,6 +412,9 @@ func (b *LocalBackend) NetMon() *netmon.Monitor {
return b.sys.NetMon.Get()
}
// PolicyClient returns the policy client for the backend.
func (b *LocalBackend) PolicyClient() policyclient.Client { return b.polc }
type metrics struct {
// advertisedRoutes is a metric that reports the number of network routes that are advertised by the local node.
// This informs the user of how many routes are being advertised by the local node, excluding exit routes.
@@ -6757,25 +6753,6 @@ func (b *LocalBackend) resetDialPlan() {
}
}
// getHardwareAddrs returns the hardware addresses for the machine. If the list
// of hardware addresses is empty, it will return the previously known hardware
// addresses. Both the current, and previously known hardware addresses might be
// empty.
func (b *LocalBackend) getHardwareAddrs() ([]string, error) {
addrs, err := posture.GetHardwareAddrs()
if err != nil {
return nil, err
}
if len(addrs) == 0 {
b.logf("getHardwareAddrs: got empty list of hwaddrs, returning previous list")
return b.lastKnownHardwareAddrs.Load(), nil
}
b.lastKnownHardwareAddrs.Store(addrs)
return addrs, nil
}
// resetForProfileChangeLockedOnEntry resets the backend for a profile change.
//
// b.mu must held on entry. It is released on exit.