Skip to content

Commit f97aa98

Browse files
committed
Merge tag 'v1.84.2' into sunos-1.84
Release 1.84.2
2 parents e2bc1b0 + 5f702f4 commit f97aa98

File tree

6 files changed

+332
-101
lines changed

6 files changed

+332
-101
lines changed

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.84.1
1+
1.84.2

cmd/containerboot/main_test.go

Lines changed: 157 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -41,97 +41,6 @@ import (
4141
"tailscale.com/types/ptr"
4242
)
4343

44-
// testEnv represents the environment needed for a single sub-test so that tests
45-
// can run in parallel.
46-
type testEnv struct {
47-
kube *kubeServer // Fake kube server.
48-
lapi *localAPI // Local TS API server.
49-
d string // Temp dir for the specific test.
50-
argFile string // File with commands test_tailscale{,d}.sh were invoked with.
51-
runningSockPath string // Path to the running tailscaled socket.
52-
localAddrPort int // Port for the containerboot HTTP server.
53-
healthAddrPort int // Port for the (deprecated) containerboot health server.
54-
}
55-
56-
func newTestEnv(t *testing.T) testEnv {
57-
d := t.TempDir()
58-
59-
lapi := localAPI{FSRoot: d}
60-
if err := lapi.Start(); err != nil {
61-
t.Fatal(err)
62-
}
63-
t.Cleanup(lapi.Close)
64-
65-
kube := kubeServer{FSRoot: d}
66-
kube.Start(t)
67-
t.Cleanup(kube.Close)
68-
69-
tailscaledConf := &ipn.ConfigVAlpha{AuthKey: ptr.To("foo"), Version: "alpha0"}
70-
serveConf := ipn.ServeConfig{TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}}}
71-
egressCfg := egressSvcConfig("foo", "foo.tailnetxyz.ts.net")
72-
73-
dirs := []string{
74-
"var/lib",
75-
"usr/bin",
76-
"tmp",
77-
"dev/net",
78-
"proc/sys/net/ipv4",
79-
"proc/sys/net/ipv6/conf/all",
80-
"etc/tailscaled",
81-
}
82-
for _, path := range dirs {
83-
if err := os.MkdirAll(filepath.Join(d, path), 0700); err != nil {
84-
t.Fatal(err)
85-
}
86-
}
87-
files := map[string][]byte{
88-
"usr/bin/tailscaled": fakeTailscaled,
89-
"usr/bin/tailscale": fakeTailscale,
90-
"usr/bin/iptables": fakeTailscale,
91-
"usr/bin/ip6tables": fakeTailscale,
92-
"dev/net/tun": []byte(""),
93-
"proc/sys/net/ipv4/ip_forward": []byte("0"),
94-
"proc/sys/net/ipv6/conf/all/forwarding": []byte("0"),
95-
"etc/tailscaled/cap-95.hujson": mustJSON(t, tailscaledConf),
96-
"etc/tailscaled/serve-config.json": mustJSON(t, serveConf),
97-
filepath.Join("etc/tailscaled/", egressservices.KeyEgressServices): mustJSON(t, egressCfg),
98-
filepath.Join("etc/tailscaled/", egressservices.KeyHEPPings): []byte("4"),
99-
}
100-
for path, content := range files {
101-
// Making everything executable is a little weird, but the
102-
// stuff that doesn't need to be executable doesn't care if we
103-
// do make it executable.
104-
if err := os.WriteFile(filepath.Join(d, path), content, 0700); err != nil {
105-
t.Fatal(err)
106-
}
107-
}
108-
109-
argFile := filepath.Join(d, "args")
110-
runningSockPath := filepath.Join(d, "tmp/tailscaled.sock")
111-
var localAddrPort, healthAddrPort int
112-
for _, p := range []*int{&localAddrPort, &healthAddrPort} {
113-
ln, err := net.Listen("tcp", ":0")
114-
if err != nil {
115-
t.Fatalf("Failed to open listener: %v", err)
116-
}
117-
if err := ln.Close(); err != nil {
118-
t.Fatalf("Failed to close listener: %v", err)
119-
}
120-
port := ln.Addr().(*net.TCPAddr).Port
121-
*p = port
122-
}
123-
124-
return testEnv{
125-
kube: &kube,
126-
lapi: &lapi,
127-
d: d,
128-
argFile: argFile,
129-
runningSockPath: runningSockPath,
130-
localAddrPort: localAddrPort,
131-
healthAddrPort: healthAddrPort,
132-
}
133-
}
134-
13544
func TestContainerBoot(t *testing.T) {
13645
boot := filepath.Join(t.TempDir(), "containerboot")
13746
if err := exec.Command("go", "build", "-ldflags", "-X main.testSleepDuration=1ms", "-o", boot, "tailscale.com/cmd/containerboot").Run(); err != nil {
@@ -515,6 +424,37 @@ func TestContainerBoot(t *testing.T) {
515424
},
516425
}
517426
},
427+
"auth_key_once_extra_args_override_dns": func(env *testEnv) testCase {
428+
return testCase{
429+
Env: map[string]string{
430+
"TS_AUTHKEY": "tskey-key",
431+
"TS_AUTH_ONCE": "true",
432+
"TS_ACCEPT_DNS": "false",
433+
"TS_EXTRA_ARGS": "--accept-dns",
434+
},
435+
Phases: []phase{
436+
{
437+
WantCmds: []string{
438+
"/usr/bin/tailscaled --socket=/tmp/tailscaled.sock --state=mem: --statedir=/tmp --tun=userspace-networking",
439+
},
440+
},
441+
{
442+
Notify: &ipn.Notify{
443+
State: ptr.To(ipn.NeedsLogin),
444+
},
445+
WantCmds: []string{
446+
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=true --authkey=tskey-key",
447+
},
448+
},
449+
{
450+
Notify: runningNotify,
451+
WantCmds: []string{
452+
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock set --accept-dns=true",
453+
},
454+
},
455+
},
456+
}
457+
},
518458
"kube_storage": func(env *testEnv) testCase {
519459
return testCase{
520460
Env: map[string]string{
@@ -766,6 +706,41 @@ func TestContainerBoot(t *testing.T) {
766706
},
767707
}
768708
},
709+
"extra_args_accept_dns": func(env *testEnv) testCase {
710+
return testCase{
711+
Env: map[string]string{
712+
"TS_EXTRA_ARGS": "--accept-dns",
713+
},
714+
Phases: []phase{
715+
{
716+
WantCmds: []string{
717+
"/usr/bin/tailscaled --socket=/tmp/tailscaled.sock --state=mem: --statedir=/tmp --tun=userspace-networking",
718+
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=true",
719+
},
720+
}, {
721+
Notify: runningNotify,
722+
},
723+
},
724+
}
725+
},
726+
"extra_args_accept_dns_overrides_env_var": func(env *testEnv) testCase {
727+
return testCase{
728+
Env: map[string]string{
729+
"TS_ACCEPT_DNS": "true", // Overridden by TS_EXTRA_ARGS.
730+
"TS_EXTRA_ARGS": "--accept-dns=false",
731+
},
732+
Phases: []phase{
733+
{
734+
WantCmds: []string{
735+
"/usr/bin/tailscaled --socket=/tmp/tailscaled.sock --state=mem: --statedir=/tmp --tun=userspace-networking",
736+
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false",
737+
},
738+
}, {
739+
Notify: runningNotify,
740+
},
741+
},
742+
}
743+
},
769744
"hostname": func(env *testEnv) testCase {
770745
return testCase{
771746
Env: map[string]string{
@@ -1604,3 +1579,94 @@ func egressSvcConfig(name, fqdn string) egressservices.Configs {
16041579
},
16051580
}
16061581
}
1582+
1583+
// testEnv represents the environment needed for a single sub-test so that tests
1584+
// can run in parallel.
1585+
type testEnv struct {
1586+
kube *kubeServer // Fake kube server.
1587+
lapi *localAPI // Local TS API server.
1588+
d string // Temp dir for the specific test.
1589+
argFile string // File with commands test_tailscale{,d}.sh were invoked with.
1590+
runningSockPath string // Path to the running tailscaled socket.
1591+
localAddrPort int // Port for the containerboot HTTP server.
1592+
healthAddrPort int // Port for the (deprecated) containerboot health server.
1593+
}
1594+
1595+
func newTestEnv(t *testing.T) testEnv {
1596+
d := t.TempDir()
1597+
1598+
lapi := localAPI{FSRoot: d}
1599+
if err := lapi.Start(); err != nil {
1600+
t.Fatal(err)
1601+
}
1602+
t.Cleanup(lapi.Close)
1603+
1604+
kube := kubeServer{FSRoot: d}
1605+
kube.Start(t)
1606+
t.Cleanup(kube.Close)
1607+
1608+
tailscaledConf := &ipn.ConfigVAlpha{AuthKey: ptr.To("foo"), Version: "alpha0"}
1609+
serveConf := ipn.ServeConfig{TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}}}
1610+
egressCfg := egressSvcConfig("foo", "foo.tailnetxyz.ts.net")
1611+
1612+
dirs := []string{
1613+
"var/lib",
1614+
"usr/bin",
1615+
"tmp",
1616+
"dev/net",
1617+
"proc/sys/net/ipv4",
1618+
"proc/sys/net/ipv6/conf/all",
1619+
"etc/tailscaled",
1620+
}
1621+
for _, path := range dirs {
1622+
if err := os.MkdirAll(filepath.Join(d, path), 0700); err != nil {
1623+
t.Fatal(err)
1624+
}
1625+
}
1626+
files := map[string][]byte{
1627+
"usr/bin/tailscaled": fakeTailscaled,
1628+
"usr/bin/tailscale": fakeTailscale,
1629+
"usr/bin/iptables": fakeTailscale,
1630+
"usr/bin/ip6tables": fakeTailscale,
1631+
"dev/net/tun": []byte(""),
1632+
"proc/sys/net/ipv4/ip_forward": []byte("0"),
1633+
"proc/sys/net/ipv6/conf/all/forwarding": []byte("0"),
1634+
"etc/tailscaled/cap-95.hujson": mustJSON(t, tailscaledConf),
1635+
"etc/tailscaled/serve-config.json": mustJSON(t, serveConf),
1636+
filepath.Join("etc/tailscaled/", egressservices.KeyEgressServices): mustJSON(t, egressCfg),
1637+
filepath.Join("etc/tailscaled/", egressservices.KeyHEPPings): []byte("4"),
1638+
}
1639+
for path, content := range files {
1640+
// Making everything executable is a little weird, but the
1641+
// stuff that doesn't need to be executable doesn't care if we
1642+
// do make it executable.
1643+
if err := os.WriteFile(filepath.Join(d, path), content, 0700); err != nil {
1644+
t.Fatal(err)
1645+
}
1646+
}
1647+
1648+
argFile := filepath.Join(d, "args")
1649+
runningSockPath := filepath.Join(d, "tmp/tailscaled.sock")
1650+
var localAddrPort, healthAddrPort int
1651+
for _, p := range []*int{&localAddrPort, &healthAddrPort} {
1652+
ln, err := net.Listen("tcp", ":0")
1653+
if err != nil {
1654+
t.Fatalf("Failed to open listener: %v", err)
1655+
}
1656+
if err := ln.Close(); err != nil {
1657+
t.Fatalf("Failed to close listener: %v", err)
1658+
}
1659+
port := ln.Addr().(*net.TCPAddr).Port
1660+
*p = port
1661+
}
1662+
1663+
return testEnv{
1664+
kube: &kube,
1665+
lapi: &lapi,
1666+
d: d,
1667+
argFile: argFile,
1668+
runningSockPath: runningSockPath,
1669+
localAddrPort: localAddrPort,
1670+
healthAddrPort: healthAddrPort,
1671+
}
1672+
}

cmd/containerboot/settings.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,69 @@ func configFromEnv() (*settings, error) {
147147
}
148148
}
149149

150+
// See https://github.com/tailscale/tailscale/issues/16108 for context- we
151+
// do this to preserve the previous behaviour where --accept-dns could be
152+
// set either via TS_ACCEPT_DNS or TS_EXTRA_ARGS.
153+
acceptDNS := cfg.AcceptDNS != nil && *cfg.AcceptDNS
154+
tsExtraArgs, acceptDNSNew := parseAcceptDNS(cfg.ExtraArgs, acceptDNS)
155+
cfg.ExtraArgs = tsExtraArgs
156+
if acceptDNS != acceptDNSNew {
157+
cfg.AcceptDNS = &acceptDNSNew
158+
}
159+
150160
if err := cfg.validate(); err != nil {
151161
return nil, fmt.Errorf("invalid configuration: %v", err)
152162
}
153163
return cfg, nil
154164
}
155165

166+
// parseAcceptDNS parses any values for Tailscale --accept-dns flag set via
167+
// TS_ACCEPT_DNS and TS_EXTRA_ARGS env vars. If TS_EXTRA_ARGS contains
168+
// --accept-dns flag, override the acceptDNS value with the one from
169+
// TS_EXTRA_ARGS.
170+
// The value of extraArgs can be empty string or one or more whitespace-separate
171+
// key value pairs for 'tailscale up' command. The value for boolean flags can
172+
// be omitted (default to true).
173+
func parseAcceptDNS(extraArgs string, acceptDNS bool) (string, bool) {
174+
if !strings.Contains(extraArgs, "--accept-dns") {
175+
return extraArgs, acceptDNS
176+
}
177+
// TODO(irbekrm): we should validate that TS_EXTRA_ARGS contains legit
178+
// 'tailscale up' flag values separated by whitespace.
179+
argsArr := strings.Fields(extraArgs)
180+
i := -1
181+
for key, val := range argsArr {
182+
if strings.HasPrefix(val, "--accept-dns") {
183+
i = key
184+
break
185+
}
186+
}
187+
if i == -1 {
188+
return extraArgs, acceptDNS
189+
}
190+
a := strings.TrimSpace(argsArr[i])
191+
var acceptDNSFromExtraArgsS string
192+
keyval := strings.Split(a, "=")
193+
if len(keyval) == 2 {
194+
acceptDNSFromExtraArgsS = keyval[1]
195+
} else if len(keyval) == 1 && keyval[0] == "--accept-dns" {
196+
// If the arg is just --accept-dns, we assume it means true.
197+
acceptDNSFromExtraArgsS = "true"
198+
} else {
199+
log.Printf("TS_EXTRA_ARGS contains --accept-dns, but it is not in the expected format --accept-dns=<true|false>, ignoring it")
200+
return extraArgs, acceptDNS
201+
}
202+
acceptDNSFromExtraArgs, err := strconv.ParseBool(acceptDNSFromExtraArgsS)
203+
if err != nil {
204+
log.Printf("TS_EXTRA_ARGS contains --accept-dns=%q, which is not a valid boolean value, ignoring it", acceptDNSFromExtraArgsS)
205+
return extraArgs, acceptDNS
206+
}
207+
if acceptDNSFromExtraArgs != acceptDNS {
208+
log.Printf("TS_EXTRA_ARGS contains --accept-dns=%v, which overrides TS_ACCEPT_DNS=%v", acceptDNSFromExtraArgs, acceptDNS)
209+
}
210+
return strings.Join(append(argsArr[:i], argsArr[i+1:]...), " "), acceptDNSFromExtraArgs
211+
}
212+
156213
func (s *settings) validate() error {
157214
if s.TailscaledConfigFilePath != "" {
158215
dir, file := path.Split(s.TailscaledConfigFilePath)

0 commit comments

Comments
 (0)