diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 462b18b6e..06d9b5ff8 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -668,7 +668,7 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE if err != nil { return err } - authKey, err = resolveAuthKey(ctx, authKey) + authKey, err = resolveAuthKey(ctx, authKey, upArgs.advertiseTags) if err != nil { return err } @@ -1121,19 +1121,23 @@ func init() { // resolveAuthKey either returns v unchanged (in the common case) or, if it // starts with "tskey-client-" (as Tailscale OAuth secrets do) parses it like // -// tskey-client-xxxx[?ephemeral=false&tags=foo,bar&preauthorized=BOOL&baseURL=...] +// tskey-client-xxxx[?ephemeral=false&bar&preauthorized=BOOL&baseURL=...] // // and does the OAuth2 dance to get and return an authkey. The "ephemeral" // property defaults to true if unspecified. The "preauthorized" defaults to -// false. The "baseURL" defaults to -// https://api.tailscale.com. -func resolveAuthKey(ctx context.Context, v string) (string, error) { +// false. The "baseURL" defaults to https://api.tailscale.com. +// The passed in tags are required, and must be non-empty. These will be +// set on the authkey generated by the OAuth2 dance. +func resolveAuthKey(ctx context.Context, v, tags string) (string, error) { if !strings.HasPrefix(v, "tskey-client-") { return v, nil } if !envknob.Bool("TS_EXPERIMENT_OAUTH_AUTHKEY") { return "", errors.New("oauth authkeys are in experimental status") } + if tags == "" { + return "", errors.New("oauth authkeys require --advertise-tags") + } clientSecret, named, _ := strings.Cut(v, "?") attrs, err := url.ParseQuery(named) @@ -1142,7 +1146,7 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { } for k := range attrs { switch k { - case "ephemeral", "preauthorized", "tags", "baseURL": + case "ephemeral", "preauthorized", "baseURL": default: return "", fmt.Errorf("unknown attribute %q", k) } @@ -1166,10 +1170,6 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { if err != nil { return "", err } - var tags []string - if v := attrs.Get("tags"); v != "" { - tags = strings.Split(v, ",") - } baseURL := "https://api.tailscale.com" if v := attrs.Get("baseURL"); v != "" { @@ -1193,7 +1193,7 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { Reusable: false, Ephemeral: ephemeral, Preauthorized: preauth, - Tags: tags, + Tags: strings.Split(tags, ","), }, }, }