fix tags not resolving to username if email is present (#2309)

* ensure valid tags is populated on user gets too

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* ensure forced tags are added

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* remove unused envvar in test

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* debug log auth/unauth tags in policy man

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* defer shutdown in tags test

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* add tag test with groups

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* add email, display name, picture to create user

Updates #2166

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* add ability to set display and email to cli

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* add email to test users in integration

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* fix issue where tags were only assigned to email, not username

Fixes #2300
Fixes #2307

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* expand principles to correct login name

and if fix an issue where nodeip principles might not expand to all
relevant IPs instead of taking the first in a prefix.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* fix ssh unit test

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* update cli and oauth tests for users with email

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* index by test email

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

* fix last test

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>

---------

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2024-12-19 13:10:10 +01:00 committed by GitHub
parent af4508b9dc
commit 770f3dcb93
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 409 additions and 230 deletions

View file

@ -119,8 +119,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns2 + ns1
"user1@test.no": 3, // ns1 + ns2
"user2@test.no": 3, // ns2 + ns1
},
},
// Test that when we have two users, which cannot see
@ -145,8 +145,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 1,
"user2": 1,
"user1@test.no": 1,
"user2@test.no": 1,
},
},
// Test that when we have two users, with ACLs and they
@ -181,8 +181,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 3,
"user2": 3,
"user1@test.no": 3,
"user2@test.no": 3,
},
},
// Test that when we have two users, that are isolated,
@ -213,8 +213,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns1 + ns2 (return path)
"user1@test.no": 3, // ns1 + ns2
"user2@test.no": 3, // ns1 + ns2 (return path)
},
},
"very-large-destination-prefix-1372": {
@ -241,8 +241,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns1 + ns2 (return path)
"user1@test.no": 3, // ns1 + ns2
"user2@test.no": 3, // ns1 + ns2 (return path)
},
},
"ipv6-acls-1470": {
@ -259,8 +259,8 @@ func TestACLHostsInNetMapTable(t *testing.T) {
},
},
}, want: map[string]int{
"user1": 3, // ns1 + ns2
"user2": 3, // ns2 + ns1
"user1@test.no": 3, // ns1 + ns2
"user2@test.no": 3, // ns2 + ns1
},
},
}
@ -282,7 +282,7 @@ func TestACLHostsInNetMapTable(t *testing.T) {
allClients, err := scenario.ListTailscaleClients()
require.NoError(t, err)
err = scenario.WaitForTailscaleSyncWithPeerCount(testCase.want["user1"])
err = scenario.WaitForTailscaleSyncWithPeerCount(testCase.want["user1@test.no"])
require.NoError(t, err)
for _, client := range allClients {

View file

@ -130,8 +130,9 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
want := []v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
{
Id: 2,
@ -141,8 +142,9 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
ProviderId: oidcConfig.Issuer + "/user1",
},
{
Id: 3,
Name: "user2",
Id: 3,
Name: "user2",
Email: "user2@test.no",
},
{
Id: 4,
@ -260,8 +262,9 @@ func TestOIDC024UserCreation(t *testing.T) {
want: func(iss string) []v1.User {
return []v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
{
Id: 2,
@ -271,8 +274,9 @@ func TestOIDC024UserCreation(t *testing.T) {
ProviderId: iss + "/user1",
},
{
Id: 3,
Name: "user2",
Id: 3,
Name: "user2",
Email: "user2@test.no",
},
{
Id: 4,
@ -295,8 +299,9 @@ func TestOIDC024UserCreation(t *testing.T) {
want: func(iss string) []v1.User {
return []v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
{
Id: 2,
@ -305,8 +310,9 @@ func TestOIDC024UserCreation(t *testing.T) {
ProviderId: iss + "/user1",
},
{
Id: 3,
Name: "user2",
Id: 3,
Name: "user2",
Email: "user2@test.no",
},
{
Id: 4,
@ -357,8 +363,9 @@ func TestOIDC024UserCreation(t *testing.T) {
want: func(iss string) []v1.User {
return []v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
{
Id: 2,
@ -367,8 +374,9 @@ func TestOIDC024UserCreation(t *testing.T) {
ProviderId: iss + "/user1",
},
{
Id: 3,
Name: "user2",
Id: 3,
Name: "user2",
Email: "user2@test.no",
},
{
Id: 4,
@ -421,8 +429,9 @@ func TestOIDC024UserCreation(t *testing.T) {
want: func(iss string) []v1.User {
return []v1.User{
{
Id: 1,
Name: "user1.headscale.net",
Id: 1,
Name: "user1.headscale.net",
Email: "user1.headscale.net@test.no",
},
{
Id: 2,
@ -431,8 +440,9 @@ func TestOIDC024UserCreation(t *testing.T) {
ProviderId: iss + "/user1",
},
{
Id: 3,
Name: "user2.headscale.net",
Id: 3,
Name: "user2.headscale.net",
Email: "user2.headscale.net@test.no",
},
{
Id: 4,

View file

@ -135,8 +135,9 @@ func TestUserCommand(t *testing.T) {
slices.SortFunc(listByUsername, sortWithID)
want := []*v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
}
@ -161,8 +162,9 @@ func TestUserCommand(t *testing.T) {
slices.SortFunc(listByID, sortWithID)
want = []*v1.User{
{
Id: 1,
Name: "user1",
Id: 1,
Name: "user1",
Email: "user1@test.no",
},
}
@ -199,8 +201,9 @@ func TestUserCommand(t *testing.T) {
slices.SortFunc(listAfterIDDelete, sortWithID)
want = []*v1.User{
{
Id: 2,
Name: "newname",
Id: 2,
Name: "newname",
Email: "user2@test.no",
},
}
@ -930,7 +933,23 @@ func TestNodeAdvertiseTagCommand(t *testing.T) {
wantTag: false,
},
{
name: "with-policy",
name: "with-policy-email",
policy: &policy.ACLPolicy{
ACLs: []policy.ACL{
{
Action: "accept",
Sources: []string{"*"},
Destinations: []string{"*:*"},
},
},
TagOwners: map[string][]string{
"tag:test": {"user1@test.no"},
},
},
wantTag: true,
},
{
name: "with-policy-username",
policy: &policy.ACLPolicy{
ACLs: []policy.ACL{
{
@ -945,13 +964,32 @@ func TestNodeAdvertiseTagCommand(t *testing.T) {
},
wantTag: true,
},
{
name: "with-policy-groups",
policy: &policy.ACLPolicy{
Groups: policy.Groups{
"group:admins": []string{"user1"},
},
ACLs: []policy.ACL{
{
Action: "accept",
Sources: []string{"*"},
Destinations: []string{"*:*"},
},
},
TagOwners: map[string][]string{
"tag:test": {"group:admins"},
},
},
wantTag: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scenario, err := NewScenario(dockertestMaxWait())
assertNoErr(t, err)
// defer scenario.ShutdownAssertNoPanics(t)
defer scenario.ShutdownAssertNoPanics(t)
spec := map[string]int{
"user1": 1,

View file

@ -702,7 +702,7 @@ func (t *HeadscaleInContainer) WaitForRunning() error {
func (t *HeadscaleInContainer) CreateUser(
user string,
) error {
command := []string{"headscale", "users", "create", user}
command := []string{"headscale", "users", "create", user, fmt.Sprintf("--email=%s@test.no", user)}
_, _, err := dockertestutil.ExecuteCommand(
t.container,

View file

@ -69,9 +69,6 @@ func sshScenario(t *testing.T, policy *policy.ACLPolicy, clientsPerUser int) *Sc
},
hsic.WithACLPolicy(policy),
hsic.WithTestName("ssh"),
hsic.WithConfigEnv(map[string]string{
"HEADSCALE_EXPERIMENTAL_FEATURE_SSH": "1",
}),
)
assertNoErr(t, err)