client/web: add metric logging when viewing local / remote node (#10555)

Add metric logging for the case where a user is viewing a local or remote
node.

Updates https://github.com/tailscale/tailscale/issues/10261

Signed-off-by: Mario Minardi <mario@tailscale.com>
pull/10557/head
Mario Minardi 12 months ago committed by GitHub
parent 763b9daa84
commit 4e012794fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -448,6 +448,7 @@ func (s *Server) serveAPIAuth(w http.ResponseWriter, r *http.Request) {
switch { switch {
case sErr != nil && errors.Is(sErr, errNotUsingTailscale): case sErr != nil && errors.Is(sErr, errNotUsingTailscale):
// Restricted to the readonly view, no auth action to take. // Restricted to the readonly view, no auth action to take.
s.lc.IncrementCounter(r.Context(), "web_client_viewing_local", 1)
resp.AuthNeeded = "" resp.AuthNeeded = ""
case sErr != nil && errors.Is(sErr, errNotOwner): case sErr != nil && errors.Is(sErr, errNotOwner):
// Restricted to the readonly view, no auth action to take. // Restricted to the readonly view, no auth action to take.
@ -474,6 +475,12 @@ func (s *Server) serveAPIAuth(w http.ResponseWriter, r *http.Request) {
resp.CanManageNode = true resp.CanManageNode = true
resp.AuthNeeded = "" resp.AuthNeeded = ""
default: default:
// whois being nil implies local as the request did not come over Tailscale
if whois == nil || (whois.Node.StableID == status.Self.ID) {
s.lc.IncrementCounter(r.Context(), "web_client_viewing_local", 1)
} else {
s.lc.IncrementCounter(r.Context(), "web_client_viewing_remote", 1)
}
resp.AuthNeeded = tailscaleAuth resp.AuthNeeded = tailscaleAuth
} }

@ -790,6 +790,7 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
}, },
UserProfile: otherUser, UserProfile: otherUser,
} }
nonTailscaleIP := "10.100.2.3"
testControlURL := &defaultControlURL testControlURL := &defaultControlURL
var loggedMetrics []string var loggedMetrics []string
@ -820,9 +821,9 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
waitAuthURL: mockWaitAuthURL, waitAuthURL: mockWaitAuthURL,
} }
remoteNodeCookie := "ts-cookie-remote-node" authenticatedRemoteNodeCookie := "ts-cookie-remote-node-authenticated"
s.browserSessions.Store(remoteNodeCookie, &browserSession{ s.browserSessions.Store(authenticatedRemoteNodeCookie, &browserSession{
ID: remoteNodeCookie, ID: authenticatedRemoteNodeCookie,
SrcNode: remoteNode.Node.ID, SrcNode: remoteNode.Node.ID,
SrcUser: user.ID, SrcUser: user.ID,
Created: oneHourAgo, Created: oneHourAgo,
@ -830,9 +831,9 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
AuthURL: *testControlURL + testAuthPathSuccess, AuthURL: *testControlURL + testAuthPathSuccess,
Authenticated: true, Authenticated: true,
}) })
localNodeCookie := "ts-cookie-local-node" authenticatedLocalNodeCookie := "ts-cookie-local-node-authenticated"
s.browserSessions.Store(localNodeCookie, &browserSession{ s.browserSessions.Store(authenticatedLocalNodeCookie, &browserSession{
ID: localNodeCookie, ID: authenticatedLocalNodeCookie,
SrcNode: localNode.Node.ID, SrcNode: localNode.Node.ID,
SrcUser: user.ID, SrcUser: user.ID,
Created: oneHourAgo, Created: oneHourAgo,
@ -840,6 +841,26 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
AuthURL: *testControlURL + testAuthPathSuccess, AuthURL: *testControlURL + testAuthPathSuccess,
Authenticated: true, Authenticated: true,
}) })
unauthenticatedRemoteNodeCookie := "ts-cookie-remote-node-unauthenticated"
s.browserSessions.Store(unauthenticatedRemoteNodeCookie, &browserSession{
ID: unauthenticatedRemoteNodeCookie,
SrcNode: remoteNode.Node.ID,
SrcUser: user.ID,
Created: oneHourAgo,
AuthID: testAuthPathSuccess,
AuthURL: *testControlURL + testAuthPathSuccess,
Authenticated: false,
})
unauthenticatedLocalNodeCookie := "ts-cookie-local-node-unauthenticated"
s.browserSessions.Store(unauthenticatedLocalNodeCookie, &browserSession{
ID: unauthenticatedLocalNodeCookie,
SrcNode: localNode.Node.ID,
SrcUser: user.ID,
Created: oneHourAgo,
AuthID: testAuthPathSuccess,
AuthURL: *testControlURL + testAuthPathSuccess,
Authenticated: false,
})
tests := []struct { tests := []struct {
name string name string
@ -850,34 +871,52 @@ func TestServeAPIAuthMetricLogging(t *testing.T) {
}{ }{
{ {
name: "managing-remote", name: "managing-remote",
cookie: remoteNodeCookie, cookie: authenticatedRemoteNodeCookie,
remoteAddr: remoteIP, remoteAddr: remoteIP,
wantLoggedMetric: "web_client_managing_remote", wantLoggedMetric: "web_client_managing_remote",
}, },
{ {
name: "managing-local", name: "managing-local",
cookie: localNodeCookie, cookie: authenticatedLocalNodeCookie,
remoteAddr: localIP, remoteAddr: localIP,
wantLoggedMetric: "web_client_managing_local", wantLoggedMetric: "web_client_managing_local",
}, },
{ {
name: "viewing-not-owner", name: "viewing-not-owner",
cookie: remoteNodeCookie, cookie: authenticatedRemoteNodeCookie,
remoteAddr: otherIP, remoteAddr: otherIP,
wantLoggedMetric: "web_client_viewing_not_owner", wantLoggedMetric: "web_client_viewing_not_owner",
}, },
{ {
name: "viewing-local-tagged", name: "viewing-local-tagged",
cookie: localNodeCookie, cookie: authenticatedLocalNodeCookie,
remoteAddr: localTaggedIP, remoteAddr: localTaggedIP,
wantLoggedMetric: "web_client_viewing_local_tag", wantLoggedMetric: "web_client_viewing_local_tag",
}, },
{ {
name: "viewing-remote-tagged", name: "viewing-remote-tagged",
cookie: remoteNodeCookie, cookie: authenticatedRemoteNodeCookie,
remoteAddr: remoteTaggedIP, remoteAddr: remoteTaggedIP,
wantLoggedMetric: "web_client_viewing_remote_tag", wantLoggedMetric: "web_client_viewing_remote_tag",
}, },
{
name: "viewing-local-non-tailscale",
cookie: authenticatedLocalNodeCookie,
remoteAddr: nonTailscaleIP,
wantLoggedMetric: "web_client_viewing_local",
},
{
name: "viewing-local-unauthenticated",
cookie: unauthenticatedLocalNodeCookie,
remoteAddr: localIP,
wantLoggedMetric: "web_client_viewing_local",
},
{
name: "viewing-remote-unauthenticated",
cookie: unauthenticatedRemoteNodeCookie,
remoteAddr: remoteIP,
wantLoggedMetric: "web_client_viewing_remote",
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

Loading…
Cancel
Save