From 9726e1f2089beadff6a0fd86fe1f8fe99d3daf5a Mon Sep 17 00:00:00 2001 From: Nick Khyl Date: Tue, 4 Feb 2025 15:52:21 -0600 Subject: [PATCH] ipn/{ipnserver,localapi},tsnet: use ipnauth.Self as the actor in tsnet localapi handlers With #14843 merged, (*localapi.Handler).servePrefs() now requires a non-nil actor, and other places may soon require it as well. In this PR, we update localapi.NewHandler with a new required parameter for the actor. We then update tsnet to use ipnauth.Self. We also rearrange the code in (*ipnserver.Server).serveHTTP() to pass the actor via Handler's constructor instead of the field. Updates #14823 Signed-off-by: Nick Khyl --- ipn/ipnserver/server.go | 14 +++++++------- ipn/localapi/localapi.go | 7 +++---- tsnet/tsnet.go | 5 +++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index a08643667..5df9375a4 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -196,22 +196,22 @@ func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) { defer onDone() if strings.HasPrefix(r.URL.Path, "/localapi/") { - lah := localapi.NewHandler(lb, s.logf, s.backendLogID) if actor, ok := ci.(*actor); ok { - lah.PermitRead, lah.PermitWrite = actor.Permissions(lb.OperatorUserID()) - lah.PermitCert = actor.CanFetchCerts() reason, err := base64.StdEncoding.DecodeString(r.Header.Get(apitype.RequestReasonHeader)) if err != nil { http.Error(w, "invalid reason header", http.StatusBadRequest) return } - lah.Actor = actorWithAccessOverride(actor, string(reason)) + ci = actorWithAccessOverride(actor, string(reason)) + } + + lah := localapi.NewHandler(ci, lb, s.logf, s.backendLogID) + if actor, ok := ci.(*actor); ok { + lah.PermitRead, lah.PermitWrite = actor.Permissions(lb.OperatorUserID()) + lah.PermitCert = actor.CanFetchCerts() } else if testenv.InTest() { lah.PermitRead, lah.PermitWrite = true, true } - if lah.Actor == nil { - lah.Actor = ci - } lah.ServeHTTP(w, r) return } diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index c75f732b6..d1f07ea4e 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -169,10 +169,9 @@ var ( metrics = map[string]*clientmetric.Metric{} ) -// NewHandler creates a new LocalAPI HTTP handler. All parameters except netMon -// are required (if non-nil it's used to do faster interface lookups). -func NewHandler(b *ipnlocal.LocalBackend, logf logger.Logf, logID logid.PublicID) *Handler { - return &Handler{b: b, logf: logf, backendLogID: logID, clock: tstime.StdClock{}} +// NewHandler creates a new LocalAPI HTTP handler. All parameters are required. +func NewHandler(actor ipnauth.Actor, b *ipnlocal.LocalBackend, logf logger.Logf, logID logid.PublicID) *Handler { + return &Handler{Actor: actor, b: b, logf: logf, backendLogID: logID, clock: tstime.StdClock{}} } type Handler struct { diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 23a9f9a98..e1494c65f 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -33,6 +33,7 @@ import ( "tailscale.com/health" "tailscale.com/hostinfo" "tailscale.com/ipn" + "tailscale.com/ipn/ipnauth" "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/ipnstate" "tailscale.com/ipn/localapi" @@ -272,7 +273,7 @@ func (s *Server) Loopback() (addr string, proxyCred, localAPICred string, err er // out the CONNECT code from tailscaled/proxy.go that uses // httputil.ReverseProxy and adding auth support. go func() { - lah := localapi.NewHandler(s.lb, s.logf, s.logid) + lah := localapi.NewHandler(ipnauth.Self, s.lb, s.logf, s.logid) lah.PermitWrite = true lah.PermitRead = true lah.RequiredPassword = s.localAPICred @@ -667,7 +668,7 @@ func (s *Server) start() (reterr error) { go s.printAuthURLLoop() // Run the localapi handler, to allow fetching LetsEncrypt certs. - lah := localapi.NewHandler(lb, tsLogf, s.logid) + lah := localapi.NewHandler(ipnauth.Self, lb, tsLogf, s.logid) lah.PermitWrite = true lah.PermitRead = true