diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index d02db38f1..2fbee516a 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -65,15 +65,22 @@ func newFlagSet(name string) *flag.FlagSet { func CleanUpArgs(args []string) []string { out := make([]string, 0, len(args)) for _, arg := range args { + switch { // Rewrite --authkey to --auth-key, and --authkey=x to --auth-key=x, // and the same for the -authkey variant. - switch { case arg == "--authkey", arg == "-authkey": arg = "--auth-key" case strings.HasPrefix(arg, "--authkey="), strings.HasPrefix(arg, "-authkey="): - arg = strings.TrimLeft(arg, "-") - arg = strings.TrimPrefix(arg, "authkey=") - arg = "--auth-key=" + arg + _, val, _ := strings.Cut(arg, "=") + arg = "--auth-key=" + val + + // And the same, for posture-checking => report-posture + case arg == "--posture-checking", arg == "-posture-checking": + arg = "--report-posture" + case strings.HasPrefix(arg, "--posture-checking="), strings.HasPrefix(arg, "-posture-checking="): + _, val, _ := strings.Cut(arg, "=") + arg = "--report-posture=" + val + } out = append(out, arg) } diff --git a/cmd/tailscale/cli/cli_test.go b/cmd/tailscale/cli/cli_test.go index 4f6bdab2e..9aa3693fd 100644 --- a/cmd/tailscale/cli/cli_test.go +++ b/cmd/tailscale/cli/cli_test.go @@ -605,7 +605,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { want: "", }, { - name: "losing_posture_checking", + name: "losing_report_posture", flags: []string{"--accept-dns"}, curPrefs: &ipn.Prefs{ ControlURL: ipn.DefaultControlURL, @@ -615,7 +615,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { NetfilterMode: preftype.NetfilterOn, NoStatefulFiltering: opt.NewBool(true), }, - want: accidentalUpPrefix + " --accept-dns --posture-checking", + want: accidentalUpPrefix + " --accept-dns --report-posture", }, } for _, tt := range tests { @@ -1394,23 +1394,28 @@ var cmpIP = cmp.Comparer(func(a, b netip.Addr) bool { }) func TestCleanUpArgs(t *testing.T) { + type S = []string c := qt.New(t) tests := []struct { in []string want []string }{ - {in: []string{"something"}, want: []string{"something"}}, - {in: []string{}, want: []string{}}, - {in: []string{"--authkey=0"}, want: []string{"--auth-key=0"}}, - {in: []string{"a", "--authkey=1", "b"}, want: []string{"a", "--auth-key=1", "b"}}, - {in: []string{"a", "--auth-key=2", "b"}, want: []string{"a", "--auth-key=2", "b"}}, - {in: []string{"a", "-authkey=3", "b"}, want: []string{"a", "--auth-key=3", "b"}}, - {in: []string{"a", "-auth-key=4", "b"}, want: []string{"a", "-auth-key=4", "b"}}, - {in: []string{"a", "--authkey", "5", "b"}, want: []string{"a", "--auth-key", "5", "b"}}, - {in: []string{"a", "-authkey", "6", "b"}, want: []string{"a", "--auth-key", "6", "b"}}, - {in: []string{"a", "authkey", "7", "b"}, want: []string{"a", "authkey", "7", "b"}}, - {in: []string{"--authkeyexpiry", "8"}, want: []string{"--authkeyexpiry", "8"}}, - {in: []string{"--auth-key-expiry", "9"}, want: []string{"--auth-key-expiry", "9"}}, + {in: S{"something"}, want: S{"something"}}, + {in: S{}, want: S{}}, + {in: S{"--authkey=0"}, want: S{"--auth-key=0"}}, + {in: S{"a", "--authkey=1", "b"}, want: S{"a", "--auth-key=1", "b"}}, + {in: S{"a", "--auth-key=2", "b"}, want: S{"a", "--auth-key=2", "b"}}, + {in: S{"a", "-authkey=3", "b"}, want: S{"a", "--auth-key=3", "b"}}, + {in: S{"a", "-auth-key=4", "b"}, want: S{"a", "-auth-key=4", "b"}}, + {in: S{"a", "--authkey", "5", "b"}, want: S{"a", "--auth-key", "5", "b"}}, + {in: S{"a", "-authkey", "6", "b"}, want: S{"a", "--auth-key", "6", "b"}}, + {in: S{"a", "authkey", "7", "b"}, want: S{"a", "authkey", "7", "b"}}, + {in: S{"--authkeyexpiry", "8"}, want: S{"--authkeyexpiry", "8"}}, + {in: S{"--auth-key-expiry", "9"}, want: S{"--auth-key-expiry", "9"}}, + + {in: S{"--posture-checking"}, want: S{"--report-posture"}}, + {in: S{"-posture-checking"}, want: S{"--report-posture"}}, + {in: S{"--posture-checking=nein"}, want: S{"--report-posture=nein"}}, } for _, tt := range tests { diff --git a/cmd/tailscale/cli/set.go b/cmd/tailscale/cli/set.go index f4ea674ec..aa5966698 100644 --- a/cmd/tailscale/cli/set.go +++ b/cmd/tailscale/cli/set.go @@ -60,7 +60,7 @@ type setArgsT struct { forceDaemon bool updateCheck bool updateApply bool - postureChecking bool + reportPosture bool snat bool statefulFiltering bool netfilterMode string @@ -83,7 +83,7 @@ func newSetFlagSet(goos string, setArgs *setArgsT) *flag.FlagSet { setf.BoolVar(&setArgs.advertiseConnector, "advertise-connector", false, "offer to be an app connector for domain specific internet traffic for the tailnet") setf.BoolVar(&setArgs.updateCheck, "update-check", true, "notify about available Tailscale updates") setf.BoolVar(&setArgs.updateApply, "auto-update", false, "automatically update to the latest available version") - setf.BoolVar(&setArgs.postureChecking, "posture-checking", false, "allow management plane to gather device posture information") + setf.BoolVar(&setArgs.reportPosture, "report-posture", false, "allow management plane to gather device posture information") setf.BoolVar(&setArgs.runWebClient, "webclient", false, "expose the web interface for managing this node over Tailscale at port 5252") setf.StringVar(&setArgs.relayServerPort, "relay-server-port", "", hidden+"UDP port number (0 will pick a random unused port) for the relay server to bind to, on all interfaces, or empty string to disable relay server functionality") @@ -156,7 +156,7 @@ func runSet(ctx context.Context, args []string) (retErr error) { AppConnector: ipn.AppConnectorPrefs{ Advertise: setArgs.advertiseConnector, }, - PostureChecking: setArgs.postureChecking, + PostureChecking: setArgs.reportPosture, NoStatefulFiltering: opt.NewBool(!setArgs.statefulFiltering), }, } diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index d1e813b95..e4bb6f576 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -109,7 +109,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet { 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") upf.BoolVar(&upArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet") - upf.BoolVar(&upArgs.postureChecking, "posture-checking", false, hidden+"allow management plane to gather device posture information") + upf.BoolVar(&upArgs.postureChecking, "report-posture", false, hidden+"allow management plane to gather device posture information") if safesocket.GOOSUsesPeerCreds(goos) { upf.StringVar(&upArgs.opUser, "operator", "", "Unix username to allow to operate on tailscaled without sudo") @@ -772,7 +772,7 @@ func init() { addPrefFlagMapping("update-check", "AutoUpdate.Check") addPrefFlagMapping("auto-update", "AutoUpdate.Apply") addPrefFlagMapping("advertise-connector", "AppConnector") - addPrefFlagMapping("posture-checking", "PostureChecking") + addPrefFlagMapping("report-posture", "PostureChecking") addPrefFlagMapping("relay-server-port", "RelayServerPort") } @@ -1050,7 +1050,7 @@ func prefsToFlags(env upCheckEnv, prefs *ipn.Prefs) (flagVal map[string]any) { set(prefs.NetfilterMode.String()) case "unattended": set(prefs.ForceDaemon) - case "posture-checking": + case "report-posture": set(prefs.PostureChecking) } }) diff --git a/cmd/tailscale/cli/up_test.go b/cmd/tailscale/cli/up_test.go index 2c80ae94d..eb06f84dc 100644 --- a/cmd/tailscale/cli/up_test.go +++ b/cmd/tailscale/cli/up_test.go @@ -33,7 +33,7 @@ var validUpFlags = set.Of( "netfilter-mode", "nickname", "operator", - "posture-checking", + "report-posture", "qr", "reset", "shields-up", diff --git a/ipn/prefs.go b/ipn/prefs.go index 1c9d71d73..caf9ccfc3 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -235,6 +235,11 @@ type Prefs struct { // PostureChecking enables the collection of information used for device // posture checks. + // + // Note: this should be named ReportPosture, but it was shipped as + // PostureChecking in some early releases and this JSON field is written to + // disk, so we just keep its old name. (akin to CorpDNS which is an internal + // pref name that doesn't match the public interface) PostureChecking bool // NetfilterKind specifies what netfilter implementation to use.