Home Download Docs Code Community
     1	/*
     2	Copyright 2022 The Perkeep Authors
     3	
     4	Licensed under the Apache License, Version 2.0 (the "License");
     5	you may not use this file except in compliance with the License.
     6	You may obtain a copy of the License at
     7	
     8	     http://www.apache.org/licenses/LICENSE-2.0
     9	
    10	Unless required by applicable law or agreed to in writing, software
    11	distributed under the License is distributed on an "AS IS" BASIS,
    12	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13	See the License for the specific language governing permissions and
    14	limitations under the License.
    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		// TODO(bradfitz): use grants: https://tailscale.com/blog/acl-grants
    38		return nil, errors.New("unknown tailscale auth mode")
    39	}
    40	
    41	type tailscaleAuth struct {
    42		any bool // whether all access is permitted to anybody in the tailnet
    43	
    44		lc         *tailscale.LocalClient
    45		anyForUser string // if non-empty, the user for whom any access is permitted
    46	}
    47	
    48	func (ta *tailscaleAuth) AllowedAccess(req *http.Request) Operation {
    49		// AddAuthHeader inserts in req the credentials needed
    50		// for a client to authenticate.
    51		// TODO: eventially use req.RemoteAddr to talk to Tailscale LocalAPI WhoIs method
    52		// and check caps.
    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		// Nothing
    75	}
Website layout inspired by memcached.
Content by the authors.