mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-05 20:26:47 +02:00
cmd/tailscale/cli: allow tag without "tag:" prefix in 'tailscale up'
If a user passes --advertise-tags=foo,bar (with no colons in any
segment), automatically prepend "tag:" client-side so it goes on the
wire as "tag:foo,tag:bar". Segments that already contain a colon are
left untouched and must be fully-qualified ("tag:foo"), which keeps
the door open for future colon-bearing syntax.
This was originally added in cd07437ad (2020-10-28) and then reverted
in 1be01ddc6 (2020-11-10) over forward-compatibility concerns. But
then it was realized in 2026-04-29 that this was always safe for
future extensiblity anyway (tags can't contain colons-- tag:foo:bar is
invalid anyway, per the 2020 CheckTag restrictions). So if we wanted
to perhaps some hypothetical --advertise-tags=tagset:setfoo or "group:foo",
we'd still have syntax to do, as it can't conflict with tag:group:foo.
Avery signed off on this on Slack: "Ok, I withdraw my objection to
auto-qualifying tag names in advertise-tags and I hope I won't regret
it :)"
Updates #861
Change-Id: I06935b0d3ae909894c95c9c2e185b7d6a219ff32
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
f343b496c3
commit
815bb291c9
@ -779,11 +779,43 @@ func TestPrefsFromUpArgs(t *testing.T) {
|
||||
wantErr: `--exit-node-allow-lan-access can only be used with --exit-node`,
|
||||
},
|
||||
{
|
||||
name: "error_tag_prefix",
|
||||
name: "error_tag_bad_prefix",
|
||||
args: upArgsT{
|
||||
advertiseTags: "foo",
|
||||
advertiseTags: "notatag:foo",
|
||||
},
|
||||
wantErr: `tag: "notatag:foo": tags must start with 'tag:'`,
|
||||
},
|
||||
{
|
||||
name: "tag_auto_prefix",
|
||||
args: upArgsFromOSArgs("linux", "--advertise-tags=foo,bar"),
|
||||
want: &ipn.Prefs{
|
||||
ControlURL: ipn.DefaultControlURL,
|
||||
WantRunning: true,
|
||||
CorpDNS: true,
|
||||
AdvertiseTags: []string{"tag:foo", "tag:bar"},
|
||||
NoSNAT: false,
|
||||
NoStatefulFiltering: "true",
|
||||
NetfilterMode: preftype.NetfilterOn,
|
||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||
Check: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tag_mixed_prefix",
|
||||
args: upArgsFromOSArgs("linux", "--advertise-tags=tag:foo,bar"),
|
||||
want: &ipn.Prefs{
|
||||
ControlURL: ipn.DefaultControlURL,
|
||||
WantRunning: true,
|
||||
CorpDNS: true,
|
||||
AdvertiseTags: []string{"tag:foo", "tag:bar"},
|
||||
NoSNAT: false,
|
||||
NoStatefulFiltering: "true",
|
||||
NetfilterMode: preftype.NetfilterOn,
|
||||
AutoUpdate: ipn.AutoUpdatePrefs{
|
||||
Check: true,
|
||||
},
|
||||
},
|
||||
wantErr: `tag: "foo": tags must start with 'tag:'`,
|
||||
},
|
||||
{
|
||||
name: "error_long_hostname",
|
||||
|
||||
@ -113,7 +113,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet {
|
||||
upf.BoolVar(&upArgs.exitNodeAllowLANAccess, "exit-node-allow-lan-access", false, "Allow direct access to the local network when routing traffic via an exit node")
|
||||
upf.BoolVar(&upArgs.shieldsUp, "shields-up", false, "don't allow incoming connections")
|
||||
upf.BoolVar(&upArgs.runSSH, "ssh", false, "run an SSH server, permitting access per tailnet admin's declared policy")
|
||||
upf.StringVar(&upArgs.advertiseTags, "advertise-tags", "", "comma-separated ACL tags to request; each must start with \"tag:\" (e.g. \"tag:eng,tag:montreal,tag:ssh\")")
|
||||
upf.StringVar(&upArgs.advertiseTags, "advertise-tags", "", "comma-separated ACL tags to request (e.g. \"tag:eng,tag:montreal,tag:ssh\"); the \"tag:\" prefix is optional and added automatically when omitted (e.g. \"eng,montreal,ssh\")")
|
||||
upf.StringVar(&upArgs.hostname, "hostname", "", "hostname to use instead of the one provided by the OS")
|
||||
upf.StringVar(&upArgs.advertiseRoutes, "advertise-routes", "", "routes to advertise to other nodes (comma-separated, e.g. \"10.0.0.0/8,192.168.0.0/24\") or empty string to not advertise routes")
|
||||
upf.BoolVar(&upArgs.advertiseConnector, "advertise-connector", false, "advertise this node as an app connector")
|
||||
@ -309,9 +309,15 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
|
||||
var tags []string
|
||||
if upArgs.advertiseTags != "" {
|
||||
tags = strings.Split(upArgs.advertiseTags, ",")
|
||||
for _, tag := range tags {
|
||||
err := tailcfg.CheckTag(tag)
|
||||
if err != nil {
|
||||
for i, tag := range tags {
|
||||
// Allow users to omit the "tag:" prefix; if the tag has no
|
||||
// colon at all, add it for them. Tags with a colon must be
|
||||
// fully qualified ("tag:foo") and are validated as-is.
|
||||
if !strings.Contains(tag, ":") {
|
||||
tag = "tag:" + tag
|
||||
tags[i] = tag
|
||||
}
|
||||
if err := tailcfg.CheckTag(tag); err != nil {
|
||||
return nil, fmt.Errorf("tag: %q: %s", tag, err)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user