Compare the two sockets' configured paths as paths, not strings

The check that the control socket and the info API are not configured
on one path compared the strings, so a doubled or trailing separator, or
a case difference on windows where pipe names are case-insensitive, got
past it and the second bind failed with a message about another nebula.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Matt RichardsonandClaude Fable 5.1 committed 2026-10-21 12:27:12 -04:00
1 parent c5c826d163
commit fdfcf3bd17
2 files changed
+21 -1

No files matched your search

+15 -1
View File
@@ -4,6 +4,9 @@ import (
"context"
"errors"
"log/slog"
"path/filepath"
"runtime"
"strings"
"github.com/slackhq/nebula/commands"
"github.com/slackhq/nebula/config"
@@ -63,13 +66,24 @@ func sharedSocketPath(c *config.C) (string, bool) {
}
info, err := infoConfigFrom(c)
if err != nil || !info.Enabled || info.Path != ctl {
if err != nil || !info.Enabled || !samePath(info.Path, ctl) {
return "", false
}
return ctl, true
}
// samePath reports whether two configured socket paths name one node: cleaned, so a
// doubled separator or a trailing one does not hide the match, and on windows, where
// pipe names are case-insensitive, compared without case.
func samePath(a, b string) bool {
a, b = filepath.Clean(a), filepath.Clean(b)
if runtime.GOOS == "windows" {
return strings.EqualFold(a, b)
}
return a == b
}
// wireControl brings up the control socket and keeps it pointed at the configured path.
func wireControl(ctx context.Context, l *slog.Logger, c *config.C, reg *commands.Registry) *Server {
srv := NewServer(l, reg)
+6
View File
@@ -198,6 +198,12 @@ func TestWireRefusesOnePathForBothAPIs(t *testing.T) {
t.Cleanup(eps.Stop)
assert.Empty(t, eps.Control.Path(), "the control socket does not take the info API's path")
assert.Empty(t, eps.Info.Path(), "the info API does not take the control socket's path")
// The same node spelled differently is the same node.
doubled := filepath.Join(filepath.Dir(shared), "") + "//" + filepath.Base(shared)
require.NoError(t, c.ReloadConfigString(section(shared, doubled)).Err)
assert.Empty(t, eps.Control.Path())
assert.Empty(t, eps.Info.Path())
_, err := os.Stat(shared)
assert.True(t, os.IsNotExist(err), "neither side bound the shared path")