diff --git a/ipn/ipnlocal/c2n.go b/ipn/ipnlocal/c2n.go index afe9f56ee..135ddc8c3 100644 --- a/ipn/ipnlocal/c2n.go +++ b/ipn/ipnlocal/c2n.go @@ -24,6 +24,7 @@ import ( "tailscale.com/clientupdate" "tailscale.com/envknob" "tailscale.com/net/sockstats" + "tailscale.com/posture" "tailscale.com/tailcfg" "tailscale.com/util/clientmetric" "tailscale.com/util/goroutines" @@ -67,6 +68,14 @@ func (b *LocalBackend) handleC2N(w http.ResponseWriter, r *http.Request) { } else { http.Error(w, "no log flusher wired up", http.StatusInternalServerError) } + case "/posture/identity": + switch r.Method { + case httpm.GET: + b.handleC2NPostureIdentityGet(w, r) + default: + http.Error(w, "bad method", http.StatusMethodNotAllowed) + return + } case "/debug/goroutines": w.Header().Set("Content-Type", "text/plain") w.Write(goroutines.ScrubbedGoroutineDump(true)) @@ -215,6 +224,29 @@ func (b *LocalBackend) handleC2NUpdatePost(w http.ResponseWriter, r *http.Reques }() } +func (b *LocalBackend) handleC2NPostureIdentityGet(w http.ResponseWriter, r *http.Request) { + b.logf("c2n: GET /posture/identity received") + + res := tailcfg.C2NPostureIdentityResponse{} + + // TODO(kradalby): Use syspolicy + envknob to allow Win registry, + // macOS defaults and env to override this setting. + if b.Prefs().PostureChecking() { + sns, err := posture.GetSerialNumbers() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + res.SerialNumbers = sns + } else { + res.PostureDisabled = true + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(res) +} + func (b *LocalBackend) newC2NUpdateResponse() tailcfg.C2NUpdateResponse { // If NewUpdater does not return an error, we can update the installation. // Exception: When version.IsMacSysExt returns true, we don't support that diff --git a/tailcfg/c2ntypes.go b/tailcfg/c2ntypes.go index 44f3ac70c..042595e22 100644 --- a/tailcfg/c2ntypes.go +++ b/tailcfg/c2ntypes.go @@ -52,3 +52,15 @@ type C2NUpdateResponse struct { // Started indicates whether the update has started. Started bool } + +// C2NPostureIdentityResponse contains either a set of identifying serial number +// from the client or a boolean indicating that the machine has opted out of +// posture collection. +type C2NPostureIdentityResponse struct { + // SerialNumbers is a list of serial numbers of the client machine. + SerialNumbers []string `json:",omitempty"` + + // PostureDisabled indicates if the machine has opted out of + // device posture collection. + PostureDisabled bool `json:",omitempty"` +}