client/tailscale: revert CreateKey API change, add Client.CreateKeyWithExpiry

The client/tailscale is a stable-ish API we try not to break. Revert
the Client.CreateKey method as it was and add a new
CreateKeyWithExpiry method to do the new thing. And document the
expiry field and enforce that the time.Duration can't be between in
range greater than 0 and less than a second.

Updates #7143
Updates #8124 (reverts it, effectively)

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2023-05-12 18:50:30 -07:00 committed by Brad Fitzpatrick
parent 678bb92bb8
commit 4664318be2
5 changed files with 20 additions and 13 deletions

View File

@ -68,15 +68,27 @@ func (c *Client) Keys(ctx context.Context) ([]string, error) {
}
// CreateKey creates a new key for the current user. Currently, only auth keys
// can be created. Returns the key itself, which cannot be retrieved again
// can be created. It returns the secret key itself, which cannot be retrieved again
// later, and the key metadata.
func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities, expiry time.Duration) (string, *Key, error) {
//
// To create a key with a specific expiry, use CreateKeyWithExpiry.
func (c *Client) CreateKey(ctx context.Context, caps KeyCapabilities) (keySecret string, keyMeta *Key, _ error) {
return c.CreateKeyWithExpiry(ctx, caps, 0)
}
// CreateKeyWithExpiry is like CreateKey, but allows specifying a expiration time.
//
// The time is truncated to a whole number of seconds. If zero, that means no expiration.
func (c *Client) CreateKeyWithExpiry(ctx context.Context, caps KeyCapabilities, expiry time.Duration) (keySecret string, keyMeta *Key, _ error) {
// convert expirySeconds to an int64 (seconds)
expirySeconds := int64(expiry.Seconds())
if expirySeconds < 0 {
return "", nil, fmt.Errorf("expiry must be positive")
}
if expirySeconds == 0 && expiry != 0 {
return "", nil, fmt.Errorf("non-zero expiry must be at least one second")
}
keyRequest := struct {
Capabilities KeyCapabilities `json:"capabilities"`

View File

@ -67,7 +67,7 @@ func main() {
},
}
authkey, _, err := tsClient.CreateKey(ctx, caps, 0)
authkey, _, err := tsClient.CreateKey(ctx, caps)
if err != nil {
log.Fatal(err.Error())
}

View File

@ -153,9 +153,7 @@ waitOnline:
},
},
}
// zeroSeconds adopts the default expiration time.
zeroSeconds := time.Duration(0 * time.Second)
authkey, _, err := tsClient.CreateKey(ctx, caps, zeroSeconds)
authkey, _, err := tsClient.CreateKey(ctx, caps)
if err != nil {
startlog.Fatalf("creating operator authkey: %v", err)
}
@ -289,7 +287,7 @@ type ServiceReconciler struct {
}
type tsClient interface {
CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error)
CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error)
DeleteDevice(ctx context.Context, id string) error
}
@ -596,8 +594,7 @@ func (a *ServiceReconciler) newAuthKey(ctx context.Context, tags []string) (stri
},
}
zeroDuration := time.Duration(0)
key, _, err := a.tsClient.CreateKey(ctx, caps, zeroDuration)
key, _, err := a.tsClient.CreateKey(ctx, caps)
if err != nil {
return "", err
}

View File

@ -807,14 +807,13 @@ type fakeTSClient struct {
deleted []string
}
func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities, expiry time.Duration) (string, *tailscale.Key, error) {
func (c *fakeTSClient) CreateKey(ctx context.Context, caps tailscale.KeyCapabilities) (string, *tailscale.Key, error) {
c.Lock()
defer c.Unlock()
c.keyRequests = append(c.keyRequests, caps)
k := &tailscale.Key{
ID: "key",
Created: time.Now(),
Expires: time.Now().Add(expiry),
Capabilities: caps,
}
return "secret-authkey", k, nil

View File

@ -1198,8 +1198,7 @@ func resolveAuthKey(ctx context.Context, v, tags string) (string, error) {
},
}
const defaultExpiry = 0
authkey, _, err := tsClient.CreateKey(ctx, caps, defaultExpiry)
authkey, _, err := tsClient.CreateKey(ctx, caps)
if err != nil {
return "", err
}