ipn: introduce app connector advertisement preference and flags

Introduce a preference structure to store the setting for app connector
advertisement.

Introduce the associated flags:

  tailscale up --advertise-connector{=true,=false}
  tailscale set --advertise-connector{=true,=false}

```
% tailscale set --advertise-connector=false
% tailscale debug prefs | jq .AppConnector.Advertise
false
% tailscale set --advertise-connector=true
% tailscale debug prefs | jq .AppConnector.Advertise
true
% tailscale up --advertise-connector=false
% tailscale debug prefs | jq .AppConnector.Advertise
false
% tailscale up --advertise-connector=true
% tailscale debug prefs | jq .AppConnector.Advertise
true
```

Updates tailscale/corp#15437

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker
2023-10-26 15:55:32 -07:00
committed by James Tucker
parent 09fcbae900
commit ca4c940a4d
7 changed files with 108 additions and 0 deletions
+44
View File
@@ -893,6 +893,7 @@ func TestUpdatePrefs(t *testing.T) {
AdvertiseRoutesSet: true,
AdvertiseTagsSet: true,
AllowSingleHostsSet: true,
AppConnectorSet: true,
ControlURLSet: true,
CorpDNSSet: true,
ExitNodeAllowLANAccessSet: true,
@@ -1131,6 +1132,49 @@ func TestUpdatePrefs(t *testing.T) {
wantJustEditMP: nil,
env: upCheckEnv{backendState: "Running"},
},
{
name: "advertise_connector",
flags: []string{"--advertise-connector"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
},
wantJustEditMP: &ipn.MaskedPrefs{
AppConnectorSet: true,
WantRunningSet: true,
},
env: upCheckEnv{backendState: "Running"},
checkUpdatePrefsMutations: func(t *testing.T, newPrefs *ipn.Prefs) {
if !newPrefs.AppConnector.Advertise {
t.Errorf("prefs.AppConnector.Advertise not set")
}
},
},
{
name: "no_advertise_connector",
flags: []string{"--advertise-connector=false"},
curPrefs: &ipn.Prefs{
ControlURL: ipn.DefaultControlURL,
AllowSingleHosts: true,
CorpDNS: true,
NetfilterMode: preftype.NetfilterOn,
AppConnector: ipn.AppConnectorPrefs{
Advertise: true,
},
},
wantJustEditMP: &ipn.MaskedPrefs{
AppConnectorSet: true,
WantRunningSet: true,
},
env: upCheckEnv{backendState: "Running"},
checkUpdatePrefsMutations: func(t *testing.T, newPrefs *ipn.Prefs) {
if newPrefs.AppConnector.Advertise {
t.Errorf("prefs.AppConnector.Advertise not unset")
}
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+5
View File
@@ -45,6 +45,7 @@ type setArgsT struct {
hostname string
advertiseRoutes string
advertiseDefaultRoute bool
advertiseConnector bool
opUser string
acceptedRisks string
profileName string
@@ -67,6 +68,7 @@ func newSetFlagSet(goos string, setArgs *setArgsT) *flag.FlagSet {
setf.StringVar(&setArgs.hostname, "hostname", "", "hostname to use instead of the one provided by the OS")
setf.StringVar(&setArgs.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")
setf.BoolVar(&setArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet")
setf.BoolVar(&setArgs.advertiseConnector, "advertise-connector", false, "offer to be an exit node for 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, "HIDDEN: allow management plane to gather device posture information")
@@ -113,6 +115,9 @@ func runSet(ctx context.Context, args []string) (retErr error) {
Check: setArgs.updateCheck,
Apply: setArgs.updateApply,
},
AppConnector: ipn.AppConnectorPrefs{
Advertise: setArgs.advertiseConnector,
},
PostureChecking: setArgs.postureChecking,
},
}
+6
View File
@@ -113,6 +113,7 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet {
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.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")
upf.BoolVar(&upArgs.advertiseDefaultRoute, "advertise-exit-node", false, "offer to be an exit node for internet traffic for the tailnet")
if safesocket.GOOSUsesPeerCreds(goos) {
@@ -165,6 +166,7 @@ type upArgsT struct {
advertiseRoutes string
advertiseDefaultRoute bool
advertiseTags string
advertiseConnector bool
snat bool
netfilterMode string
authKeyOrFile string // "secret" or "file:/path/to/secret"
@@ -283,6 +285,7 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
prefs.ForceDaemon = upArgs.forceDaemon
prefs.OperatorUser = upArgs.opUser
prefs.ProfileName = upArgs.profileName
prefs.AppConnector.Advertise = upArgs.advertiseConnector
if goos == "linux" {
prefs.NoSNAT = !upArgs.snat
@@ -730,6 +733,7 @@ func init() {
addPrefFlagMapping("nickname", "ProfileName")
addPrefFlagMapping("update-check", "AutoUpdate")
addPrefFlagMapping("auto-update", "AutoUpdate")
addPrefFlagMapping("advertise-connector", "AppConnector")
addPrefFlagMapping("posture-checking", "PostureChecking")
}
@@ -965,6 +969,8 @@ func prefsToFlags(env upCheckEnv, prefs *ipn.Prefs) (flagVal map[string]any) {
set(sb.String())
case "advertise-exit-node":
set(hasExitNodeRoutes(prefs.AdvertiseRoutes))
case "advertise-connector":
set(prefs.AppConnector.Advertise)
case "snat-subnet-routes":
set(!prefs.NoSNAT)
case "netfilter-mode":