Просмотр исходного кода

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

Updates #12614

Change-Id: I9d08a1330b9c55e1a23e7979a707e11d8e090d79
Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 5 месяцев назад
Родитель
Сommit
ba76578447

+ 1 - 3
cmd/k8s-operator/depaware.txt

@@ -17,7 +17,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
    W 💣 github.com/dblohm7/wingoes/com/automation                    from tailscale.com/util/osdiag/internal/wsc
    W    github.com/dblohm7/wingoes/internal                          from github.com/dblohm7/wingoes/com
    W 💣 github.com/dblohm7/wingoes/pe                                from tailscale.com/util/osdiag+
-  LW 💣 github.com/digitalocean/go-smbios/smbios                     from tailscale.com/posture
         github.com/distribution/reference                            from tailscale.com/cmd/k8s-operator
         github.com/emicklei/go-restful/v3                            from k8s.io/kube-openapi/pkg/common
         github.com/emicklei/go-restful/v3/log                        from github.com/emicklei/go-restful/v3
@@ -784,7 +783,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
         tailscale.com/net/udprelay/status                            from tailscale.com/client/local
         tailscale.com/omit                                           from tailscale.com/ipn/conffile
         tailscale.com/paths                                          from tailscale.com/client/local+
-        tailscale.com/posture                                        from tailscale.com/ipn/ipnlocal
         tailscale.com/proxymap                                       from tailscale.com/tsd+
      💣 tailscale.com/safesocket                                     from tailscale.com/client/local+
         tailscale.com/sessionrecording                               from tailscale.com/k8s-operator/sessionrecording+
@@ -1099,7 +1097,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
         internal/unsafeheader                                        from internal/reflectlite+
         io                                                           from bufio+
         io/fs                                                        from crypto/x509+
-        io/ioutil                                                    from github.com/digitalocean/go-smbios/smbios+
+        io/ioutil                                                    from github.com/godbus/dbus/v5+
         iter                                                         from go/ast+
         log                                                          from expvar+
         log/internal                                                 from log+

+ 0 - 3
cmd/tailscaled/depaware-minbox.txt

@@ -1,6 +1,5 @@
 tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/depaware)
 
-        github.com/digitalocean/go-smbios/smbios                     from tailscale.com/posture
         github.com/gaissmai/bart                                     from tailscale.com/net/ipset+
         github.com/gaissmai/bart/internal/bitset                     from github.com/gaissmai/bart+
         github.com/gaissmai/bart/internal/sparse                     from github.com/gaissmai/bart
@@ -116,7 +115,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/net/udprelay/endpoint                          from tailscale.com/wgengine/magicsock
         tailscale.com/omit                                           from tailscale.com/ipn/conffile
         tailscale.com/paths                                          from tailscale.com/cmd/tailscaled+
-        tailscale.com/posture                                        from tailscale.com/ipn/ipnlocal
         tailscale.com/proxymap                                       from tailscale.com/tsd
         tailscale.com/safesocket                                     from tailscale.com/cmd/tailscaled+
         tailscale.com/syncs                                          from tailscale.com/cmd/tailscaled+
@@ -374,7 +372,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         internal/unsafeheader                                        from internal/reflectlite+
         io                                                           from bufio+
         io/fs                                                        from crypto/x509+
-        io/ioutil                                                    from github.com/digitalocean/go-smbios/smbios
         iter                                                         from bytes+
         log                                                          from expvar+
         log/internal                                                 from log

+ 2 - 1
cmd/tailscaled/depaware.txt

@@ -282,6 +282,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
    L    tailscale.com/feature/linuxdnsfight                          from tailscale.com/feature/condregister
         tailscale.com/feature/portlist                               from tailscale.com/feature/condregister
         tailscale.com/feature/portmapper                             from tailscale.com/feature/condregister/portmapper
+        tailscale.com/feature/posture                                from tailscale.com/feature/condregister
         tailscale.com/feature/relayserver                            from tailscale.com/feature/condregister
    L    tailscale.com/feature/sdnotify                               from tailscale.com/feature/condregister
         tailscale.com/feature/syspolicy                              from tailscale.com/feature/condregister+
@@ -364,7 +365,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/omit                                           from tailscale.com/ipn/conffile
         tailscale.com/paths                                          from tailscale.com/client/local+
      💣 tailscale.com/portlist                                       from tailscale.com/feature/portlist
-        tailscale.com/posture                                        from tailscale.com/ipn/ipnlocal
+        tailscale.com/posture                                        from tailscale.com/feature/posture
         tailscale.com/proxymap                                       from tailscale.com/tsd+
      💣 tailscale.com/safesocket                                     from tailscale.com/client/local+
   LD    tailscale.com/sessionrecording                               from tailscale.com/ssh/tailssh

+ 1 - 3
cmd/tsidp/depaware.txt

@@ -14,7 +14,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
    W 💣 github.com/dblohm7/wingoes/com/automation                    from tailscale.com/util/osdiag/internal/wsc
    W    github.com/dblohm7/wingoes/internal                          from github.com/dblohm7/wingoes/com
    W 💣 github.com/dblohm7/wingoes/pe                                from tailscale.com/util/osdiag+
-  LW 💣 github.com/digitalocean/go-smbios/smbios                     from tailscale.com/posture
         github.com/fxamacker/cbor/v2                                 from tailscale.com/tka
         github.com/gaissmai/bart                                     from tailscale.com/net/ipset+
         github.com/gaissmai/bart/internal/bitset                     from github.com/gaissmai/bart+
@@ -212,7 +211,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
         tailscale.com/net/udprelay/status                            from tailscale.com/client/local
         tailscale.com/omit                                           from tailscale.com/ipn/conffile
         tailscale.com/paths                                          from tailscale.com/client/local+
-        tailscale.com/posture                                        from tailscale.com/ipn/ipnlocal
         tailscale.com/proxymap                                       from tailscale.com/tsd+
      💣 tailscale.com/safesocket                                     from tailscale.com/client/local+
         tailscale.com/syncs                                          from tailscale.com/control/controlhttp+
@@ -515,7 +513,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
         internal/unsafeheader                                        from internal/reflectlite+
         io                                                           from bufio+
         io/fs                                                        from crypto/x509+
-        io/ioutil                                                    from github.com/digitalocean/go-smbios/smbios+
+        io/ioutil                                                    from github.com/godbus/dbus/v5+
         iter                                                         from bytes+
         log                                                          from expvar+
         log/internal                                                 from log

+ 13 - 0
feature/buildfeatures/feature_posture_disabled.go

@@ -0,0 +1,13 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+// Code generated by gen.go; DO NOT EDIT.
+
+//go:build ts_omit_posture
+
+package buildfeatures
+
+// HasPosture is whether the binary was built with support for modular feature "Device posture checking support".
+// Specifically, it's whether the binary was NOT built with the "ts_omit_posture" build tag.
+// It's a const so it can be used for dead code elimination.
+const HasPosture = false

+ 13 - 0
feature/buildfeatures/feature_posture_enabled.go

@@ -0,0 +1,13 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+// Code generated by gen.go; DO NOT EDIT.
+
+//go:build !ts_omit_posture
+
+package buildfeatures
+
+// HasPosture is whether the binary was built with support for modular feature "Device posture checking support".
+// Specifically, it's whether the binary was NOT built with the "ts_omit_posture" build tag.
+// It's a const so it can be used for dead code elimination.
+const HasPosture = true

+ 8 - 0
feature/condregister/maybe_posture.go

@@ -0,0 +1,8 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+//go:build !ts_omit_posture
+
+package condregister
+
+import _ "tailscale.com/feature/posture"

+ 1 - 0
feature/featuretags/featuretags.go

@@ -139,6 +139,7 @@ var Features = map[FeatureTag]FeatureMeta{
 	},
 	"portlist":   {"PortList", "Optionally advertise listening service ports", nil},
 	"portmapper": {"PortMapper", "NAT-PMP/PCP/UPnP port mapping support", nil},
