mirror of
https://github.com/tailscale/tailscale.git
synced 2026-10-09 03:42:01 -04:00
ipn/localapi: restrict debug-log access to PermitWrite (#21447)
The debug-log endpoint was gated on PermitRead, which any local user connecting to the world-writable tailscaled socket passes. Although forged log entries are always possible, we should limit the ability for local users to influence that flow with respects to a given node. This change requires PermitWrite for debug-log, matching the trust level of every other mutating debug endpoint. Also add a buildfeatures.HasDebug guard to debug-dial-types for parity with serveDebug. Fixes tailscale/corp#48143 Change-Id: I0c0044b6b44fe7cbfb6734ac18bca3dc36eaffbf Signed-off-by: Mike Jensen <mikej@tailscale.com>
This commit is contained in:
1 parent
7f51756f2e
commit
94ea82ab55
3 files changed
+47
-1
No files matched your search
@@ -522,7 +522,7 @@ func (h *Handler) serveDebugLog(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
if !h.PermitRead {
|
||||
if !h.PermitWrite {
|
||||
http.Error(w, "debug-log access denied", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/ipn"
|
||||
@@ -73,3 +74,44 @@ func TestServeDevSetStateStore(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeDebugLogGate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
desc string
|
||||
permitRead bool
|
||||
permitWrite bool
|
||||
wantStatus int
|
||||
}{
|
||||
{
|
||||
desc: "read-only-denied",
|
||||
permitRead: true,
|
||||
wantStatus: http.StatusForbidden,
|
||||
},
|
||||
{
|
||||
desc: "write-allowed",
|
||||
permitRead: true,
|
||||
permitWrite: true,
|
||||
wantStatus: http.StatusNoContent,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
h := handlerForTest(t, &Handler{
|
||||
PermitRead: tt.permitRead,
|
||||
PermitWrite: tt.permitWrite,
|
||||
b: newTestLocalBackend(t),
|
||||
})
|
||||
req := httptest.NewRequest("POST", "http://local-tailscaled.sock/localapi/v0/debug-log",
|
||||
strings.NewReader(`{"prefix":"test","lines":["line"]}`))
|
||||
resp := httptest.NewRecorder()
|
||||
h.serveDebugLog(resp, req)
|
||||
|
||||
if resp.Code != tt.wantStatus {
|
||||
t.Errorf("resp.Code = %d, want %d; body: %s", resp.Code, tt.wantStatus, resp.Body.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"tailscale.com/tailcfg/peercap"
|
||||
"tailscale.com/tsd"
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/tstime"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/logid"
|
||||
@@ -53,6 +54,9 @@ func handlerForTest(t testing.TB, h *Handler) *Handler {
|
||||
if h.logf == nil {
|
||||
h.logf = logger.TestLogger(t)
|
||||
}
|
||||
if h.clock == nil {
|
||||
h.clock = tstime.StdClock{}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user