mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-22 18:18:00 +00:00
integration: support auth keys without user
Add AuthKeyOptions to create auth keys owned by tags only.
This commit is contained in:
parent
3b4b9a4436
commit
740d2b5a2c
3 changed files with 70 additions and 53 deletions
|
|
@ -8,6 +8,7 @@ import (
|
|||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/routes"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/ory/dockertest/v3"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
|
@ -25,6 +26,7 @@ type ControlServer interface {
|
|||
CreateUser(user string) (*v1.User, error)
|
||||
CreateAuthKey(user uint64, reusable bool, ephemeral bool) (*v1.PreAuthKey, error)
|
||||
CreateAuthKeyWithTags(user uint64, reusable bool, ephemeral bool, tags []string) (*v1.PreAuthKey, error)
|
||||
CreateAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error)
|
||||
DeleteAuthKey(user uint64, key string) error
|
||||
ListNodes(users ...string) ([]*v1.Node, error)
|
||||
DeleteNode(nodeID uint64) error
|
||||
|
|
|
|||
|
|
@ -1067,33 +1067,52 @@ func (t *HeadscaleInContainer) CreateUser(
|
|||
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 uint64,
|
||||
reusable bool,
|
||||
ephemeral bool,
|
||||
) (*v1.PreAuthKey, error) {
|
||||
// AuthKeyOptions defines options for creating an auth key.
|
||||
type AuthKeyOptions struct {
|
||||
// User is the user ID that owns the auth key. If nil and Tags are specified,
|
||||
// the auth key is owned by the tags only (tags-as-identity model).
|
||||
User *uint64
|
||||
// Reusable indicates if the key can be used multiple times
|
||||
Reusable bool
|
||||
// Ephemeral indicates if nodes registered with this key should be ephemeral
|
||||
Ephemeral bool
|
||||
// Tags are the tags to assign to the auth key
|
||||
Tags []string
|
||||
}
|
||||
|
||||
// CreateAuthKeyWithOptions creates a new "authorisation key" with the specified options.
|
||||
// This supports both user-owned and tags-only auth keys.
|
||||
func (t *HeadscaleInContainer) CreateAuthKeyWithOptions(opts AuthKeyOptions) (*v1.PreAuthKey, error) {
|
||||
command := []string{
|
||||
"headscale",
|
||||
"--user",
|
||||
strconv.FormatUint(user, 10),
|
||||
}
|
||||
|
||||
// Only add --user flag if User is specified
|
||||
if opts.User != nil {
|
||||
command = append(command, "--user", strconv.FormatUint(*opts.User, 10))
|
||||
}
|
||||
|
||||
command = append(command,
|
||||
"preauthkeys",
|
||||
"create",
|
||||
"--expiration",
|
||||
"24h",
|
||||
"--output",
|
||||
"json",
|
||||
}
|
||||
)
|
||||
|
||||
if reusable {
|
||||
if opts.Reusable {
|
||||
command = append(command, "--reusable")
|
||||
}
|
||||
|
||||
if ephemeral {
|
||||
if opts.Ephemeral {
|
||||
command = append(command, "--ephemeral")
|
||||
}
|
||||
|
||||
if len(opts.Tags) > 0 {
|
||||
command = append(command, "--tags", strings.Join(opts.Tags, ","))
|
||||
}
|
||||
|
||||
result, _, err := dockertestutil.ExecuteCommand(
|
||||
t.container,
|
||||
command,
|
||||
|
|
@ -1104,6 +1123,7 @@ func (t *HeadscaleInContainer) CreateAuthKey(
|
|||
}
|
||||
|
||||
var preAuthKey v1.PreAuthKey
|
||||
|
||||
err = json.Unmarshal([]byte(result), &preAuthKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal auth key: %w", err)
|
||||
|
|
@ -1112,6 +1132,20 @@ func (t *HeadscaleInContainer) CreateAuthKey(
|
|||
return &preAuthKey, 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 uint64,
|
||||
reusable bool,
|
||||
ephemeral bool,
|
||||
) (*v1.PreAuthKey, error) {
|
||||
return t.CreateAuthKeyWithOptions(AuthKeyOptions{
|
||||
User: &user,
|
||||
Reusable: reusable,
|
||||
Ephemeral: ephemeral,
|
||||
})
|
||||
}
|
||||
|
||||
// CreateAuthKeyWithTags creates a new "authorisation key" for a User with the specified tags.
|
||||
// This is used to create tagged PreAuthKeys for testing the tags-as-identity model.
|
||||
func (t *HeadscaleInContainer) CreateAuthKeyWithTags(
|
||||
|
|
@ -1120,47 +1154,12 @@ func (t *HeadscaleInContainer) CreateAuthKeyWithTags(
|
|||
ephemeral bool,
|
||||
tags []string,
|
||||
) (*v1.PreAuthKey, error) {
|
||||
command := []string{
|
||||
"headscale",
|
||||
"--user",
|
||||
strconv.FormatUint(user, 10),
|
||||
"preauthkeys",
|
||||
"create",
|
||||
"--expiration",
|
||||
"24h",
|
||||
"--output",
|
||||
"json",
|
||||
}
|
||||
|
||||
if reusable {
|
||||
command = append(command, "--reusable")
|
||||
}
|
||||
|
||||
if ephemeral {
|
||||
command = append(command, "--ephemeral")
|
||||
}
|
||||
|
||||
if len(tags) > 0 {
|
||||
command = append(command, "--tags", strings.Join(tags, ","))
|
||||
}
|
||||
|
||||
result, _, err := dockertestutil.ExecuteCommand(
|
||||
t.container,
|
||||
command,
|
||||
[]string{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute create auth key with tags command: %w", err)
|
||||
}
|
||||
|
||||
var preAuthKey v1.PreAuthKey
|
||||
|
||||
err = json.Unmarshal([]byte(result), &preAuthKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal auth key: %w", err)
|
||||
}
|
||||
|
||||
return &preAuthKey, nil
|
||||
return t.CreateAuthKeyWithOptions(AuthKeyOptions{
|
||||
User: &user,
|
||||
Reusable: reusable,
|
||||
Ephemeral: ephemeral,
|
||||
Tags: tags,
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteAuthKey deletes an "authorisation key" for a User.
|
||||
|
|
|
|||
|
|
@ -478,6 +478,22 @@ func (s *Scenario) CreatePreAuthKey(
|
|||
return nil, fmt.Errorf("failed to create user: %w", errNoHeadscaleAvailable)
|
||||
}
|
||||
|
||||
// CreatePreAuthKeyWithOptions creates a "pre authorised key" with the specified options
|
||||
// to be created in the Headscale instance on behalf of the Scenario.
|
||||
func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error) {
|
||||
headscale, err := s.Headscale()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create preauth key with options: %w", errNoHeadscaleAvailable)
|
||||
}
|
||||
|
||||
key, err := headscale.CreateAuthKeyWithOptions(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create preauth key with options: %w", err)
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// CreatePreAuthKeyWithTags creates a "pre authorised key" with the specified tags
|
||||
// to be created in the Headscale instance on behalf of the Scenario.
|
||||
func (s *Scenario) CreatePreAuthKeyWithTags(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue