Skip to content

Commit 1099890

Browse files
authored
ensure final dot on node name (#2503)
* ensure final dot on node name This ensures that nodes which have a base domain set, will have a dot appended to their FQDN. Resolves: #2501 * improve OIDC TTL expire test Waiting a bit more than the TTL of the OIDC token seems to remove some flakiness of this test. This furthermore makes use of a go func safe buffer which should avoid race conditions.
1 parent 0d31347 commit 1099890

File tree

7 files changed

+67
-13
lines changed

7 files changed

+67
-13
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ The new policy can be used by setting the environment variable
8787
[#2493](https://github.com/juanfont/headscale/pull/2493)
8888
- If a OIDC provider doesn't include the `email_verified` claim in its ID
8989
tokens, Headscale will attempt to get it from the UserInfo endpoint.
90-
- Improve performance by only querying relevant nodes from the database for node updates [#2509](https://github.com/juanfont/headscale/pull/2509)
90+
- Improve performance by only querying relevant nodes from the database for node
91+
updates [#2509](https://github.com/juanfont/headscale/pull/2509)
92+
- node FQDNs in the netmap will now contain a dot (".") at the end. This aligns
93+
with behaviour of tailscale.com
94+
[#2503](https://github.com/juanfont/headscale/pull/2503)
9195

9296
## 0.25.1 (2025-02-25)
9397

hscontrol/mapper/tail_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,32 @@ func TestTailNode(t *testing.T) {
169169
},
170170
wantErr: false,
171171
},
172+
{
173+
name: "check-dot-suffix-on-node-name",
174+
node: &types.Node{
175+
GivenName: "minimal",
176+
Hostinfo: &tailcfg.Hostinfo{},
177+
},
178+
dnsConfig: &tailcfg.DNSConfig{},
179+
baseDomain: "example.com",
180+
want: &tailcfg.Node{
181+
// a node name should have a dot appended
182+
Name: "minimal.example.com.",
183+
StableID: "0",
184+
HomeDERP: 0,
185+
LegacyDERPString: "127.3.3.40:0",
186+
Hostinfo: hiview(tailcfg.Hostinfo{}),
187+
Tags: []string{},
188+
MachineAuthorized: true,
189+
190+
CapMap: tailcfg.NodeCapMap{
191+
tailcfg.CapabilityFileSharing: []tailcfg.RawMessage{},
192+
tailcfg.CapabilityAdmin: []tailcfg.RawMessage{},
193+
tailcfg.CapabilitySSH: []tailcfg.RawMessage{},
194+
},
195+
},
196+
wantErr: false,
197+
},
172198
// TODO: Add tests to check other aspects of the node conversion:
173199
// - With tags and policy
174200
// - dnsconfig and basedomain

hscontrol/types/node.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ func (node *Node) GetFQDN(baseDomain string) (string, error) {
364364

365365
if baseDomain != "" {
366366
hostname = fmt.Sprintf(
367-
"%s.%s",
367+
"%s.%s.",
368368
node.GivenName,
369369
baseDomain,
370370
)

hscontrol/types/node_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func TestNodeFQDN(t *testing.T) {
142142
},
143143
},
144144
domain: "example.com",
145-
want: "test.example.com",
145+
want: "test.example.com.",
146146
},
147147
{
148148
name: "all-set",
@@ -153,7 +153,7 @@ func TestNodeFQDN(t *testing.T) {
153153
},
154154
},
155155
domain: "example.com",
156-
want: "test.example.com",
156+
want: "test.example.com.",
157157
},
158158
{
159159
name: "no-given-name",
@@ -171,7 +171,7 @@ func TestNodeFQDN(t *testing.T) {
171171
GivenName: strings.Repeat("a", 256),
172172
},
173173
domain: "example.com",
174-
wantErr: fmt.Sprintf("failed to create valid FQDN (%s.example.com): hostname too long, cannot except 255 ASCII chars", strings.Repeat("a", 256)),
174+
wantErr: fmt.Sprintf("failed to create valid FQDN (%s.example.com.): hostname too long, cannot except 255 ASCII chars", strings.Repeat("a", 256)),
175175
},
176176
{
177177
name: "no-dnsconfig",
@@ -182,7 +182,7 @@ func TestNodeFQDN(t *testing.T) {
182182
},
183183
},
184184
domain: "example.com",
185-
want: "test.example.com",
185+
want: "test.example.com.",
186186
},
187187
}
188188

integration/auth_oidc_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,11 @@ func TestOIDCExpireNodesBasedOnTokenExpiry(t *testing.T) {
170170
t.Logf("%d successful pings out of %d (before expiry)", success, len(allClients)*len(allIps))
171171

172172
// This is not great, but this sadly is a time dependent test, so the
173-
// safe thing to do is wait out the whole TTL time before checking if
174-
// the clients have logged out. The Wait function can't do it itself
175-
// as it has an upper bound of 1 min.
176-
time.Sleep(shortAccessTTL)
173+
// safe thing to do is wait out the whole TTL time (and a bit more out
174+
// of safety reasons) before checking if the clients have logged out.
175+
// The Wait function can't do it itself as it has an upper bound of 1
176+
// min.
177+
time.Sleep(shortAccessTTL + 10*time.Second)
177178

178179
assertTailscaleNodesLogout(t, allClients)
179180
}

integration/dns_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestResolveMagicDNS(t *testing.T) {
4949
// It is safe to ignore this error as we handled it when caching it
5050
peerFQDN, _ := peer.FQDN()
5151

52-
assert.Equal(t, fmt.Sprintf("%s.headscale.net", peer.Hostname()), peerFQDN)
52+
assert.Equal(t, fmt.Sprintf("%s.headscale.net.", peer.Hostname()), peerFQDN)
5353

5454
command := []string{
5555
"tailscale",

integration/dockertestutil/execute.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"errors"
66
"fmt"
7+
"sync"
78
"time"
89

910
"github.com/ory/dockertest/v3"
@@ -29,14 +30,36 @@ func ExecuteCommandTimeout(timeout time.Duration) ExecuteCommandOption {
2930
})
3031
}
3132

33+
// buffer is a goroutine safe bytes.buffer
34+
type buffer struct {
35+
store bytes.Buffer
36+
mutex sync.Mutex
37+
}
38+
39+
// Write appends the contents of p to the buffer, growing the buffer as needed. It returns
40+
// the number of bytes written.
41+
func (b *buffer) Write(p []byte) (n int, err error) {
42+
b.mutex.Lock()
43+
defer b.mutex.Unlock()
44+
return b.store.Write(p)
45+
}
46+
47+
// String returns the contents of the unread portion of the buffer
48+
// as a string.
49+
func (b *buffer) String() string {
50+
b.mutex.Lock()
51+
defer b.mutex.Unlock()
52+
return b.store.String()
53+
}
54+
3255
func ExecuteCommand(
3356
resource *dockertest.Resource,
3457
cmd []string,
3558
env []string,
3659
options ...ExecuteCommandOption,
3760
) (string, string, error) {
38-
var stdout bytes.Buffer
39-
var stderr bytes.Buffer
61+
var stdout = buffer{}
62+
var stderr = buffer{}
4063

4164
execConfig := ExecuteCommandConfig{
4265
timeout: dockerExecuteTimeout,

0 commit comments

Comments
 (0)