From 8a792ab540f7744c669b6952a257c32a7f6f0ea2 Mon Sep 17 00:00:00 2001 From: Percy Wegmann Date: Fri, 7 Feb 2025 09:28:09 -0600 Subject: [PATCH] tsnet: provide AuthenticatedAPITransport for use with tailscale.com/client/tailscale/v2 This allows use of the officially supported control server API, authenticated with the tsnet node's nodekey. Updates tailscale/corp#22748 Signed-off-by: Percy Wegmann --- tsnet/tsnet.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index f5fcd416f..6fffa9aff 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -931,8 +931,7 @@ func getTSNetDir(logf logger.Logf, confDir, prog string) (string, error) { // requests to the Tailscale control server. // It requires the user to set tailscale.I_Acknowledge_This_API_Is_Unstable. // -// TODO: (percy) provide a way to use Noise for the official API at -// tailscale.com/client/tailscale/v2. +// Deprecated: use AuthenticatedAPITransport with tailscale.com/client/tailscale/v2 instead. func (s *Server) APIClient() (*tailscale.Client, error) { if !tailscale.I_Acknowledge_This_API_Is_Unstable { return nil, errors.New("use of Client without setting I_Acknowledge_This_API_Is_Unstable") @@ -947,6 +946,32 @@ func (s *Server) APIClient() (*tailscale.Client, error) { return c, nil } +// AuthenticatedAPITransport provides an HTTP transport that can be used with +// the control server API without needing additional authentication details. It +// authenticates using the current client's nodekey. +// +// For example: +// +// import "net/http" +// import "tailscale.com/client/tailscale/v2" +// import "tailscale.com/tsnet" +// +// var s *tsnet.Server +// ... +// rt, err := s.AuthenticatedAPITransport() +// // handler err ... +// var client tailscale.Client{HTTP: http.Client{ +// Timeout: 1*time.Minute, +// UserAgent: "your-useragent-here", +// Transport: rt, +// }} +func (s *Server) AuthenticatedAPITransport() (http.RoundTripper, error) { + if err := s.Start(); err != nil { + return nil, err + } + return s.lb.KeyProvingNoiseRoundTripper(), nil +} + // Listen announces only on the Tailscale network. // It will start the server if it has not been started yet. //