+	"posture":    {"Posture", "Device posture checking support", nil},
 	"netlog": {
 		Sym:  "NetLog",
 		Desc: "Network flow logging support",

+ 114 - 0
feature/posture/posture.go

@@ -0,0 +1,114 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+// Package posture registers support for device posture checking,
+// reporting machine-specific information to the control plane
+// when enabled by the user and tailnet.
+package posture
+
+import (
+	"encoding/json"
+	"net/http"
+
+	"tailscale.com/ipn/ipnext"
+	"tailscale.com/ipn/ipnlocal"
+	"tailscale.com/posture"
+	"tailscale.com/syncs"
+	"tailscale.com/tailcfg"
+	"tailscale.com/types/logger"
+	"tailscale.com/util/syspolicy/pkey"
+	"tailscale.com/util/syspolicy/ptype"
+)
+
+func init() {
+	ipnext.RegisterExtension("posture", newExtension)
+	ipnlocal.RegisterC2N("GET /posture/identity", handleC2NPostureIdentityGet)
+}
+
+func newExtension(logf logger.Logf, b ipnext.SafeBackend) (ipnext.Extension, error) {
+	e := &extension{
+		logf: logger.WithPrefix(logf, "posture: "),
+	}
+	return e, nil
+}
+
+type extension struct {
+	logf logger.Logf
+
+	// 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]
+}
+
+func (e *extension) Name() string             { return "posture" }
+func (e *extension) Init(h ipnext.Host) error { return nil }
+func (e *extension) Shutdown() error          { return nil }
+
+func handleC2NPostureIdentityGet(b *ipnlocal.LocalBackend, w http.ResponseWriter, r *http.Request) {
+	e, ok := ipnlocal.GetExt[*extension](b)
+	if !ok {
+		http.Error(w, "posture extension not available", http.StatusInternalServerError)
+		return
+	}
+	e.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.PolicyClient().GetPreferenceOption(pkey.PostureChecking, ptype.ShowChoiceByPolicy)
+	if err != nil {
+		e.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.PolicyClient(), e.logf)
+		if err != nil {
+			e.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 = e.getHardwareAddrs()
+			if err != nil {
+				e.logf("c2n: GetHardwareAddrs returned error: %v", err)
+			}
+		}
+	} else {
+		res.PostureDisabled = true
+	}
+
+	e.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)
+}
+
+// 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 (e *extension) getHardwareAddrs() ([]string, error) {
+	addrs, err := posture.GetHardwareAddrs()
+	if err != nil {
+		return nil, err
+	}
+
+	if len(addrs) == 0 {
+		e.logf("getHardwareAddrs: got empty list of hwaddrs, returning previous list")
+		return e.lastKnownHardwareAddrs.Load(), nil
+	}
+
+	e.lastKnownHardwareAddrs.Store(addrs)
+	return addrs, nil
+}

+ 0 - 49
ipn/ipnlocal/c2n.go

@@ -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
ipn/ipnlocal/local.go

@@ -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.

+ 1 - 3
tsnet/depaware.txt

@@ -14,7 +14,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
    W 💣 github.com/dblohm7/wingoes/com/automation                    from tailscale.com/util/osdiag/internal/wsc
    W    github.com/dblohm7/wingoes/internal                          from github.com/dblohm7/wingoes/com
    W 💣 github.com/dblohm7/wingoes/pe                                from tailscale.com/util/osdiag+
-  LW 💣 github.com/digitalocean/go-smbios/smbios                     from tailscale.com/posture
         github.com/fxamacker/cbor/v2                                 from tailscale.com/tka
         github.com/gaissmai/bart                                     from tailscale.com/net/ipset+
         github.com/gaissmai/bart/internal/bitset                     from github.com/gaissmai/bart+
@@ -208,7 +207,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
         tailscale.com/net/udprelay/status                            from tailscale.com/client/local
         tailscale.com/omit                                           from tailscale.com/ipn/conffile
         tailscale.com/paths                                          from tailscale.com/client/local+
-        tailscale.com/posture                                        from tailscale.com/ipn/ipnlocal
         tailscale.com/proxymap                                       from tailscale.com/tsd+
      💣 tailscale.com/safesocket                                     from tailscale.com/client/local+
         tailscale.com/syncs                                          from tailscale.com/control/controlhttp+
@@ -508,7 +506,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
         internal/unsafeheader                                        from internal/reflectlite+
         io                                                           from bufio+
         io/fs                                                        from crypto/x509+
-        io/ioutil                                                    from github.com/digitalocean/go-smbios/smbios+
+        io/ioutil                                                    from github.com/godbus/dbus/v5+
         iter                                                         from bytes+
         log                                                          from expvar+
         log/internal                                                 from log