1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16
17 package auth
18
19 import (
20 "context"
21 "errors"
22 "log"
23 "net/http"
24 "strings"
25
26 "tailscale.com/client/tailscale"
27 )
28
29 func newTailscaleAuth(arg string) (AuthMode, error) {
30 if arg == "full-access-to-tailnet" {
31 return &tailscaleAuth{any: true}, nil
32 }
33 if strings.Contains(arg, "@") {
34 lc := &tailscale.LocalClient{}
35 return &tailscaleAuth{lc: lc, anyForUser: arg}, nil
36 }
37
38 return nil, errors.New("unknown tailscale auth mode")
39 }
40
41 type tailscaleAuth struct {
42 any bool
43
44 lc *tailscale.LocalClient
45 anyForUser string
46 }
47
48 func (ta *tailscaleAuth) AllowedAccess(req *http.Request) Operation {
49
50
51
52
53 if ta.any {
54 return OpAll
55 }
56 if ta.anyForUser != "" {
57 res, err := ta.lc.WhoIs(req.Context(), req.RemoteAddr)
58 if err != nil {
59 if !errors.Is(err, context.Canceled) {
60 log.Printf("tailscale: WhoIs(%q) = %v", req.RemoteAddr, err)
61 }
62 return 0
63 }
64 if res.UserProfile.LoginName == ta.anyForUser {
65 return OpAll
66 }
67 log.Printf("access denied to Tailscale user %q; only %q is allowed", res.UserProfile.LoginName, ta.anyForUser)
68 return 0
69 }
70 return 0
71 }
72
73 func (*tailscaleAuth) AddAuthHeader(req *http.Request) {
74
75 }