tailscale/drive/magic/magic_test.go
Fernando Serboncini 02631749ba drive: add taildrive "magic" share with name-encoded ACLs
Reserves the share name "magic" for a share whose top-level directory
names encode their own ACL (e.g. "fserb+rhea"). Peers only see and can
descend into top-level dirs that name both the sharer and themselves.
Top-level dir creation/deletion via WebDAV is denied for remote peers;
the directory layout is sharer-local only.

New package drive/magic parses and matches the directory names. The
peerapi handler plumbs the peer's and the local node's tailnet logins
into a new drive.Authz value passed to ServeHTTPWithPerms. The CLI
recognizes the reserved name and validates the path is a directory.

Change-Id: If7b6ad9fdab46b99e7ac5a7c5417a57d61b44478
2026-04-27 10:12:52 -04:00

83 lines
2.4 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package magic
import (
"slices"
"testing"
)
func TestParseDirACL(t *testing.T) {
tests := []struct {
name string
want []string
wantErr bool
}{
{"fserb", []string{"fserb"}, false},
{"fserb+rhea", []string{"fserb", "rhea"}, false},
{"Fserb+RHEA", []string{"fserb", "rhea"}, false},
{"fserb+fserb", []string{"fserb"}, false},
{"fserb+rhea+joe", []string{"fserb", "rhea", "joe"}, false},
{"fserb@example.com+rhea", []string{"fserb@example.com", "rhea"}, false},
{"", nil, true},
{"+fserb", nil, true},
{"fserb+", nil, true},
{"fserb++rhea", nil, true},
{"fserb rhea", nil, true},
{"fserb!", nil, true},
{"@example.com", nil, true},
{"fserb@", nil, true},
{"fserb@@example.com", nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseDirACL(tt.name)
if (err != nil) != tt.wantErr {
t.Fatalf("err=%v, wantErr=%v", err, tt.wantErr)
}
if tt.wantErr {
return
}
if !slices.Equal(got.Users, tt.want) {
t.Errorf("Users=%v, want %v", got.Users, tt.want)
}
})
}
}
func TestMatches(t *testing.T) {
const sharer = "fserb@example.com"
tests := []struct {
name string
dir string
peerLogin string
want bool
}{
{"sharer matches own dir", "fserb", sharer, true},
{"sharer matches paired dir", "fserb+rhea", sharer, true},
{"peer matches paired dir (short)", "fserb+rhea", "rhea@example.com", true},
{"peer matches paired dir (email)", "fserb+rhea@example.com", "rhea@example.com", true},
{"peer mismatch full email", "fserb+rhea@other.com", "rhea@example.com", false},
{"peer not in dir", "fserb+rhea", "joe@example.com", false},
{"sharer-not-in-name invalidates dir for peer", "rhea+joe", "rhea@example.com", false},
{"sharer-not-in-name invalidates dir for sharer too", "rhea+joe", sharer, false},
{"empty peer login", "fserb", "", false},
{"three principal dir, peer ok", "fserb+rhea+joe", "joe@example.com", true},
{"case-insensitive peer", "fserb+rhea", "RHEA@example.com", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
acl, err := ParseDirACL(tt.dir)
if err != nil {
t.Fatalf("parse %q: %v", tt.dir, err)
}
got := acl.Matches(tt.peerLogin, sharer)
if got != tt.want {
t.Errorf("Matches(%q, %q)=%v, want %v", tt.peerLogin, sharer, got, tt.want)
}
})
}
}