mirror of
https://github.com/tailscale/tailscale.git
synced 2026-11-09 02:53:09 -05:00
This makes the syspolicy cli use the caller's user scope instead of the generic user scope. In tailscale/tailscale#21701, we made the LocalAPI policy endpoint resolve unscoped policy requests to the connected user's policy. However, the cli serialized setting.DefaultScope() as /policy/User, which selected the general user policy and not the User(SID) policy used by IPN watchers. This was tested by changing the AlwaysOn policy and verifying that the User(SID) policy was reloaded and the gui's IPN policy change callbacks fired. Updates tailscale/corp#41463 Signed-off-by: kari <kari@tailscale.com>
157 lines
4.1 KiB
Go
157 lines
4.1 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
//go:build go1.19
|
|
|
|
package local
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"tailscale.com/tstest/deptest"
|
|
"tailscale.com/tstest/nettest"
|
|
"tailscale.com/types/key"
|
|
"tailscale.com/util/httpm"
|
|
)
|
|
|
|
func TestGetServeConfigFromJSON(t *testing.T) {
|
|
sc, err := getServeConfigFromJSON([]byte("null"))
|
|
if sc != nil {
|
|
t.Errorf("want nil for null")
|
|
}
|
|
if err != nil {
|
|
t.Errorf("reading null: %v", err)
|
|
}
|
|
|
|
sc, err = getServeConfigFromJSON([]byte(`{"TCP":{}}`))
|
|
if err != nil {
|
|
t.Errorf("reading object: %v", err)
|
|
} else if sc == nil {
|
|
t.Errorf("want non-nil for object")
|
|
} else if sc.TCP == nil {
|
|
t.Errorf("want non-nil TCP for object")
|
|
}
|
|
}
|
|
|
|
func TestWhoIsPeerNotFound(t *testing.T) {
|
|
nw := nettest.GetNetwork(t)
|
|
ts := nettest.NewHTTPServer(nw, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(404)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
lc := &Client{
|
|
Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return nw.Dial(ctx, network, ts.Listener.Addr().String())
|
|
},
|
|
}
|
|
var k key.NodePublic
|
|
if err := k.UnmarshalText([]byte("nodekey:5c8f86d5fc70d924e55f02446165a5dae8f822994ad26bcf4b08fd841f9bf261")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
res, err := lc.WhoIsNodeKey(context.Background(), k)
|
|
if err != ErrPeerNotFound {
|
|
t.Errorf("got (%v, %v), want ErrPeerNotFound", res, err)
|
|
}
|
|
res, err = lc.WhoIs(context.Background(), "1.2.3.4:5678")
|
|
if err != ErrPeerNotFound {
|
|
t.Errorf("got (%v, %v), want ErrPeerNotFound", res, err)
|
|
}
|
|
}
|
|
|
|
func TestUserDialSelf(t *testing.T) {
|
|
// Start a real TCP listener that the client should dial directly
|
|
// when the server tells it to dial-self.
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer ln.Close()
|
|
go func() {
|
|
for {
|
|
c, err := ln.Accept()
|
|
if err != nil {
|
|
return
|
|
}
|
|
c.Write([]byte("hello"))
|
|
c.Close()
|
|
}
|
|
}()
|
|
targetAddr := ln.Addr().(*net.TCPAddr)
|
|
|
|
// Mock LocalAPI server that returns Dial-Self response.
|
|
nw := nettest.GetNetwork(t)
|
|
ts := nettest.NewHTTPServer(nw, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Dial-Self", "true")
|
|
w.Header().Set("Dial-Addr", targetAddr.String())
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer ts.Close()
|
|
|
|
lc := &Client{
|
|
Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return nw.Dial(ctx, network, ts.Listener.Addr().String())
|
|
},
|
|
}
|
|
|
|
conn, err := lc.UserDial(context.Background(), "tcp", targetAddr.IP.String(), uint16(targetAddr.Port))
|
|
if err != nil {
|
|
t.Fatalf("UserDial: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
buf := make([]byte, 5)
|
|
n, err := conn.Read(buf)
|
|
if err != nil {
|
|
t.Fatalf("Read: %v", err)
|
|
}
|
|
if got := string(buf[:n]); got != "hello" {
|
|
t.Errorf("got %q, want %q", got, "hello")
|
|
}
|
|
}
|
|
|
|
func TestEffectivePolicyForCurrentUserUsesUnscopedEndpoint(t *testing.T) {
|
|
nw := nettest.GetNetwork(t)
|
|
|
|
var gotMethod, gotPath string
|
|
ts := nettest.NewHTTPServer(nw, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotMethod = r.Method
|
|
gotPath = r.URL.Path
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write([]byte(`{}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
lc := &Client{
|
|
Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
return nw.Dial(ctx, network, ts.Listener.Addr().String())
|
|
},
|
|
}
|
|
|
|
if _, err := lc.ReloadEffectivePolicyForCurrentUser(context.Background()); err != nil {
|
|
t.Fatalf("ReloadEffectivePolicyForCurrentUser: %v", err)
|
|
}
|
|
|
|
if gotMethod != httpm.POST {
|
|
t.Errorf("method = %q, want %q", gotMethod, httpm.POST)
|
|
}
|
|
if gotPath != "/localapi/v0/policy/" {
|
|
t.Errorf("path = %q, want %q", gotPath, "/localapi/v0/policy/")
|
|
}
|
|
}
|
|
|
|
func TestDeps(t *testing.T) {
|
|
deptest.DepChecker{
|
|
BadDeps: map[string]string{
|
|
// Make sure we don't again accidentally bring in a dependency on
|
|
// drive or its transitive dependencies
|
|
"testing": "do not use testing package in production code",
|
|
"tailscale.com/drive/driveimpl": "https://github.com/tailscale/tailscale/pull/10631",
|
|
"github.com/studio-b12/gowebdav": "https://github.com/tailscale/tailscale/pull/10631",
|
|
},
|
|
}.Check(t)
|
|
}
|