Просмотр исходного кода

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>
Matt Richardson 12 часов назад
Родитель
Сommit
dbca7e5e0d
2 измененных файлов с 21 добавлено и 1 удалено
  1. 15 1
      localapi/wire.go
  2. 6 0
      localapi/wire_test.go

+ 15 - 1
localapi/wire.go

@@ -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 - 0
localapi/wire_test.go

@@ -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")