cmd/tailscale: propagate tailscaled 403s as AccessDeniedErrors

So Linux/etc CLI users get helpful advice to run tailscale
with --operator=$USER when they try to 'tailscale file {cp,get}'
but are mysteriously forbidden.

Signed-off-by: David Eger <eger@google.com>
Signed-off-by: David Eger <david.eger@gmail.com>
This commit is contained in:
davideger 2022-01-25 09:58:21 -08:00 committed by GitHub
parent f3c0023add
commit f31546809f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 12 deletions

View File

@ -104,6 +104,10 @@ func doLocalRequestNiceError(req *http.Request) (*http.Response, error) {
if server := res.Header.Get("Tailscale-Version"); server != "" && server != version.Long && onVersionMismatch != nil { if server := res.Header.Get("Tailscale-Version"); server != "" && server != version.Long && onVersionMismatch != nil {
onVersionMismatch(version.Long, server) onVersionMismatch(version.Long, server)
} }
if res.StatusCode == 403 {
all, _ := ioutil.ReadAll(res.Body)
return nil, &AccessDeniedError{errors.New(errorMessageFromBody(all))}
}
return res, nil return res, nil
} }
if ue, ok := err.(*url.Error); ok { if ue, ok := err.(*url.Error); ok {
@ -179,10 +183,6 @@ func send(ctx context.Context, method, path string, wantStatus int, body io.Read
return nil, err return nil, err
} }
if res.StatusCode != wantStatus { if res.StatusCode != wantStatus {
if res.StatusCode == 403 {
return nil, &AccessDeniedError{errors.New(errorMessageFromBody(slurp))}
}
err := fmt.Errorf("HTTP %s: %s (expected %v)", res.Status, slurp, wantStatus)
return nil, bestError(err, slurp) return nil, bestError(err, slurp)
} }
return slurp, nil return slurp, nil
@ -294,7 +294,7 @@ func GetWaitingFile(ctx context.Context, baseName string) (rc io.ReadCloser, siz
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
res, err := DoLocalRequest(req) res, err := doLocalRequestNiceError(req)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
@ -343,7 +343,7 @@ func PushFile(ctx context.Context, target tailcfg.StableNodeID, size int64, name
return nil return nil
} }
all, _ := io.ReadAll(res.Body) all, _ := io.ReadAll(res.Body)
return fmt.Errorf("%s: %s", res.Status, all) return bestError(fmt.Errorf("%s: %s", res.Status, all), all)
} }
func CheckIPForwarding(ctx context.Context) error { func CheckIPForwarding(ctx context.Context) error {

View File

@ -13,7 +13,6 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"runtime"
"strings" "strings"
"github.com/peterbourgon/ff/v3/ffcli" "github.com/peterbourgon/ff/v3/ffcli"
@ -92,9 +91,6 @@ func runCert(ctx context.Context, args []string) error {
certArgs.keyFile = domain + ".key" certArgs.keyFile = domain + ".key"
} }
certPEM, keyPEM, err := tailscale.CertPair(ctx, domain) certPEM, keyPEM, err := tailscale.CertPair(ctx, domain)
if tailscale.IsAccessDeniedError(err) && os.Getuid() != 0 && runtime.GOOS != "windows" {
return fmt.Errorf("%v\n\nUse 'sudo tailscale cert' or 'tailscale up --operator=$USER' to not require root.", err)
}
if err != nil { if err != nil {
return err return err
} }

View File

@ -171,6 +171,9 @@ change in the future.
}) })
err := rootCmd.Run(context.Background()) err := rootCmd.Run(context.Background())
if tailscale.IsAccessDeniedError(err) && os.Getuid() != 0 && runtime.GOOS != "windows" {
return fmt.Errorf("%v\n\nUse 'sudo tailscale %s' or 'tailscale up --operator=$USER' to not require root.", err, strings.Join(args, " "))
}
if errors.Is(err, flag.ErrHelp) { if errors.Is(err, flag.ErrHelp) {
return nil return nil
} }

View File

@ -324,7 +324,7 @@ func runFileGet(ctx context.Context, args []string) error {
for { for {
wfs, err = tailscale.WaitingFiles(ctx) wfs, err = tailscale.WaitingFiles(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting WaitingFiles: %v", err) return fmt.Errorf("getting WaitingFiles: %w", err)
} }
if len(wfs) != 0 || !getArgs.wait { if len(wfs) != 0 || !getArgs.wait {
break break
@ -379,7 +379,7 @@ func wipeInbox(ctx context.Context) error {
} }
wfs, err := tailscale.WaitingFiles(ctx) wfs, err := tailscale.WaitingFiles(ctx)
if err != nil { if err != nil {
return fmt.Errorf("getting WaitingFiles: %v", err) return fmt.Errorf("getting WaitingFiles: %w", err)
} }
deleted := 0 deleted := 0
for _, wf := range wfs { for _, wf := range wfs {