Browse Source

ipn/ipnlocal: add VIPServices hash to return body of vip-services c2n endpoint

This commit updates the return body of c2n endpoint /vip-services to keep hash generation logic on client side.

Updates tailscale/corp#24510

Signed-off-by: KevinLiang10 <[email protected]>
KevinLiang10 1 year ago
parent
commit
2af255790d
3 changed files with 22 additions and 4 deletions
  1. 5 1
      ipn/ipnlocal/c2n.go
  2. 2 3
      ipn/ipnlocal/local.go
  3. 15 0
      tailcfg/c2ntypes.go

+ 5 - 1
ipn/ipnlocal/c2n.go

@@ -274,8 +274,12 @@ func handleC2NSetNetfilterKind(b *LocalBackend, w http.ResponseWriter, r *http.R
 
 func handleC2NVIPServicesGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
 	b.logf("c2n: GET /vip-services received")
+	var res tailcfg.C2NVIPServicesResponse
+	res.VIPServices = b.VIPServices()
+	res.ServicesHash = b.vipServiceHash(res.VIPServices)
 
-	json.NewEncoder(w).Encode(b.VIPServices())
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(res)
 }
 
 func handleC2NUpdateGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {

+ 2 - 3
ipn/ipnlocal/local.go

@@ -5022,7 +5022,7 @@ func (b *LocalBackend) applyPrefsToHostinfoLocked(hi *tailcfg.Hostinfo, prefs ip
 	}
 	hi.SSH_HostKeys = sshHostKeys
 
-	hi.ServicesHash = b.vipServiceHashLocked(prefs)
+	hi.ServicesHash = b.vipServiceHash(b.vipServicesFromPrefsLocked(prefs))
 
 	// The Hostinfo.WantIngress field tells control whether this node wants to
 	// be wired up for ingress connections. If harmless if it's accidentally
@@ -7661,8 +7661,7 @@ func (b *LocalBackend) VIPServices() []*tailcfg.VIPService {
 	return b.vipServicesFromPrefsLocked(b.pm.CurrentPrefs())
 }
 
-func (b *LocalBackend) vipServiceHashLocked(prefs ipn.PrefsView) string {
-	services := b.vipServicesFromPrefsLocked(prefs)
+func (b *LocalBackend) vipServiceHash(services []*tailcfg.VIPService) string {
 	if len(services) == 0 {
 		return ""
 	}

+ 15 - 0
tailcfg/c2ntypes.go

@@ -102,3 +102,18 @@ type C2NTLSCertInfo struct {
 	// TODO(bradfitz): add fields for whether an ACME fetch is currently in
 	// process and when it started, etc.
 }
+
+// C2NVIPServicesResponse is the response (from node to control) from the
+// /vip-services handler.
+//
+// It returns the list of VIPServices that the node is currently serving with
+// their port info and whether they are active or not. It also returns a hash of
+// the response to allow the control server to detect changes.
+type C2NVIPServicesResponse struct {
+	// VIPServices is the list of VIP services that the node is currently serving.
+	VIPServices []*VIPService `json:",omitempty"`
+
+	// ServicesHash is the hash of VIPServices to allow the control server to detect
+	// changes. This value matches what is reported in latest [Hostinfo.ServicesHash].
+	ServicesHash string
+}