Tobias Lütke 3 days ago committed by GitHub
commit 8da3ac31cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -25,6 +25,7 @@ import (
"net/url"
"os"
"path"
"regexp"
"slices"
"strconv"
"strings"
@ -82,6 +83,17 @@ var ErrProxyToTailscaledSocket = errors.New("cannot proxy to tailscaled socket")
var serveHTTPContextKey ctxkey.Key[*serveHTTPContext]
// handleInvalidCharsRe matches any character that is not a word character, hyphen, underscore, or dot.
var handleInvalidCharsRe = regexp.MustCompile(`[^\w\-_.]+`)
// handelizeLogin converts a login name (e.g. "John.Doe@example.com") into a
// lowercase handle with only word characters, hyphens, underscores, and dots.
// It takes the local part before '@' and replaces invalid characters with '-'.
func handelizeLogin(login string) string {
localPart := strings.Split(login, "@")[0]
return handleInvalidCharsRe.ReplaceAllString(strings.ToLower(localPart), "-")
}
type serveHTTPContext struct {
SrcAddr netip.AddrPort
ForVIPService tailcfg.ServiceName // "" means local
@ -1021,6 +1033,7 @@ func (b *LocalBackend) addTailscaleIdentityHeaders(r *httputil.ProxyRequest) {
// Clear any incoming values squatting in the headers.
r.Out.Header.Del("Tailscale-User-Login")
r.Out.Header.Del("Tailscale-User-Name")
r.Out.Header.Del("Tailscale-User-Handle")
r.Out.Header.Del("Tailscale-User-Profile-Pic")
r.Out.Header.Del("Tailscale-Funnel-Request")
r.Out.Header.Del("Tailscale-Headers-Info")
@ -1044,6 +1057,7 @@ func (b *LocalBackend) addTailscaleIdentityHeaders(r *httputil.ProxyRequest) {
}
r.Out.Header.Set("Tailscale-User-Login", encTailscaleHeaderValue(user.LoginName))
r.Out.Header.Set("Tailscale-User-Name", encTailscaleHeaderValue(user.DisplayName))
r.Out.Header.Set("Tailscale-User-Handle", encTailscaleHeaderValue(handelizeLogin(user.LoginName)))
r.Out.Header.Set("Tailscale-User-Profile-Pic", user.ProfilePicURL)
r.Out.Header.Set("Tailscale-Headers-Info", "https://tailscale.com/s/serve-headers")
}

@ -751,6 +751,7 @@ func TestServeHTTPProxyHeaders(t *testing.T) {
{"X-Forwarded-For", "100.150.151.152"},
{"Tailscale-User-Login", "someone@example.com"},
{"Tailscale-User-Name", "Some One"},
{"Tailscale-User-Handle", "someone"},
{"Tailscale-User-Profile-Pic", "https://example.com/photo.jpg"},
{"Tailscale-Headers-Info", "https://tailscale.com/s/serve-headers"},
},
@ -763,6 +764,7 @@ func TestServeHTTPProxyHeaders(t *testing.T) {
{"X-Forwarded-For", "100.150.151.153"},
{"Tailscale-User-Login", ""},
{"Tailscale-User-Name", ""},
{"Tailscale-User-Handle", ""},
{"Tailscale-User-Profile-Pic", ""},
{"Tailscale-Headers-Info", ""},
},
@ -775,6 +777,7 @@ func TestServeHTTPProxyHeaders(t *testing.T) {
{"X-Forwarded-For", "100.160.161.162"},
{"Tailscale-User-Login", ""},
{"Tailscale-User-Name", ""},
{"Tailscale-User-Handle", ""},
{"Tailscale-User-Profile-Pic", ""},
{"Tailscale-Headers-Info", ""},
},
@ -806,6 +809,33 @@ func TestServeHTTPProxyHeaders(t *testing.T) {
}
}
func TestHandelizeLogin(t *testing.T) {
tests := []struct {
in string
want string
}{
{"someone@example.com", "someone"},
{"john.doe@example.com", "john.doe"},
{"John.Doe@example.com", "john.doe"},
{"john-doe@example.com", "john-doe"},
{"john_doe@example.com", "john_doe"},
{"john123@example.com", "john123"},
{"john+doe@example.com", "john-doe"},
{"john!#$doe@example.com", "john-doe"},
{"john doe@example.com", "john-doe"},
{"jöhn@example.com", "j-hn"},
{"someone", "someone"},
{"@example.com", ""},
{"John.Doe-Test_123@example.com", "john.doe-test_123"},
}
for _, tt := range tests {
got := handelizeLogin(tt.in)
if got != tt.want {
t.Errorf("handelizeLogin(%q) = %q, want %q", tt.in, got, tt.want)
}
}
}
func TestServeHTTPProxyGrantHeader(t *testing.T) {
b := newTestBackend(t)
@ -891,6 +921,7 @@ func TestServeHTTPProxyGrantHeader(t *testing.T) {
{"X-Forwarded-For", "100.150.151.152"},
{"Tailscale-User-Login", "someone@example.com"},
{"Tailscale-User-Name", "Some One"},
{"Tailscale-User-Handle", "someone"},
{"Tailscale-User-Profile-Pic", "https://example.com/photo.jpg"},
{"Tailscale-Headers-Info", "https://tailscale.com/s/serve-headers"},
{"Tailscale-App-Capabilities", `{"example.com/cap/interesting":[{"role":"🐿"}]}`},
@ -904,6 +935,7 @@ func TestServeHTTPProxyGrantHeader(t *testing.T) {
{"X-Forwarded-For", "100.150.151.153"},
{"Tailscale-User-Login", ""},
{"Tailscale-User-Name", ""},
{"Tailscale-User-Handle", ""},
{"Tailscale-User-Profile-Pic", ""},
{"Tailscale-Headers-Info", ""},
{"Tailscale-App-Capabilities", `{"example.com/cap/boring":[{"role":"Viewer"}]}`},
@ -917,6 +949,7 @@ func TestServeHTTPProxyGrantHeader(t *testing.T) {
{"X-Forwarded-For", "100.160.161.162"},
{"Tailscale-User-Login", ""},
{"Tailscale-User-Name", ""},
{"Tailscale-User-Handle", ""},
{"Tailscale-User-Profile-Pic", ""},
{"Tailscale-Headers-Info", ""},
{"Tailscale-App-Capabilities", ""},

Loading…
Cancel
Save