types/authkey: include user object in response (#2542)
* types/authkey: include user object, not string Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * make preauthkeys use id Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * changelog Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * integration: wire up user id for auth keys Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
f1206328dc
commit
8f9fbf16f1
23 changed files with 454 additions and 779 deletions
|
@ -3,9 +3,12 @@ package integration
|
|||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"slices"
|
||||
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/samber/lo"
|
||||
|
@ -84,8 +87,11 @@ func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) {
|
|||
time.Sleep(5 * time.Minute)
|
||||
}
|
||||
|
||||
userMap, err := headscale.MapUsers()
|
||||
assertNoErr(t, err)
|
||||
|
||||
for _, userName := range spec.Users {
|
||||
key, err := scenario.CreatePreAuthKey(userName, true, false)
|
||||
key, err := scenario.CreatePreAuthKey(userMap[userName].GetId(), true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create pre-auth key for user %s: %s", userName, err)
|
||||
}
|
||||
|
@ -121,16 +127,7 @@ func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
found := false
|
||||
for _, oldIP := range clientIPs[client] {
|
||||
if ip == oldIP {
|
||||
found = true
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
if !slices.Contains(clientIPs[client], ip) {
|
||||
t.Fatalf(
|
||||
"IPs changed for client %s. Used to be %v now %v",
|
||||
client.Hostname(),
|
||||
|
@ -195,8 +192,11 @@ func TestAuthKeyLogoutAndReloginNewUser(t *testing.T) {
|
|||
|
||||
t.Logf("all clients logged out")
|
||||
|
||||
userMap, err := headscale.MapUsers()
|
||||
assertNoErr(t, err)
|
||||
|
||||
// Create a new authkey for user1, to be used for all clients
|
||||
key, err := scenario.CreatePreAuthKey("user1", true, false)
|
||||
key, err := scenario.CreatePreAuthKey(userMap["user1"].GetId(), true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create pre-auth key for user1: %s", err)
|
||||
}
|
||||
|
@ -300,8 +300,11 @@ func TestAuthKeyLogoutAndReloginSameUserExpiredKey(t *testing.T) {
|
|||
time.Sleep(5 * time.Minute)
|
||||
}
|
||||
|
||||
userMap, err := headscale.MapUsers()
|
||||
assertNoErr(t, err)
|
||||
|
||||
for _, userName := range spec.Users {
|
||||
key, err := scenario.CreatePreAuthKey(userName, true, false)
|
||||
key, err := scenario.CreatePreAuthKey(userMap[userName].GetId(), true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create pre-auth key for user %s: %s", userName, err)
|
||||
}
|
||||
|
@ -312,7 +315,7 @@ func TestAuthKeyLogoutAndReloginSameUserExpiredKey(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
userName,
|
||||
strconv.FormatUint(userMap[userName].GetId(), 10),
|
||||
"expire",
|
||||
key.Key,
|
||||
})
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"cmp"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -271,7 +272,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"create",
|
||||
"--reusable",
|
||||
"--expiration",
|
||||
|
@ -297,7 +298,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"list",
|
||||
"--output",
|
||||
"json",
|
||||
|
@ -311,8 +312,8 @@ func TestPreAuthKeyCommand(t *testing.T) {
|
|||
|
||||
assert.Equal(
|
||||
t,
|
||||
[]string{keys[0].GetId(), keys[1].GetId(), keys[2].GetId()},
|
||||
[]string{
|
||||
[]uint64{keys[0].GetId(), keys[1].GetId(), keys[2].GetId()},
|
||||
[]uint64{
|
||||
listedPreAuthKeys[1].GetId(),
|
||||
listedPreAuthKeys[2].GetId(),
|
||||
listedPreAuthKeys[3].GetId(),
|
||||
|
@ -354,7 +355,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"expire",
|
||||
listedPreAuthKeys[1].GetKey(),
|
||||
},
|
||||
|
@ -368,7 +369,7 @@ func TestPreAuthKeyCommand(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"list",
|
||||
"--output",
|
||||
"json",
|
||||
|
@ -408,7 +409,7 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"create",
|
||||
"--reusable",
|
||||
"--output",
|
||||
|
@ -425,7 +426,7 @@ func TestPreAuthKeyCommandWithoutExpiry(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"list",
|
||||
"--output",
|
||||
"json",
|
||||
|
@ -470,7 +471,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"create",
|
||||
"--reusable=true",
|
||||
"--output",
|
||||
|
@ -487,7 +488,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"create",
|
||||
"--ephemeral=true",
|
||||
"--output",
|
||||
|
@ -507,7 +508,7 @@ func TestPreAuthKeyCommandReusableEphemeral(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user,
|
||||
"1",
|
||||
"list",
|
||||
"--output",
|
||||
"json",
|
||||
|
@ -547,7 +548,7 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
|
|||
headscale, err := scenario.Headscale()
|
||||
assertNoErr(t, err)
|
||||
|
||||
err = headscale.CreateUser(user2)
|
||||
u2, err := headscale.CreateUser(user2)
|
||||
assertNoErr(t, err)
|
||||
|
||||
var user2Key v1.PreAuthKey
|
||||
|
@ -558,7 +559,7 @@ func TestPreAuthKeyCorrectUserLoggedInCommand(t *testing.T) {
|
|||
"headscale",
|
||||
"preauthkeys",
|
||||
"--user",
|
||||
user2,
|
||||
strconv.FormatUint(u2.GetId(), 10),
|
||||
"create",
|
||||
"--reusable",
|
||||
"--expiration",
|
||||
|
|
|
@ -18,10 +18,11 @@ type ControlServer interface {
|
|||
GetHealthEndpoint() string
|
||||
GetEndpoint() string
|
||||
WaitForRunning() error
|
||||
CreateUser(user string) error
|
||||
CreateAuthKey(user string, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
|
||||
CreateUser(user string) (*v1.User, error)
|
||||
CreateAuthKey(user uint64, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
|
||||
ListNodes(users ...string) ([]*v1.Node, error)
|
||||
ListUsers() ([]*v1.User, error)
|
||||
MapUsers() (map[string]*v1.User, error)
|
||||
ApproveRoutes(uint64, []netip.Prefix) (*v1.Node, error)
|
||||
GetCert() []byte
|
||||
GetHostname() string
|
||||
|
|
|
@ -133,7 +133,7 @@ func testEphemeralWithOptions(t *testing.T, opts ...hsic.Option) {
|
|||
assertNoErrHeadscaleEnv(t, err)
|
||||
|
||||
for _, userName := range spec.Users {
|
||||
err = scenario.CreateUser(userName)
|
||||
user, err := scenario.CreateUser(userName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create user %s: %s", userName, err)
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func testEphemeralWithOptions(t *testing.T, opts ...hsic.Option) {
|
|||
t.Fatalf("failed to create tailscale nodes in user %s: %s", userName, err)
|
||||
}
|
||||
|
||||
key, err := scenario.CreatePreAuthKey(userName, true, true)
|
||||
key, err := scenario.CreatePreAuthKey(user.GetId(), true, true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create pre-auth key for user %s: %s", userName, err)
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ func TestEphemeral2006DeletedTooQuickly(t *testing.T) {
|
|||
assertNoErrHeadscaleEnv(t, err)
|
||||
|
||||
for _, userName := range spec.Users {
|
||||
err = scenario.CreateUser(userName)
|
||||
user, err := scenario.CreateUser(userName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create user %s: %s", userName, err)
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ func TestEphemeral2006DeletedTooQuickly(t *testing.T) {
|
|||
t.Fatalf("failed to create tailscale nodes in user %s: %s", userName, err)
|
||||
}
|
||||
|
||||
key, err := scenario.CreatePreAuthKey(userName, true, true)
|
||||
key, err := scenario.CreatePreAuthKey(user.GetId(), true, true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create pre-auth key for user %s: %s", userName, err)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/ory/dockertest/v3/docker"
|
||||
"gopkg.in/yaml.v3"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/util/mak"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -703,32 +704,38 @@ func (t *HeadscaleInContainer) WaitForRunning() error {
|
|||
// CreateUser adds a new user to the Headscale instance.
|
||||
func (t *HeadscaleInContainer) CreateUser(
|
||||
user string,
|
||||
) error {
|
||||
command := []string{"headscale", "users", "create", user, fmt.Sprintf("--email=%s@test.no", user)}
|
||||
) (*v1.User, error) {
|
||||
command := []string{"headscale", "users", "create", user, fmt.Sprintf("--email=%s@test.no", user), "--output", "json"}
|
||||
|
||||
_, _, err := dockertestutil.ExecuteCommand(
|
||||
result, _, err := dockertestutil.ExecuteCommand(
|
||||
t.container,
|
||||
command,
|
||||
[]string{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
var u v1.User
|
||||
err = json.Unmarshal([]byte(result), &u)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal user: %w", err)
|
||||
}
|
||||
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
// CreateAuthKey creates a new "authorisation key" for a User that can be used
|
||||
// to authorise a TailscaleClient with the Headscale instance.
|
||||
func (t *HeadscaleInContainer) CreateAuthKey(
|
||||
user string,
|
||||
user uint64,
|
||||
reusable bool,
|
||||
ephemeral bool,
|
||||
) (*v1.PreAuthKey, error) {
|
||||
command := []string{
|
||||
"headscale",
|
||||
"--user",
|
||||
user,
|
||||
strconv.FormatUint(user, 10),
|
||||
"preauthkeys",
|
||||
"create",
|
||||
"--expiration",
|
||||
|
@ -834,6 +841,22 @@ func (t *HeadscaleInContainer) ListUsers() ([]*v1.User, error) {
|
|||
return users, nil
|
||||
}
|
||||
|
||||
// MapUsers returns a map of users from Headscale. It is keyed by the
|
||||
// user name.
|
||||
func (t *HeadscaleInContainer) MapUsers() (map[string]*v1.User, error) {
|
||||
users, err := t.ListUsers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userMap map[string]*v1.User
|
||||
for _, user := range users {
|
||||
mak.Set(&userMap, user.Name, user)
|
||||
}
|
||||
|
||||
return userMap, nil
|
||||
}
|
||||
|
||||
func (h *HeadscaleInContainer) SetPolicy(pol *policyv1.ACLPolicy) error {
|
||||
err := h.writePolicy(pol)
|
||||
if err != nil {
|
||||
|
|
|
@ -1680,7 +1680,10 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
|
||||
scenario.runHeadscaleRegister("user1", body)
|
||||
} else {
|
||||
pak, err := scenario.CreatePreAuthKey("user1", false, false)
|
||||
userMap, err := headscale.MapUsers()
|
||||
assertNoErr(t, err)
|
||||
|
||||
pak, err := scenario.CreatePreAuthKey(userMap["user1"].GetId(), false, false)
|
||||
assertNoErr(t, err)
|
||||
|
||||
err = routerUsernet1.Login(headscale.GetEndpoint(), pak.Key)
|
||||
|
|
|
@ -436,7 +436,7 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
|
|||
// CreatePreAuthKey creates a "pre authentorised key" to be created in the
|
||||
// Headscale instance on behalf of the Scenario.
|
||||
func (s *Scenario) CreatePreAuthKey(
|
||||
user string,
|
||||
user uint64,
|
||||
reusable bool,
|
||||
ephemeral bool,
|
||||
) (*v1.PreAuthKey, error) {
|
||||
|
@ -454,21 +454,21 @@ func (s *Scenario) CreatePreAuthKey(
|
|||
|
||||
// CreateUser creates a User to be created in the
|
||||
// Headscale instance on behalf of the Scenario.
|
||||
func (s *Scenario) CreateUser(user string) error {
|
||||
func (s *Scenario) CreateUser(user string) (*v1.User, error) {
|
||||
if headscale, err := s.Headscale(); err == nil {
|
||||
err := headscale.CreateUser(user)
|
||||
u, err := headscale.CreateUser(user)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create user: %w", err)
|
||||
return nil, fmt.Errorf("failed to create user: %w", err)
|
||||
}
|
||||
|
||||
s.users[user] = &User{
|
||||
Clients: make(map[string]TailscaleClient),
|
||||
}
|
||||
|
||||
return nil
|
||||
return u, nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
|
||||
return nil, fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
|
||||
}
|
||||
|
||||
/// Client related stuff
|
||||
|
@ -703,7 +703,7 @@ func (s *Scenario) createHeadscaleEnv(
|
|||
|
||||
sort.Strings(s.spec.Users)
|
||||
for _, user := range s.spec.Users {
|
||||
err = s.CreateUser(user)
|
||||
u, err := s.CreateUser(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ func (s *Scenario) createHeadscaleEnv(
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
key, err := s.CreatePreAuthKey(user, true, false)
|
||||
key, err := s.CreatePreAuthKey(u.GetId(), true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ func TestHeadscale(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("create-user", func(t *testing.T) {
|
||||
err := scenario.CreateUser(user)
|
||||
_, err := scenario.CreateUser(user)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create user: %s", err)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ func TestHeadscale(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("create-auth-key", func(t *testing.T) {
|
||||
_, err := scenario.CreatePreAuthKey(user, true, false)
|
||||
_, err := scenario.CreatePreAuthKey(1, true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create preauthkey: %s", err)
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("create-user", func(t *testing.T) {
|
||||
err := scenario.CreateUser(user)
|
||||
_, err := scenario.CreateUser(user)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create user: %s", err)
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("join-headscale", func(t *testing.T) {
|
||||
key, err := scenario.CreatePreAuthKey(user, true, false)
|
||||
key, err := scenario.CreatePreAuthKey(1, true, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create preauthkey: %s", err)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue